Merge "Introduce early exit path for non resource path." into oc-dev
diff --git a/api/current.txt b/api/current.txt
index 82b6ae9..6023aab 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -206,9 +206,6 @@
 
   public static final class R.attr {
     ctor public R.attr();
-    field public static final int __removed1 = 16844099; // 0x1010543
-    field public static final int __removed2 = 16844104; // 0x1010548
-    field public static final int __removed3 = 16844116; // 0x1010554
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -273,7 +270,7 @@
     field public static final int allowTaskReparenting = 16843268; // 0x1010204
     field public static final int allowUndo = 16843999; // 0x10104df
     field public static final int alpha = 16843551; // 0x101031f
-    field public static final int alphabeticModifiers = 16844112; // 0x1010550
+    field public static final int alphabeticModifiers = 16844110; // 0x101054e
     field public static final int alphabeticShortcut = 16843235; // 0x10101e3
     field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
     field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
@@ -293,7 +290,7 @@
     field public static final int anyDensity = 16843372; // 0x101026c
     field public static final int apduServiceBanner = 16843757; // 0x10103ed
     field public static final int apiKey = 16843281; // 0x1010211
-    field public static final int appCategory = 16844102; // 0x1010546
+    field public static final int appCategory = 16844101; // 0x1010545
     field public static final int author = 16843444; // 0x10102b4
     field public static final int authorities = 16842776; // 0x1010018
     field public static final int autoAdvanceViewId = 16843535; // 0x101030f
@@ -301,7 +298,7 @@
     field public static final int autoLink = 16842928; // 0x10100b0
     field public static final int autoMirrored = 16843754; // 0x10103ea
     field public static final int autoRemoveFromRecents = 16843847; // 0x1010447
-    field public static final int autoSizeMaxTextSize = 16844103; // 0x1010547
+    field public static final int autoSizeMaxTextSize = 16844102; // 0x1010546
     field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
     field public static final int autoSizePresetSizes = 16844087; // 0x1010537
     field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
@@ -310,8 +307,8 @@
     field public static final deprecated int autoText = 16843114; // 0x101016a
     field public static final int autoUrlDetect = 16843404; // 0x101028c
     field public static final int autoVerify = 16844014; // 0x10104ee
-    field public static final int autofillHints = 16844121; // 0x1010559
-    field public static final int autofilledHighlight = 16844139; // 0x101056b
+    field public static final int autofillHints = 16844118; // 0x1010556
+    field public static final int autofilledHighlight = 16844136; // 0x1010568
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -361,7 +358,7 @@
     field public static final int canRecord = 16844060; // 0x101051c
     field public static final deprecated int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
     field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
-    field public static final int canRequestFingerprintGestures = 16844111; // 0x101054f
+    field public static final int canRequestFingerprintGestures = 16844109; // 0x101054d
     field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
     field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
     field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
@@ -373,7 +370,7 @@
     field public static final int centerMedium = 16842959; // 0x10100cf
     field public static final int centerX = 16843170; // 0x10101a2
     field public static final int centerY = 16843171; // 0x10101a3
-    field public static final int certDigest = 16844106; // 0x101054a
+    field public static final int certDigest = 16844104; // 0x1010548
     field public static final int checkBoxPreferenceStyle = 16842895; // 0x101008f
     field public static final int checkMark = 16843016; // 0x1010108
     field public static final int checkMarkTint = 16843943; // 0x10104a7
@@ -412,12 +409,12 @@
     field public static final int colorControlHighlight = 16843820; // 0x101042c
     field public static final int colorControlNormal = 16843817; // 0x1010429
     field public static final int colorEdgeEffect = 16843982; // 0x10104ce
-    field public static final int colorError = 16844100; // 0x1010544
+    field public static final int colorError = 16844099; // 0x1010543
     field public static final int colorFocusedHighlight = 16843663; // 0x101038f
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
     field public static final int colorLongPressedHighlight = 16843662; // 0x101038e
-    field public static final int colorMode = 16844108; // 0x101054c
+    field public static final int colorMode = 16844106; // 0x101054a
     field public static final int colorMultiSelectHighlight = 16843665; // 0x1010391
     field public static final int colorPressedHighlight = 16843661; // 0x101038d
     field public static final int colorPrimary = 16843827; // 0x1010433
@@ -470,7 +467,7 @@
     field public static final deprecated int dayOfWeekBackground = 16843924; // 0x1010494
     field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
     field public static final int debuggable = 16842767; // 0x101000f
-    field public static final int defaultFocusHighlightEnabled = 16844133; // 0x1010565
+    field public static final int defaultFocusHighlightEnabled = 16844130; // 0x1010562
     field public static final int defaultHeight = 16844021; // 0x10104f5
     field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
     field public static final int defaultValue = 16843245; // 0x10101ed
@@ -602,15 +599,15 @@
     field public static final int flipInterval = 16843129; // 0x1010179
     field public static final int focusable = 16842970; // 0x10100da
     field public static final int focusableInTouchMode = 16842971; // 0x10100db
-    field public static final int focusedByDefault = 16844101; // 0x1010545
+    field public static final int focusedByDefault = 16844100; // 0x1010544
     field public static final deprecated int focusedMonthDateColor = 16843587; // 0x1010343
     field public static final int font = 16844082; // 0x1010532
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
-    field public static final int fontProviderAuthority = 16844114; // 0x1010552
-    field public static final int fontProviderCerts = 16844128; // 0x1010560
-    field public static final int fontProviderPackage = 16844122; // 0x101055a
-    field public static final int fontProviderQuery = 16844115; // 0x1010553
+    field public static final int fontProviderAuthority = 16844112; // 0x1010550
+    field public static final int fontProviderCerts = 16844125; // 0x101055d
+    field public static final int fontProviderPackage = 16844119; // 0x1010557
+    field public static final int fontProviderQuery = 16844113; // 0x1010551
     field public static final int fontStyle = 16844095; // 0x101053f
     field public static final int fontWeight = 16844083; // 0x1010533
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
@@ -696,9 +693,9 @@
     field public static final int hyphenationFrequency = 16843998; // 0x10104de
     field public static final int icon = 16842754; // 0x1010002
     field public static final int iconPreview = 16843337; // 0x1010249
-    field public static final int iconSpaceReserved = 16844132; // 0x1010564
-    field public static final int iconTint = 16844129; // 0x1010561
-    field public static final int iconTintMode = 16844130; // 0x1010562
+    field public static final int iconSpaceReserved = 16844129; // 0x1010561
+    field public static final int iconTint = 16844126; // 0x101055e
+    field public static final int iconTintMode = 16844127; // 0x101055f
     field public static final int iconifiedByDefault = 16843514; // 0x10102fa
     field public static final int id = 16842960; // 0x10100d0
     field public static final int ignoreGravity = 16843263; // 0x10101ff
@@ -715,7 +712,7 @@
     field public static final int imeSubtypeMode = 16843501; // 0x10102ed
     field public static final int immersive = 16843456; // 0x10102c0
     field public static final int importantForAccessibility = 16843690; // 0x10103aa
-    field public static final int importantForAutofill = 16844123; // 0x101055b
+    field public static final int importantForAutofill = 16844120; // 0x1010558
     field public static final int inAnimation = 16843127; // 0x1010177
     field public static final int includeFontPadding = 16843103; // 0x101015f
     field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -750,21 +747,21 @@
     field public static final int isAsciiCapable = 16843753; // 0x10103e9
     field public static final int isAuxiliary = 16843647; // 0x101037f
     field public static final int isDefault = 16843297; // 0x1010221
-    field public static final int isFeatureSplit = 16844126; // 0x101055e
+    field public static final int isFeatureSplit = 16844123; // 0x101055b
     field public static final int isGame = 16843764; // 0x10103f4
     field public static final int isIndicator = 16843079; // 0x1010147
     field public static final int isModifier = 16843334; // 0x1010246
     field public static final int isRepeatable = 16843336; // 0x1010248
     field public static final int isScrollContainer = 16843342; // 0x101024e
-    field public static final int isStatic = 16844125; // 0x101055d
+    field public static final int isStatic = 16844122; // 0x101055a
     field public static final int isSticky = 16843335; // 0x1010247
     field public static final int isolatedProcess = 16843689; // 0x10103a9
-    field public static final int isolatedSplits = 16844109; // 0x101054d
+    field public static final int isolatedSplits = 16844107; // 0x101054b
     field public static final int itemBackground = 16843056; // 0x1010130
     field public static final int itemIconDisabledAlpha = 16843057; // 0x1010131
     field public static final int itemPadding = 16843565; // 0x101032d
     field public static final int itemTextAppearance = 16843052; // 0x101012c
-    field public static final int justificationMode = 16844138; // 0x101056a
+    field public static final int justificationMode = 16844135; // 0x1010567
     field public static final int keepScreenOn = 16843286; // 0x1010216
     field public static final int key = 16843240; // 0x10101e8
     field public static final int keyBackground = 16843315; // 0x1010233
@@ -881,7 +878,7 @@
     field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
     field public static final int matchOrder = 16843855; // 0x101044f
     field public static final int max = 16843062; // 0x1010136
-    field public static final int maxAspectRatio = 16844131; // 0x1010563
+    field public static final int maxAspectRatio = 16844128; // 0x1010560
     field public static final int maxButtonHeight = 16844029; // 0x10104fd
     field public static final int maxDate = 16843584; // 0x1010340
     field public static final int maxEms = 16843095; // 0x1010157
@@ -944,7 +941,7 @@
     field public static final int numbersSelectorColor = 16843939; // 0x10104a3
     field public static final int numbersTextColor = 16843937; // 0x10104a1
     field public static final deprecated int numeric = 16843109; // 0x1010165
-    field public static final int numericModifiers = 16844113; // 0x1010551
+    field public static final int numericModifiers = 16844111; // 0x101054f
     field public static final int numericShortcut = 16843236; // 0x10101e4
     field public static final int offset = 16844052; // 0x1010514
     field public static final int onClick = 16843375; // 0x101026f
@@ -992,7 +989,7 @@
     field public static final int persistableMode = 16843821; // 0x101042d
     field public static final int persistent = 16842765; // 0x101000d
     field public static final int persistentDrawingCache = 16842990; // 0x10100ee
-    field public static final int persistentWhenFeatureAvailable = 16844134; // 0x1010566
+    field public static final int persistentWhenFeatureAvailable = 16844131; // 0x1010563
     field public static final deprecated int phoneNumber = 16843111; // 0x1010167
     field public static final int pivotX = 16843189; // 0x10101b5
     field public static final int pivotY = 16843190; // 0x10101b6
@@ -1018,7 +1015,7 @@
     field public static final int preferenceStyle = 16842894; // 0x101008e
     field public static final int presentationTheme = 16843712; // 0x10103c0
     field public static final int previewImage = 16843482; // 0x10102da
-    field public static final int primaryContentAlpha = 16844117; // 0x1010555
+    field public static final int primaryContentAlpha = 16844114; // 0x1010552
     field public static final int priority = 16842780; // 0x101001c
     field public static final int privateImeOptions = 16843299; // 0x1010223
     field public static final int process = 16842769; // 0x1010011
@@ -1061,8 +1058,8 @@
     field public static final int ratingBarStyleSmall = 16842877; // 0x101007d
     field public static final int readPermission = 16842759; // 0x1010007
     field public static final int recognitionService = 16843932; // 0x101049c
-    field public static final int recreateOnConfigChanges = 16844105; // 0x1010549
-    field public static final int recycleEnabled = 16844124; // 0x101055c
+    field public static final int recreateOnConfigChanges = 16844103; // 0x1010547
+    field public static final int recycleEnabled = 16844121; // 0x1010559
     field public static final int relinquishTaskIdentity = 16843894; // 0x1010476
     field public static final int reparent = 16843964; // 0x10104bc
     field public static final int reparentWithOverlay = 16843965; // 0x10104bd
@@ -1076,9 +1073,9 @@
     field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
     field public static final int required = 16843406; // 0x101028e
     field public static final int requiredAccountType = 16843734; // 0x10103d6
-    field public static final int requiredFeature = 16844119; // 0x1010557
+    field public static final int requiredFeature = 16844116; // 0x1010554
     field public static final int requiredForAllUsers = 16843728; // 0x10103d0
-    field public static final int requiredNotFeature = 16844120; // 0x1010558
+    field public static final int requiredNotFeature = 16844117; // 0x1010555
     field public static final int requiresFadingEdge = 16843685; // 0x10103a5
     field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
     field public static final int resizeClip = 16843983; // 0x10104cf
@@ -1146,7 +1143,7 @@
     field public static final int searchSuggestSelection = 16843224; // 0x10101d8
     field public static final int searchSuggestThreshold = 16843373; // 0x101026d
     field public static final int searchViewStyle = 16843904; // 0x1010480
-    field public static final int secondaryContentAlpha = 16844118; // 0x1010556
+    field public static final int secondaryContentAlpha = 16844115; // 0x1010553
     field public static final int secondaryProgress = 16843064; // 0x1010138
     field public static final int secondaryProgressTint = 16843879; // 0x1010467
     field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
@@ -1186,7 +1183,7 @@
     field public static final deprecated int shownWeekCount = 16843585; // 0x1010341
     field public static final int shrinkColumns = 16843082; // 0x101014a
     field public static final deprecated int singleLine = 16843101; // 0x101015d
-    field public static final int singleLineTitle = 16844127; // 0x101055f
+    field public static final int singleLineTitle = 16844124; // 0x101055c
     field public static final int singleUser = 16843711; // 0x10103bf
     field public static final int slideEdge = 16843824; // 0x1010430
     field public static final int smallIcon = 16843422; // 0x101029e
@@ -1200,7 +1197,7 @@
     field public static final int spinnerStyle = 16842881; // 0x1010081
     field public static final int spinnersShown = 16843595; // 0x101034b
     field public static final int splitMotionEvents = 16843503; // 0x10102ef
-    field public static final int splitName = 16844107; // 0x101054b
+    field public static final int splitName = 16844105; // 0x1010549
     field public static final int splitTrack = 16843852; // 0x101044c
     field public static final int spotShadowAlpha = 16843967; // 0x10104bf
     field public static final int src = 16843033; // 0x1010119
@@ -1297,7 +1294,7 @@
     field public static final int targetName = 16843853; // 0x101044d
     field public static final int targetPackage = 16842785; // 0x1010021
     field public static final int targetProcesses = 16844097; // 0x1010541
-    field public static final int targetSandboxVersion = 16844110; // 0x101054e
+    field public static final int targetSandboxVersion = 16844108; // 0x101054c
     field public static final int targetSdkVersion = 16843376; // 0x1010270
     field public static final int taskAffinity = 16842770; // 0x1010012
     field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
@@ -1540,7 +1537,7 @@
     field public static final int windowShowAnimation = 16842934; // 0x10100b6
     field public static final int windowShowWallpaper = 16843410; // 0x1010292
     field public static final int windowSoftInputMode = 16843307; // 0x101022b
-    field public static final int windowSplashscreenContent = 16844135; // 0x1010567
+    field public static final int windowSplashscreenContent = 16844132; // 0x1010564
     field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
     field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
     field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -30508,7 +30505,7 @@
     field public static final int M = 23; // 0x17
     field public static final int N = 24; // 0x18
     field public static final int N_MR1 = 25; // 0x19
-    field public static final int O = 10000; // 0x2710
+    field public static final int O = 26; // 0x1a
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/api/removed.txt b/api/removed.txt
index f52b39a..9baafeb 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -254,18 +254,6 @@
     field public static final int BADGING_SD = 10; // 0xa
   }
 
-  public abstract class NetworkRecommendationProvider {
-    ctor public deprecated NetworkRecommendationProvider(android.os.Handler);
-    method public deprecated void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback);
-    field public static final deprecated java.lang.String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT";
-    field public static final deprecated java.lang.String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
-  }
-
-  public static deprecated class NetworkRecommendationProvider.ResultCallback {
-    ctor public NetworkRecommendationProvider.ResultCallback(android.os.IRemoteCallback, int);
-    method public void onResult(android.net.RecommendationResult);
-  }
-
   public abstract class PskKeyManager {
     ctor public PskKeyManager();
     field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
@@ -273,37 +261,6 @@
     field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
   }
 
-  public final deprecated class RecommendationRequest implements android.os.Parcelable {
-    ctor protected RecommendationRequest(android.os.Parcel);
-    method public android.net.wifi.WifiConfiguration[] getConnectableConfigs();
-    method public android.net.wifi.WifiConfiguration getConnectedConfig();
-    method public android.net.wifi.WifiConfiguration getDefaultWifiConfig();
-    method public int getLastSelectedNetworkId();
-    method public long getLastSelectedNetworkTimestamp();
-    method public android.net.wifi.ScanResult[] getScanResults();
-    method public void setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
-    method public void setConnectedConfig(android.net.wifi.WifiConfiguration);
-    field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR;
-  }
-
-  public static final deprecated class RecommendationRequest.Builder {
-    ctor public RecommendationRequest.Builder();
-    method public android.net.RecommendationRequest build();
-    method public android.net.RecommendationRequest.Builder setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
-    method public android.net.RecommendationRequest.Builder setConnectedWifiConfig(android.net.wifi.WifiConfiguration);
-    method public android.net.RecommendationRequest.Builder setDefaultWifiConfig(android.net.wifi.WifiConfiguration);
-    method public android.net.RecommendationRequest.Builder setLastSelectedNetwork(int, long);
-    method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]);
-  }
-
-  public final deprecated class RecommendationResult implements android.os.Parcelable {
-    method public static android.net.RecommendationResult createConnectRecommendation(android.net.wifi.WifiConfiguration);
-    method public static android.net.RecommendationResult createDoNotConnectRecommendation();
-    method public android.net.wifi.WifiConfiguration getWifiConfiguration();
-    method public boolean hasRecommendation();
-    field public static final android.os.Parcelable.Creator<android.net.RecommendationResult> CREATOR;
-  }
-
   public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
     method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index fcc647d..67b6e82 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -327,9 +327,6 @@
 
   public static final class R.attr {
     ctor public R.attr();
-    field public static final int __removed1 = 16844099; // 0x1010543
-    field public static final int __removed2 = 16844104; // 0x1010548
-    field public static final int __removed3 = 16844116; // 0x1010554
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -394,7 +391,7 @@
     field public static final int allowTaskReparenting = 16843268; // 0x1010204
     field public static final int allowUndo = 16843999; // 0x10104df
     field public static final int alpha = 16843551; // 0x101031f
-    field public static final int alphabeticModifiers = 16844112; // 0x1010550
+    field public static final int alphabeticModifiers = 16844110; // 0x101054e
     field public static final int alphabeticShortcut = 16843235; // 0x10101e3
     field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
     field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
@@ -414,7 +411,7 @@
     field public static final int anyDensity = 16843372; // 0x101026c
     field public static final int apduServiceBanner = 16843757; // 0x10103ed
     field public static final int apiKey = 16843281; // 0x1010211
-    field public static final int appCategory = 16844102; // 0x1010546
+    field public static final int appCategory = 16844101; // 0x1010545
     field public static final int author = 16843444; // 0x10102b4
     field public static final int authorities = 16842776; // 0x1010018
     field public static final int autoAdvanceViewId = 16843535; // 0x101030f
@@ -422,7 +419,7 @@
     field public static final int autoLink = 16842928; // 0x10100b0
     field public static final int autoMirrored = 16843754; // 0x10103ea
     field public static final int autoRemoveFromRecents = 16843847; // 0x1010447
-    field public static final int autoSizeMaxTextSize = 16844103; // 0x1010547
+    field public static final int autoSizeMaxTextSize = 16844102; // 0x1010546
     field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
     field public static final int autoSizePresetSizes = 16844087; // 0x1010537
     field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
@@ -431,8 +428,8 @@
     field public static final deprecated int autoText = 16843114; // 0x101016a
     field public static final int autoUrlDetect = 16843404; // 0x101028c
     field public static final int autoVerify = 16844014; // 0x10104ee
-    field public static final int autofillHints = 16844121; // 0x1010559
-    field public static final int autofilledHighlight = 16844139; // 0x101056b
+    field public static final int autofillHints = 16844118; // 0x1010556
+    field public static final int autofilledHighlight = 16844136; // 0x1010568
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -482,7 +479,7 @@
     field public static final int canRecord = 16844060; // 0x101051c
     field public static final deprecated int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
     field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
-    field public static final int canRequestFingerprintGestures = 16844111; // 0x101054f
+    field public static final int canRequestFingerprintGestures = 16844109; // 0x101054d
     field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
     field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
     field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
@@ -494,7 +491,7 @@
     field public static final int centerMedium = 16842959; // 0x10100cf
     field public static final int centerX = 16843170; // 0x10101a2
     field public static final int centerY = 16843171; // 0x10101a3
-    field public static final int certDigest = 16844106; // 0x101054a
+    field public static final int certDigest = 16844104; // 0x1010548
     field public static final int checkBoxPreferenceStyle = 16842895; // 0x101008f
     field public static final int checkMark = 16843016; // 0x1010108
     field public static final int checkMarkTint = 16843943; // 0x10104a7
@@ -533,12 +530,12 @@
     field public static final int colorControlHighlight = 16843820; // 0x101042c
     field public static final int colorControlNormal = 16843817; // 0x1010429
     field public static final int colorEdgeEffect = 16843982; // 0x10104ce
-    field public static final int colorError = 16844100; // 0x1010544
+    field public static final int colorError = 16844099; // 0x1010543
     field public static final int colorFocusedHighlight = 16843663; // 0x101038f
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
     field public static final int colorLongPressedHighlight = 16843662; // 0x101038e
-    field public static final int colorMode = 16844108; // 0x101054c
+    field public static final int colorMode = 16844106; // 0x101054a
     field public static final int colorMultiSelectHighlight = 16843665; // 0x1010391
     field public static final int colorPressedHighlight = 16843661; // 0x101038d
     field public static final int colorPrimary = 16843827; // 0x1010433
@@ -591,7 +588,7 @@
     field public static final deprecated int dayOfWeekBackground = 16843924; // 0x1010494
     field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
     field public static final int debuggable = 16842767; // 0x101000f
-    field public static final int defaultFocusHighlightEnabled = 16844133; // 0x1010565
+    field public static final int defaultFocusHighlightEnabled = 16844130; // 0x1010562
     field public static final int defaultHeight = 16844021; // 0x10104f5
     field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
     field public static final int defaultValue = 16843245; // 0x10101ed
@@ -723,15 +720,15 @@
     field public static final int flipInterval = 16843129; // 0x1010179
     field public static final int focusable = 16842970; // 0x10100da
     field public static final int focusableInTouchMode = 16842971; // 0x10100db
-    field public static final int focusedByDefault = 16844101; // 0x1010545
+    field public static final int focusedByDefault = 16844100; // 0x1010544
     field public static final deprecated int focusedMonthDateColor = 16843587; // 0x1010343
     field public static final int font = 16844082; // 0x1010532
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
-    field public static final int fontProviderAuthority = 16844114; // 0x1010552
-    field public static final int fontProviderCerts = 16844128; // 0x1010560
-    field public static final int fontProviderPackage = 16844122; // 0x101055a
-    field public static final int fontProviderQuery = 16844115; // 0x1010553
+    field public static final int fontProviderAuthority = 16844112; // 0x1010550
+    field public static final int fontProviderCerts = 16844125; // 0x101055d
+    field public static final int fontProviderPackage = 16844119; // 0x1010557
+    field public static final int fontProviderQuery = 16844113; // 0x1010551
     field public static final int fontStyle = 16844095; // 0x101053f
     field public static final int fontWeight = 16844083; // 0x1010533
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
@@ -817,9 +814,9 @@
     field public static final int hyphenationFrequency = 16843998; // 0x10104de
     field public static final int icon = 16842754; // 0x1010002
     field public static final int iconPreview = 16843337; // 0x1010249
-    field public static final int iconSpaceReserved = 16844132; // 0x1010564
-    field public static final int iconTint = 16844129; // 0x1010561
-    field public static final int iconTintMode = 16844130; // 0x1010562
+    field public static final int iconSpaceReserved = 16844129; // 0x1010561
+    field public static final int iconTint = 16844126; // 0x101055e
+    field public static final int iconTintMode = 16844127; // 0x101055f
     field public static final int iconifiedByDefault = 16843514; // 0x10102fa
     field public static final int id = 16842960; // 0x10100d0
     field public static final int ignoreGravity = 16843263; // 0x10101ff
@@ -836,7 +833,7 @@
     field public static final int imeSubtypeMode = 16843501; // 0x10102ed
     field public static final int immersive = 16843456; // 0x10102c0
     field public static final int importantForAccessibility = 16843690; // 0x10103aa
-    field public static final int importantForAutofill = 16844123; // 0x101055b
+    field public static final int importantForAutofill = 16844120; // 0x1010558
     field public static final int inAnimation = 16843127; // 0x1010177
     field public static final int includeFontPadding = 16843103; // 0x101015f
     field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -871,21 +868,21 @@
     field public static final int isAsciiCapable = 16843753; // 0x10103e9
     field public static final int isAuxiliary = 16843647; // 0x101037f
     field public static final int isDefault = 16843297; // 0x1010221
-    field public static final int isFeatureSplit = 16844126; // 0x101055e
+    field public static final int isFeatureSplit = 16844123; // 0x101055b
     field public static final int isGame = 16843764; // 0x10103f4
     field public static final int isIndicator = 16843079; // 0x1010147
     field public static final int isModifier = 16843334; // 0x1010246
     field public static final int isRepeatable = 16843336; // 0x1010248
     field public static final int isScrollContainer = 16843342; // 0x101024e
-    field public static final int isStatic = 16844125; // 0x101055d
+    field public static final int isStatic = 16844122; // 0x101055a
     field public static final int isSticky = 16843335; // 0x1010247
     field public static final int isolatedProcess = 16843689; // 0x10103a9
-    field public static final int isolatedSplits = 16844109; // 0x101054d
+    field public static final int isolatedSplits = 16844107; // 0x101054b
     field public static final int itemBackground = 16843056; // 0x1010130
     field public static final int itemIconDisabledAlpha = 16843057; // 0x1010131
     field public static final int itemPadding = 16843565; // 0x101032d
     field public static final int itemTextAppearance = 16843052; // 0x101012c
-    field public static final int justificationMode = 16844138; // 0x101056a
+    field public static final int justificationMode = 16844135; // 0x1010567
     field public static final int keepScreenOn = 16843286; // 0x1010216
     field public static final int key = 16843240; // 0x10101e8
     field public static final int keyBackground = 16843315; // 0x1010233
@@ -1002,7 +999,7 @@
     field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
     field public static final int matchOrder = 16843855; // 0x101044f
     field public static final int max = 16843062; // 0x1010136
-    field public static final int maxAspectRatio = 16844131; // 0x1010563
+    field public static final int maxAspectRatio = 16844128; // 0x1010560
     field public static final int maxButtonHeight = 16844029; // 0x10104fd
     field public static final int maxDate = 16843584; // 0x1010340
     field public static final int maxEms = 16843095; // 0x1010157
@@ -1065,7 +1062,7 @@
     field public static final int numbersSelectorColor = 16843939; // 0x10104a3
     field public static final int numbersTextColor = 16843937; // 0x10104a1
     field public static final deprecated int numeric = 16843109; // 0x1010165
-    field public static final int numericModifiers = 16844113; // 0x1010551
+    field public static final int numericModifiers = 16844111; // 0x101054f
     field public static final int numericShortcut = 16843236; // 0x10101e4
     field public static final int offset = 16844052; // 0x1010514
     field public static final int onClick = 16843375; // 0x101026f
@@ -1113,7 +1110,7 @@
     field public static final int persistableMode = 16843821; // 0x101042d
     field public static final int persistent = 16842765; // 0x101000d
     field public static final int persistentDrawingCache = 16842990; // 0x10100ee
-    field public static final int persistentWhenFeatureAvailable = 16844134; // 0x1010566
+    field public static final int persistentWhenFeatureAvailable = 16844131; // 0x1010563
     field public static final deprecated int phoneNumber = 16843111; // 0x1010167
     field public static final int pivotX = 16843189; // 0x10101b5
     field public static final int pivotY = 16843190; // 0x10101b6
@@ -1139,7 +1136,7 @@
     field public static final int preferenceStyle = 16842894; // 0x101008e
     field public static final int presentationTheme = 16843712; // 0x10103c0
     field public static final int previewImage = 16843482; // 0x10102da
-    field public static final int primaryContentAlpha = 16844117; // 0x1010555
+    field public static final int primaryContentAlpha = 16844114; // 0x1010552
     field public static final int priority = 16842780; // 0x101001c
     field public static final int privateImeOptions = 16843299; // 0x1010223
     field public static final int process = 16842769; // 0x1010011
@@ -1182,8 +1179,8 @@
     field public static final int ratingBarStyleSmall = 16842877; // 0x101007d
     field public static final int readPermission = 16842759; // 0x1010007
     field public static final int recognitionService = 16843932; // 0x101049c
-    field public static final int recreateOnConfigChanges = 16844105; // 0x1010549
-    field public static final int recycleEnabled = 16844124; // 0x101055c
+    field public static final int recreateOnConfigChanges = 16844103; // 0x1010547
+    field public static final int recycleEnabled = 16844121; // 0x1010559
     field public static final int relinquishTaskIdentity = 16843894; // 0x1010476
     field public static final int reparent = 16843964; // 0x10104bc
     field public static final int reparentWithOverlay = 16843965; // 0x10104bd
@@ -1197,11 +1194,11 @@
     field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
     field public static final int required = 16843406; // 0x101028e
     field public static final int requiredAccountType = 16843734; // 0x10103d6
-    field public static final int requiredFeature = 16844119; // 0x1010557
+    field public static final int requiredFeature = 16844116; // 0x1010554
     field public static final int requiredForAllUsers = 16843728; // 0x10103d0
-    field public static final int requiredNotFeature = 16844120; // 0x1010558
-    field public static final int requiredSystemPropertyName = 16844136; // 0x1010568
-    field public static final int requiredSystemPropertyValue = 16844137; // 0x1010569
+    field public static final int requiredNotFeature = 16844117; // 0x1010555
+    field public static final int requiredSystemPropertyName = 16844133; // 0x1010565
+    field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566
     field public static final int requiresFadingEdge = 16843685; // 0x10103a5
     field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
     field public static final int resizeClip = 16843983; // 0x10104cf
@@ -1273,7 +1270,7 @@
     field public static final int searchSuggestSelection = 16843224; // 0x10101d8
     field public static final int searchSuggestThreshold = 16843373; // 0x101026d
     field public static final int searchViewStyle = 16843904; // 0x1010480
-    field public static final int secondaryContentAlpha = 16844118; // 0x1010556
+    field public static final int secondaryContentAlpha = 16844115; // 0x1010553
     field public static final int secondaryProgress = 16843064; // 0x1010138
     field public static final int secondaryProgressTint = 16843879; // 0x1010467
     field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
@@ -1313,7 +1310,7 @@
     field public static final deprecated int shownWeekCount = 16843585; // 0x1010341
     field public static final int shrinkColumns = 16843082; // 0x101014a
     field public static final deprecated int singleLine = 16843101; // 0x101015d
-    field public static final int singleLineTitle = 16844127; // 0x101055f
+    field public static final int singleLineTitle = 16844124; // 0x101055c
     field public static final int singleUser = 16843711; // 0x10103bf
     field public static final int slideEdge = 16843824; // 0x1010430
     field public static final int smallIcon = 16843422; // 0x101029e
@@ -1327,7 +1324,7 @@
     field public static final int spinnerStyle = 16842881; // 0x1010081
     field public static final int spinnersShown = 16843595; // 0x101034b
     field public static final int splitMotionEvents = 16843503; // 0x10102ef
-    field public static final int splitName = 16844107; // 0x101054b
+    field public static final int splitName = 16844105; // 0x1010549
     field public static final int splitTrack = 16843852; // 0x101044c
     field public static final int spotShadowAlpha = 16843967; // 0x10104bf
     field public static final int src = 16843033; // 0x1010119
@@ -1424,7 +1421,7 @@
     field public static final int targetName = 16843853; // 0x101044d
     field public static final int targetPackage = 16842785; // 0x1010021
     field public static final int targetProcesses = 16844097; // 0x1010541
-    field public static final int targetSandboxVersion = 16844110; // 0x101054e
+    field public static final int targetSandboxVersion = 16844108; // 0x101054c
     field public static final int targetSdkVersion = 16843376; // 0x1010270
     field public static final int taskAffinity = 16842770; // 0x1010012
     field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
@@ -1667,7 +1664,7 @@
     field public static final int windowShowAnimation = 16842934; // 0x10100b6
     field public static final int windowShowWallpaper = 16843410; // 0x1010292
     field public static final int windowSoftInputMode = 16843307; // 0x101022b
-    field public static final int windowSplashscreenContent = 16844135; // 0x1010567
+    field public static final int windowSplashscreenContent = 16844132; // 0x1010564
     field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
     field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
     field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -33218,7 +33215,7 @@
     field public static final int M = 23; // 0x17
     field public static final int N = 24; // 0x18
     field public static final int N_MR1 = 25; // 0x19
-    field public static final int O = 10000; // 0x2710
+    field public static final int O = 26; // 0x1a
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 9f3970d..b1a29e7 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -252,18 +252,6 @@
     field public static final int BADGING_SD = 10; // 0xa
   }
 
-  public abstract class NetworkRecommendationProvider {
-    ctor public deprecated NetworkRecommendationProvider(android.os.Handler);
-    method public deprecated void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback);
-    field public static final deprecated java.lang.String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT";
-    field public static final deprecated java.lang.String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
-  }
-
-  public static deprecated class NetworkRecommendationProvider.ResultCallback {
-    ctor public NetworkRecommendationProvider.ResultCallback(android.os.IRemoteCallback, int);
-    method public void onResult(android.net.RecommendationResult);
-  }
-
   public abstract class PskKeyManager {
     ctor public PskKeyManager();
     field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
@@ -271,37 +259,6 @@
     field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
   }
 
-  public final deprecated class RecommendationRequest implements android.os.Parcelable {
-    ctor protected RecommendationRequest(android.os.Parcel);
-    method public android.net.wifi.WifiConfiguration[] getConnectableConfigs();
-    method public android.net.wifi.WifiConfiguration getConnectedConfig();
-    method public android.net.wifi.WifiConfiguration getDefaultWifiConfig();
-    method public int getLastSelectedNetworkId();
-    method public long getLastSelectedNetworkTimestamp();
-    method public android.net.wifi.ScanResult[] getScanResults();
-    method public void setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
-    method public void setConnectedConfig(android.net.wifi.WifiConfiguration);
-    field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR;
-  }
-
-  public static final deprecated class RecommendationRequest.Builder {
-    ctor public RecommendationRequest.Builder();
-    method public android.net.RecommendationRequest build();
-    method public android.net.RecommendationRequest.Builder setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
-    method public android.net.RecommendationRequest.Builder setConnectedWifiConfig(android.net.wifi.WifiConfiguration);
-    method public android.net.RecommendationRequest.Builder setDefaultWifiConfig(android.net.wifi.WifiConfiguration);
-    method public android.net.RecommendationRequest.Builder setLastSelectedNetwork(int, long);
-    method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]);
-  }
-
-  public final deprecated class RecommendationResult implements android.os.Parcelable {
-    method public static android.net.RecommendationResult createConnectRecommendation(android.net.wifi.WifiConfiguration);
-    method public static android.net.RecommendationResult createDoNotConnectRecommendation();
-    method public android.net.wifi.WifiConfiguration getWifiConfiguration();
-    method public boolean hasRecommendation();
-    field public static final android.os.Parcelable.Creator<android.net.RecommendationResult> CREATOR;
-  }
-
   public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
     method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index 1ff9efe4..d3cb4c9 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -206,9 +206,6 @@
 
   public static final class R.attr {
     ctor public R.attr();
-    field public static final int __removed1 = 16844099; // 0x1010543
-    field public static final int __removed2 = 16844104; // 0x1010548
-    field public static final int __removed3 = 16844116; // 0x1010554
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -273,7 +270,7 @@
     field public static final int allowTaskReparenting = 16843268; // 0x1010204
     field public static final int allowUndo = 16843999; // 0x10104df
     field public static final int alpha = 16843551; // 0x101031f
-    field public static final int alphabeticModifiers = 16844112; // 0x1010550
+    field public static final int alphabeticModifiers = 16844110; // 0x101054e
     field public static final int alphabeticShortcut = 16843235; // 0x10101e3
     field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
     field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
@@ -293,7 +290,7 @@
     field public static final int anyDensity = 16843372; // 0x101026c
     field public static final int apduServiceBanner = 16843757; // 0x10103ed
     field public static final int apiKey = 16843281; // 0x1010211
-    field public static final int appCategory = 16844102; // 0x1010546
+    field public static final int appCategory = 16844101; // 0x1010545
     field public static final int author = 16843444; // 0x10102b4
     field public static final int authorities = 16842776; // 0x1010018
     field public static final int autoAdvanceViewId = 16843535; // 0x101030f
@@ -301,7 +298,7 @@
     field public static final int autoLink = 16842928; // 0x10100b0
     field public static final int autoMirrored = 16843754; // 0x10103ea
     field public static final int autoRemoveFromRecents = 16843847; // 0x1010447
-    field public static final int autoSizeMaxTextSize = 16844103; // 0x1010547
+    field public static final int autoSizeMaxTextSize = 16844102; // 0x1010546
     field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
     field public static final int autoSizePresetSizes = 16844087; // 0x1010537
     field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
@@ -310,8 +307,8 @@
     field public static final deprecated int autoText = 16843114; // 0x101016a
     field public static final int autoUrlDetect = 16843404; // 0x101028c
     field public static final int autoVerify = 16844014; // 0x10104ee
-    field public static final int autofillHints = 16844121; // 0x1010559
-    field public static final int autofilledHighlight = 16844139; // 0x101056b
+    field public static final int autofillHints = 16844118; // 0x1010556
+    field public static final int autofilledHighlight = 16844136; // 0x1010568
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -361,7 +358,7 @@
     field public static final int canRecord = 16844060; // 0x101051c
     field public static final deprecated int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
     field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
-    field public static final int canRequestFingerprintGestures = 16844111; // 0x101054f
+    field public static final int canRequestFingerprintGestures = 16844109; // 0x101054d
     field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
     field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
     field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
@@ -373,7 +370,7 @@
     field public static final int centerMedium = 16842959; // 0x10100cf
     field public static final int centerX = 16843170; // 0x10101a2
     field public static final int centerY = 16843171; // 0x10101a3
-    field public static final int certDigest = 16844106; // 0x101054a
+    field public static final int certDigest = 16844104; // 0x1010548
     field public static final int checkBoxPreferenceStyle = 16842895; // 0x101008f
     field public static final int checkMark = 16843016; // 0x1010108
     field public static final int checkMarkTint = 16843943; // 0x10104a7
@@ -412,12 +409,12 @@
     field public static final int colorControlHighlight = 16843820; // 0x101042c
     field public static final int colorControlNormal = 16843817; // 0x1010429
     field public static final int colorEdgeEffect = 16843982; // 0x10104ce
-    field public static final int colorError = 16844100; // 0x1010544
+    field public static final int colorError = 16844099; // 0x1010543
     field public static final int colorFocusedHighlight = 16843663; // 0x101038f
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
     field public static final int colorLongPressedHighlight = 16843662; // 0x101038e
-    field public static final int colorMode = 16844108; // 0x101054c
+    field public static final int colorMode = 16844106; // 0x101054a
     field public static final int colorMultiSelectHighlight = 16843665; // 0x1010391
     field public static final int colorPressedHighlight = 16843661; // 0x101038d
     field public static final int colorPrimary = 16843827; // 0x1010433
@@ -470,7 +467,7 @@
     field public static final deprecated int dayOfWeekBackground = 16843924; // 0x1010494
     field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
     field public static final int debuggable = 16842767; // 0x101000f
-    field public static final int defaultFocusHighlightEnabled = 16844133; // 0x1010565
+    field public static final int defaultFocusHighlightEnabled = 16844130; // 0x1010562
     field public static final int defaultHeight = 16844021; // 0x10104f5
     field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
     field public static final int defaultValue = 16843245; // 0x10101ed
@@ -602,15 +599,15 @@
     field public static final int flipInterval = 16843129; // 0x1010179
     field public static final int focusable = 16842970; // 0x10100da
     field public static final int focusableInTouchMode = 16842971; // 0x10100db
-    field public static final int focusedByDefault = 16844101; // 0x1010545
+    field public static final int focusedByDefault = 16844100; // 0x1010544
     field public static final deprecated int focusedMonthDateColor = 16843587; // 0x1010343
     field public static final int font = 16844082; // 0x1010532
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
-    field public static final int fontProviderAuthority = 16844114; // 0x1010552
-    field public static final int fontProviderCerts = 16844128; // 0x1010560
-    field public static final int fontProviderPackage = 16844122; // 0x101055a
-    field public static final int fontProviderQuery = 16844115; // 0x1010553
+    field public static final int fontProviderAuthority = 16844112; // 0x1010550
+    field public static final int fontProviderCerts = 16844125; // 0x101055d
+    field public static final int fontProviderPackage = 16844119; // 0x1010557
+    field public static final int fontProviderQuery = 16844113; // 0x1010551
     field public static final int fontStyle = 16844095; // 0x101053f
     field public static final int fontWeight = 16844083; // 0x1010533
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
@@ -696,9 +693,9 @@
     field public static final int hyphenationFrequency = 16843998; // 0x10104de
     field public static final int icon = 16842754; // 0x1010002
     field public static final int iconPreview = 16843337; // 0x1010249
-    field public static final int iconSpaceReserved = 16844132; // 0x1010564
-    field public static final int iconTint = 16844129; // 0x1010561
-    field public static final int iconTintMode = 16844130; // 0x1010562
+    field public static final int iconSpaceReserved = 16844129; // 0x1010561
+    field public static final int iconTint = 16844126; // 0x101055e
+    field public static final int iconTintMode = 16844127; // 0x101055f
     field public static final int iconifiedByDefault = 16843514; // 0x10102fa
     field public static final int id = 16842960; // 0x10100d0
     field public static final int ignoreGravity = 16843263; // 0x10101ff
@@ -715,7 +712,7 @@
     field public static final int imeSubtypeMode = 16843501; // 0x10102ed
     field public static final int immersive = 16843456; // 0x10102c0
     field public static final int importantForAccessibility = 16843690; // 0x10103aa
-    field public static final int importantForAutofill = 16844123; // 0x101055b
+    field public static final int importantForAutofill = 16844120; // 0x1010558
     field public static final int inAnimation = 16843127; // 0x1010177
     field public static final int includeFontPadding = 16843103; // 0x101015f
     field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -750,21 +747,21 @@
     field public static final int isAsciiCapable = 16843753; // 0x10103e9
     field public static final int isAuxiliary = 16843647; // 0x101037f
     field public static final int isDefault = 16843297; // 0x1010221
-    field public static final int isFeatureSplit = 16844126; // 0x101055e
+    field public static final int isFeatureSplit = 16844123; // 0x101055b
     field public static final int isGame = 16843764; // 0x10103f4
     field public static final int isIndicator = 16843079; // 0x1010147
     field public static final int isModifier = 16843334; // 0x1010246
     field public static final int isRepeatable = 16843336; // 0x1010248
     field public static final int isScrollContainer = 16843342; // 0x101024e
-    field public static final int isStatic = 16844125; // 0x101055d
+    field public static final int isStatic = 16844122; // 0x101055a
     field public static final int isSticky = 16843335; // 0x1010247
     field public static final int isolatedProcess = 16843689; // 0x10103a9
-    field public static final int isolatedSplits = 16844109; // 0x101054d
+    field public static final int isolatedSplits = 16844107; // 0x101054b
     field public static final int itemBackground = 16843056; // 0x1010130
     field public static final int itemIconDisabledAlpha = 16843057; // 0x1010131
     field public static final int itemPadding = 16843565; // 0x101032d
     field public static final int itemTextAppearance = 16843052; // 0x101012c
-    field public static final int justificationMode = 16844138; // 0x101056a
+    field public static final int justificationMode = 16844135; // 0x1010567
     field public static final int keepScreenOn = 16843286; // 0x1010216
     field public static final int key = 16843240; // 0x10101e8
     field public static final int keyBackground = 16843315; // 0x1010233
@@ -881,7 +878,7 @@
     field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
     field public static final int matchOrder = 16843855; // 0x101044f
     field public static final int max = 16843062; // 0x1010136
-    field public static final int maxAspectRatio = 16844131; // 0x1010563
+    field public static final int maxAspectRatio = 16844128; // 0x1010560
     field public static final int maxButtonHeight = 16844029; // 0x10104fd
     field public static final int maxDate = 16843584; // 0x1010340
     field public static final int maxEms = 16843095; // 0x1010157
@@ -944,7 +941,7 @@
     field public static final int numbersSelectorColor = 16843939; // 0x10104a3
     field public static final int numbersTextColor = 16843937; // 0x10104a1
     field public static final deprecated int numeric = 16843109; // 0x1010165
-    field public static final int numericModifiers = 16844113; // 0x1010551
+    field public static final int numericModifiers = 16844111; // 0x101054f
     field public static final int numericShortcut = 16843236; // 0x10101e4
     field public static final int offset = 16844052; // 0x1010514
     field public static final int onClick = 16843375; // 0x101026f
@@ -992,7 +989,7 @@
     field public static final int persistableMode = 16843821; // 0x101042d
     field public static final int persistent = 16842765; // 0x101000d
     field public static final int persistentDrawingCache = 16842990; // 0x10100ee
-    field public static final int persistentWhenFeatureAvailable = 16844134; // 0x1010566
+    field public static final int persistentWhenFeatureAvailable = 16844131; // 0x1010563
     field public static final deprecated int phoneNumber = 16843111; // 0x1010167
     field public static final int pivotX = 16843189; // 0x10101b5
     field public static final int pivotY = 16843190; // 0x10101b6
@@ -1018,7 +1015,7 @@
     field public static final int preferenceStyle = 16842894; // 0x101008e
     field public static final int presentationTheme = 16843712; // 0x10103c0
     field public static final int previewImage = 16843482; // 0x10102da
-    field public static final int primaryContentAlpha = 16844117; // 0x1010555
+    field public static final int primaryContentAlpha = 16844114; // 0x1010552
     field public static final int priority = 16842780; // 0x101001c
     field public static final int privateImeOptions = 16843299; // 0x1010223
     field public static final int process = 16842769; // 0x1010011
@@ -1061,8 +1058,8 @@
     field public static final int ratingBarStyleSmall = 16842877; // 0x101007d
     field public static final int readPermission = 16842759; // 0x1010007
     field public static final int recognitionService = 16843932; // 0x101049c
-    field public static final int recreateOnConfigChanges = 16844105; // 0x1010549
-    field public static final int recycleEnabled = 16844124; // 0x101055c
+    field public static final int recreateOnConfigChanges = 16844103; // 0x1010547
+    field public static final int recycleEnabled = 16844121; // 0x1010559
     field public static final int relinquishTaskIdentity = 16843894; // 0x1010476
     field public static final int reparent = 16843964; // 0x10104bc
     field public static final int reparentWithOverlay = 16843965; // 0x10104bd
@@ -1076,9 +1073,9 @@
     field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
     field public static final int required = 16843406; // 0x101028e
     field public static final int requiredAccountType = 16843734; // 0x10103d6
-    field public static final int requiredFeature = 16844119; // 0x1010557
+    field public static final int requiredFeature = 16844116; // 0x1010554
     field public static final int requiredForAllUsers = 16843728; // 0x10103d0
-    field public static final int requiredNotFeature = 16844120; // 0x1010558
+    field public static final int requiredNotFeature = 16844117; // 0x1010555
     field public static final int requiresFadingEdge = 16843685; // 0x10103a5
     field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
     field public static final int resizeClip = 16843983; // 0x10104cf
@@ -1146,7 +1143,7 @@
     field public static final int searchSuggestSelection = 16843224; // 0x10101d8
     field public static final int searchSuggestThreshold = 16843373; // 0x101026d
     field public static final int searchViewStyle = 16843904; // 0x1010480
-    field public static final int secondaryContentAlpha = 16844118; // 0x1010556
+    field public static final int secondaryContentAlpha = 16844115; // 0x1010553
     field public static final int secondaryProgress = 16843064; // 0x1010138
     field public static final int secondaryProgressTint = 16843879; // 0x1010467
     field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
@@ -1186,7 +1183,7 @@
     field public static final deprecated int shownWeekCount = 16843585; // 0x1010341
     field public static final int shrinkColumns = 16843082; // 0x101014a
     field public static final deprecated int singleLine = 16843101; // 0x101015d
-    field public static final int singleLineTitle = 16844127; // 0x101055f
+    field public static final int singleLineTitle = 16844124; // 0x101055c
     field public static final int singleUser = 16843711; // 0x10103bf
     field public static final int slideEdge = 16843824; // 0x1010430
     field public static final int smallIcon = 16843422; // 0x101029e
@@ -1200,7 +1197,7 @@
     field public static final int spinnerStyle = 16842881; // 0x1010081
     field public static final int spinnersShown = 16843595; // 0x101034b
     field public static final int splitMotionEvents = 16843503; // 0x10102ef
-    field public static final int splitName = 16844107; // 0x101054b
+    field public static final int splitName = 16844105; // 0x1010549
     field public static final int splitTrack = 16843852; // 0x101044c
     field public static final int spotShadowAlpha = 16843967; // 0x10104bf
     field public static final int src = 16843033; // 0x1010119
@@ -1297,7 +1294,7 @@
     field public static final int targetName = 16843853; // 0x101044d
     field public static final int targetPackage = 16842785; // 0x1010021
     field public static final int targetProcesses = 16844097; // 0x1010541
-    field public static final int targetSandboxVersion = 16844110; // 0x101054e
+    field public static final int targetSandboxVersion = 16844108; // 0x101054c
     field public static final int targetSdkVersion = 16843376; // 0x1010270
     field public static final int taskAffinity = 16842770; // 0x1010012
     field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
@@ -1540,7 +1537,7 @@
     field public static final int windowShowAnimation = 16842934; // 0x10100b6
     field public static final int windowShowWallpaper = 16843410; // 0x1010292
     field public static final int windowSoftInputMode = 16843307; // 0x101022b
-    field public static final int windowSplashscreenContent = 16844135; // 0x1010567
+    field public static final int windowSplashscreenContent = 16844132; // 0x1010564
     field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
     field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
     field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -30617,7 +30614,7 @@
     field public static final int M = 23; // 0x17
     field public static final int N = 24; // 0x18
     field public static final int N_MR1 = 25; // 0x19
-    field public static final int O = 10000; // 0x2710
+    field public static final int O = 26; // 0x1a
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/api/test-removed.txt b/api/test-removed.txt
index f52b39a..9baafeb 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -254,18 +254,6 @@
     field public static final int BADGING_SD = 10; // 0xa
   }
 
-  public abstract class NetworkRecommendationProvider {
-    ctor public deprecated NetworkRecommendationProvider(android.os.Handler);
-    method public deprecated void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback);
-    field public static final deprecated java.lang.String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT";
-    field public static final deprecated java.lang.String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
-  }
-
-  public static deprecated class NetworkRecommendationProvider.ResultCallback {
-    ctor public NetworkRecommendationProvider.ResultCallback(android.os.IRemoteCallback, int);
-    method public void onResult(android.net.RecommendationResult);
-  }
-
   public abstract class PskKeyManager {
     ctor public PskKeyManager();
     field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
@@ -273,37 +261,6 @@
     field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
   }
 
-  public final deprecated class RecommendationRequest implements android.os.Parcelable {
-    ctor protected RecommendationRequest(android.os.Parcel);
-    method public android.net.wifi.WifiConfiguration[] getConnectableConfigs();
-    method public android.net.wifi.WifiConfiguration getConnectedConfig();
-    method public android.net.wifi.WifiConfiguration getDefaultWifiConfig();
-    method public int getLastSelectedNetworkId();
-    method public long getLastSelectedNetworkTimestamp();
-    method public android.net.wifi.ScanResult[] getScanResults();
-    method public void setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
-    method public void setConnectedConfig(android.net.wifi.WifiConfiguration);
-    field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR;
-  }
-
-  public static final deprecated class RecommendationRequest.Builder {
-    ctor public RecommendationRequest.Builder();
-    method public android.net.RecommendationRequest build();
-    method public android.net.RecommendationRequest.Builder setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
-    method public android.net.RecommendationRequest.Builder setConnectedWifiConfig(android.net.wifi.WifiConfiguration);
-    method public android.net.RecommendationRequest.Builder setDefaultWifiConfig(android.net.wifi.WifiConfiguration);
-    method public android.net.RecommendationRequest.Builder setLastSelectedNetwork(int, long);
-    method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]);
-  }
-
-  public final deprecated class RecommendationResult implements android.os.Parcelable {
-    method public static android.net.RecommendationResult createConnectRecommendation(android.net.wifi.WifiConfiguration);
-    method public static android.net.RecommendationResult createDoNotConnectRecommendation();
-    method public android.net.wifi.WifiConfiguration getWifiConfiguration();
-    method public boolean hasRecommendation();
-    field public static final android.os.Parcelable.Creator<android.net.RecommendationResult> CREATOR;
-  }
-
   public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
     method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
   }
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 3fd0f50..38ce427 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -1346,6 +1346,8 @@
         for (int n = 0; n < nodeCount; n++) {
             final Node node = mNodes.get(n);
             Node nodeClone = node.clone();
+            // Remove the old internal listener from the cloned child
+            nodeClone.mAnimation.removeListener(mDummyListener);
             clonesMap.put(node, nodeClone);
             anim.mNodes.add(nodeClone);
             anim.mNodeMap.put(nodeClone.mAnimation, nodeClone);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a8183f2..ab03556 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2092,7 +2092,6 @@
             if (params == null) {
                 throw new IllegalArgumentException("Expected non-null picture-in-picture params");
             }
-            updatePictureInPictureParamsForContentInsets(params);
             return ActivityManagerNative.getDefault().enterPictureInPictureMode(mToken, params);
         } catch (RemoteException e) {
             return false;
@@ -2116,7 +2115,6 @@
             if (params == null) {
                 throw new IllegalArgumentException("Expected non-null picture-in-picture params");
             }
-            updatePictureInPictureParamsForContentInsets(params);
             ActivityManagerNative.getDefault().setPictureInPictureParams(mToken, params);
         } catch (RemoteException e) {
         }
@@ -2136,21 +2134,6 @@
         }
     }
 
-    /**
-     * Updates the provided {@param params} with the last known content insets for this activity, to
-     * be used with the source hint rect for the transition into PiP.
-     */
-    private void updatePictureInPictureParamsForContentInsets(PictureInPictureParams params) {
-        if (params != null && params.hasSourceBoundsHint() && getWindow() != null &&
-                getWindow().peekDecorView() != null &&
-                getWindow().peekDecorView().getViewRootImpl() != null) {
-            params.setSourceRectHintInsets(
-                    getWindow().peekDecorView().getViewRootImpl().getLastContentInsets());
-        } else {
-            params.setSourceRectHintInsets(null);
-        }
-    }
-
     void dispatchMovedToDisplay(int displayId, Configuration config) {
         updateDisplay(displayId);
         onMovedToDisplay(displayId, config);
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 3eec596..53608fb 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -38,6 +38,7 @@
 import android.util.Pair;
 import android.util.Slog;
 import android.view.AppTransitionAnimationSpec;
+import android.view.IAppTransitionAnimationSpecsFuture;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
@@ -213,6 +214,7 @@
 
     private static final String KEY_INSTANT_APP_VERIFICATION_BUNDLE
             = "android:instantapps.installerbundle";
+    private static final String KEY_SPECS_FUTURE = "android:activity.specsFuture";
 
     /** @hide */
     public static final int ANIM_NONE = 0;
@@ -268,6 +270,7 @@
     private AppTransitionAnimationSpec mAnimSpecs[];
     private int mRotationAnimationHint = -1;
     private Bundle mAppVerificationBundle;
+    private IAppTransitionAnimationSpecsFuture mSpecsFuture;
 
     /**
      * Create an ActivityOptions specifying a custom animation to run when
@@ -492,35 +495,12 @@
      * is not executed, the callback will happen immediately.
      * @return Returns a new ActivityOptions object that you can use to
      * supply these options as the options Bundle when starting an activity.
-     * @hide
      */
-    public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
+    private static ActivityOptions makeThumbnailScaleUpAnimation(View source,
             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
         return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, true);
     }
 
-    /**
-     * Create an ActivityOptions specifying an animation where an activity window
-     * is scaled from a given position to a thumbnail at a specified location.
-     *
-     * @param source The View that this thumbnail is animating to.  This
-     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
-     * @param thumbnail The bitmap that will be shown as the final thumbnail
-     * of the animation.
-     * @param startX The x end location of the bitmap, relative to <var>source</var>.
-     * @param startY The y end location of the bitmap, relative to <var>source</var>.
-     * @param listener Optional OnAnimationStartedListener to find out when the
-     * requested animation has started running.  If for some reason the animation
-     * is not executed, the callback will happen immediately.
-     * @return Returns a new ActivityOptions object that you can use to
-     * supply these options as the options Bundle when starting an activity.
-     * @hide
-     */
-    public static ActivityOptions makeThumbnailScaleDownAnimation(View source,
-            Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
-        return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, false);
-    }
-
     private static ActivityOptions makeThumbnailAnimation(View source,
             Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,
             boolean scaleUp) {
@@ -537,29 +517,21 @@
     }
 
     /**
-     * Create an ActivityOptions specifying an animation where the new activity
-     * window and a thumbnail is aspect-scaled to a new location.
-     *
-     * @param source The View that this thumbnail is animating from.  This
-     * defines the coordinate space for <var>startX</var> and <var>startY</var>.
-     * @param thumbnail The bitmap that will be shown as the initial thumbnail
-     * of the animation.
-     * @param startX The x starting location of the bitmap, relative to <var>source</var>.
-     * @param startY The y starting location of the bitmap, relative to <var>source</var>.
-     * @param handler If <var>listener</var> is non-null this must be a valid
-     * Handler on which to dispatch the callback; otherwise it should be null.
-     * @param listener Optional OnAnimationStartedListener to find out when the
-     * requested animation has started running.  If for some reason the animation
-     * is not executed, the callback will happen immediately.
-     * @return Returns a new ActivityOptions object that you can use to
-     * supply these options as the options Bundle when starting an activity.
+     * Create an ActivityOptions specifying an animation where a list of activity windows and
+     * thumbnails are aspect scaled to/from a new location.
      * @hide
      */
-    public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source,
-            Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
-            Handler handler, OnAnimationStartedListener listener) {
-        return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
-                targetWidth, targetHeight, handler, listener, true);
+    public static ActivityOptions makeMultiThumbFutureAspectScaleAnimation(Context context,
+            Handler handler, IAppTransitionAnimationSpecsFuture specsFuture,
+            OnAnimationStartedListener listener, boolean scaleUp) {
+        ActivityOptions opts = new ActivityOptions();
+        opts.mPackageName = context.getPackageName();
+        opts.mAnimationType = scaleUp
+                ? ANIM_THUMBNAIL_ASPECT_SCALE_UP
+                : ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
+        opts.mSpecsFuture = specsFuture;
+        opts.setOnAnimationStartedListener(handler, listener);
+        return opts;
     }
 
     /**
@@ -891,6 +863,10 @@
         }
         mRotationAnimationHint = opts.getInt(KEY_ROTATION_ANIMATION_HINT);
         mAppVerificationBundle = opts.getBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE);
+        if (opts.containsKey(KEY_SPECS_FUTURE)) {
+            mSpecsFuture = IAppTransitionAnimationSpecsFuture.Stub.asInterface(opts.getBinder(
+                    KEY_SPECS_FUTURE));
+        }
     }
 
     /**
@@ -1029,6 +1005,11 @@
     public AppTransitionAnimationSpec[] getAnimSpecs() { return mAnimSpecs; }
 
     /** @hide */
+    public IAppTransitionAnimationSpecsFuture getSpecsFuture() {
+        return mSpecsFuture;
+    }
+
+    /** @hide */
     public static ActivityOptions fromBundle(Bundle bOptions) {
         return bOptions != null ? new ActivityOptions(bOptions) : null;
     }
@@ -1205,6 +1186,7 @@
         }
         mAnimSpecs = otherOptions.mAnimSpecs;
         mAnimationFinishedListener = otherOptions.mAnimationFinishedListener;
+        mSpecsFuture = otherOptions.mSpecsFuture;
     }
 
     /**
@@ -1279,6 +1261,9 @@
         if (mAnimationFinishedListener != null) {
             b.putBinder(KEY_ANIMATION_FINISHED_LISTENER, mAnimationFinishedListener.asBinder());
         }
+        if (mSpecsFuture != null) {
+            b.putBinder(KEY_SPECS_FUTURE, mSpecsFuture.asBinder());
+        }
         b.putInt(KEY_ROTATION_ANIMATION_HINT, mRotationAnimationHint);
         if (mAppVerificationBundle != null) {
             b.putBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE, mAppVerificationBundle);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 51c2246..525b151 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -478,7 +478,7 @@
     public @NonNull List<SharedLibraryInfo> getSharedLibrariesAsUser(int flags, int userId) {
         try {
             ParceledListSlice<SharedLibraryInfo> sharedLibs = mPM.getSharedLibraries(
-                    flags, userId);
+                    mContext.getOpPackageName(), flags, userId);
             if (sharedLibs == null) {
                 return Collections.emptyList();
             }
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 1b2543c..95d55dc 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -2303,11 +2303,15 @@
      */
     private void completeExecute(BackStackRecord record, boolean isPop, boolean runTransitions,
             boolean moveToState) {
+        if (isPop) {
+            record.executePopOps(moveToState);
+        } else {
+            record.executeOps();
+        }
         ArrayList<BackStackRecord> records = new ArrayList<>(1);
         ArrayList<Boolean> isRecordPop = new ArrayList<>(1);
         records.add(record);
         isRecordPop.add(isPop);
-        executeOps(records, isRecordPop, 0, 1);
         if (runTransitions) {
             FragmentTransition.startTransitions(this, records, isRecordPop, 0, 1, true);
         }
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 4994fbb..b5b1017 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -30,7 +30,7 @@
     void onTaskStackChanged();
 
     /** Called whenever an Activity is moved to the pinned stack from another stack. */
-    void onActivityPinned(String packageName);
+    void onActivityPinned(String packageName, int taskId);
 
     /** Called whenever an Activity is moved from the pinned stack to another stack. */
     void onActivityUnpinned();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 8a15b1f..3ed174b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1112,6 +1112,16 @@
     @SystemApi
     public static final String EXTRA_SUBSTITUTE_APP_NAME = "android.substName";
 
+    /**
+     * This is set on the notification shown by the activity manager about all apps
+     * running in the background.  It indicates that the notification should be shown
+     * only if any of the given apps do not already have a {@link #FLAG_FOREGROUND_SERVICE}
+     * notification currently visible to the user.  This is a string array of all
+     * package names of the apps.
+     * @hide
+     */
+    public static final String EXTRA_FOREGROUND_APPS = "android.foregroundApps";
+
     private Icon mSmallIcon;
     private Icon mLargeIcon;
 
diff --git a/core/java/android/app/PictureInPictureArgs.java b/core/java/android/app/PictureInPictureArgs.java
index d7317f4..cbe8bb9 100644
--- a/core/java/android/app/PictureInPictureArgs.java
+++ b/core/java/android/app/PictureInPictureArgs.java
@@ -160,9 +160,6 @@
         if (in.readInt() != 0) {
             mSourceRectHint = Rect.CREATOR.createFromParcel(in);
         }
-        if (in.readInt() != 0) {
-            mSourceRectHintInsets = Rect.CREATOR.createFromParcel(in);
-        }
     }
 
     private PictureInPictureArgs(Rational aspectRatio, List<RemoteAction> actions,
@@ -220,9 +217,6 @@
         if (otherArgs.hasSourceBoundsHint()) {
             mSourceRectHint = new Rect(otherArgs.getSourceRectHint());
         }
-        if (otherArgs.hasSourceBoundsHintInsets()) {
-            mSourceRectHintInsets = new Rect(otherArgs.getSourceRectHintInsets());
-        }
     }
 
     /**
@@ -346,12 +340,6 @@
         } else {
             out.writeInt(0);
         }
-        if (mSourceRectHintInsets != null) {
-            out.writeInt(1);
-            mSourceRectHintInsets.writeToParcel(out, 0);
-        } else {
-            out.writeInt(0);
-        }
     }
 
     public static final Creator<PictureInPictureArgs> CREATOR =
diff --git a/core/java/android/app/PictureInPictureParams.java b/core/java/android/app/PictureInPictureParams.java
index 323a0fb..7313b0d 100644
--- a/core/java/android/app/PictureInPictureParams.java
+++ b/core/java/android/app/PictureInPictureParams.java
@@ -135,13 +135,6 @@
     @Nullable
     private Rect mSourceRectHint;
 
-    /**
-     * The content insets that are used with the source hint rect for the transition into PiP where
-     * the insets are removed at the beginning of the transition.
-     */
-    @Nullable
-    private Rect mSourceRectHintInsets;
-
     /** {@hide} */
     PictureInPictureParams() {
     }
@@ -158,9 +151,6 @@
         if (in.readInt() != 0) {
             mSourceRectHint = Rect.CREATOR.createFromParcel(in);
         }
-        if (in.readInt() != 0) {
-            mSourceRectHintInsets = Rect.CREATOR.createFromParcel(in);
-        }
     }
 
     /** {@hide} */
@@ -185,9 +175,6 @@
         if (otherArgs.hasSourceBoundsHint()) {
             mSourceRectHint = new Rect(otherArgs.getSourceRectHint());
         }
-        if (otherArgs.hasSourceBoundsHintInsets()) {
-            mSourceRectHintInsets = new Rect(otherArgs.getSourceRectHintInsets());
-        }
     }
 
     /**
@@ -241,19 +228,6 @@
     }
 
     /**
-     * Sets the insets to be used with the source rect hint bounds.
-     * @hide
-     */
-    @Deprecated
-    public void setSourceRectHintInsets(Rect insets) {
-        if (insets == null) {
-            mSourceRectHintInsets = null;
-        } else {
-            mSourceRectHintInsets = new Rect(insets);
-        }
-    }
-
-    /**
      * @return the source rect hint
      * @hide
      */
@@ -262,14 +236,6 @@
     }
 
     /**
-     * @return the source rect hint insets.
-     * @hide
-     */
-    public Rect getSourceRectHintInsets() {
-        return mSourceRectHintInsets;
-    }
-
-    /**
      * @return whether there are launch bounds set
      * @hide
      */
@@ -277,14 +243,6 @@
         return mSourceRectHint != null && !mSourceRectHint.isEmpty();
     }
 
-    /**
-     * @return whether there are source rect hint insets set
-     * @hide
-     */
-    public boolean hasSourceBoundsHintInsets() {
-        return mSourceRectHintInsets != null;
-    }
-
     @Override
     public int describeContents() {
         return 0;
@@ -311,12 +269,6 @@
         } else {
             out.writeInt(0);
         }
-        if (mSourceRectHintInsets != null) {
-            out.writeInt(1);
-            mSourceRectHintInsets.writeToParcel(out, 0);
-        } else {
-            out.writeInt(0);
-        }
     }
 
     public static final Creator<PictureInPictureParams> CREATOR =
@@ -328,4 +280,4 @@
                     return new PictureInPictureParams[size];
                 }
             };
-}
\ No newline at end of file
+}
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 2df011f..a52ca0a 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -31,7 +31,7 @@
     }
 
     @Override
-    public void onActivityPinned(String packageName) throws RemoteException {
+    public void onActivityPinned(String packageName, int taskId) throws RemoteException {
     }
 
     @Override
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index ce8b05a..0d7a941 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -15,10 +15,13 @@
  */
 package android.app.usage;
 
+import android.annotation.IntDef;
 import android.content.res.Configuration;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 import java.util.List;
 
@@ -28,6 +31,12 @@
  */
 public final class UsageEvents implements Parcelable {
 
+    /** @hide */
+    public static final String INSTANT_APP_PACKAGE_NAME = "android.instant_app";
+
+    /** @hide */
+    public static final String INSTANT_APP_CLASS_NAME = "android.instant_class";
+
     /**
      * An event representing a state change for a component.
      */
@@ -91,6 +100,17 @@
          */
         public static final int CHOOSER_ACTION = 9;
 
+        /** @hide */
+        public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
+
+        /** @hide */
+        @IntDef(flag = true,
+                value = {
+                        FLAG_IS_PACKAGE_INSTANT_APP,
+                })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface EventFlags {}
+
         /**
          * {@hide}
          */
@@ -145,6 +165,27 @@
          */
         public String[] mContentAnnotations;
 
+        /** @hide */
+        @EventFlags
+        public int mFlags;
+
+        public Event() {
+        }
+
+        /** @hide */
+        public Event(Event orig) {
+            mPackage = orig.mPackage;
+            mClass = orig.mClass;
+            mTimeStamp = orig.mTimeStamp;
+            mEventType = orig.mEventType;
+            mConfiguration = orig.mConfiguration;
+            mShortcutId = orig.mShortcutId;
+            mAction = orig.mAction;
+            mContentType = orig.mContentType;
+            mContentAnnotations = orig.mContentAnnotations;
+            mFlags = orig.mFlags;
+        }
+
         /**
          * The package name of the source of this event.
          */
@@ -196,6 +237,20 @@
         public String getShortcutId() {
             return mShortcutId;
         }
+
+        /** @hide */
+        public Event getObfuscatedIfInstantApp() {
+            if ((mFlags & FLAG_IS_PACKAGE_INSTANT_APP) == 0) {
+                return this;
+            }
+            final Event ret = new Event(this);
+            ret.mPackage = INSTANT_APP_PACKAGE_NAME;
+            ret.mClass = INSTANT_APP_CLASS_NAME;
+
+            // Note there are other string fields too, but they're for app shortcuts and choosers,
+            // which instant apps can't use anyway, so there's no need to hide them.
+            return ret;
+        }
     }
 
     // Only used when creating the resulting events. Not used for reading/unparceling.
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 0874095..7eef85c 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -85,6 +85,17 @@
         mChooserCounts = stats.mChooserCounts;
     }
 
+    /**
+     * {@hide}
+     */
+    public UsageStats getObfuscatedForInstantApp() {
+        final UsageStats ret = new UsageStats(this);
+
+        ret.mPackageName = UsageEvents.INSTANT_APP_PACKAGE_NAME;
+
+        return ret;
+    }
+
     public String getPackageName() {
         return mPackageName;
     }
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 08595dd..dbaace2 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -127,7 +127,12 @@
 
     public abstract void applyRestoredPayload(int user, String key, byte[] payload);
 
-    /* Cache Quota Service API */
+    /**
+     * Return usage stats.
+     *
+     * @param obfuscateInstantApps whether instant app package names need to be obfuscated in the
+     *     result.
+     */
     public abstract List<UsageStats> queryUsageStatsForUser(
-            int userId, int interval, long beginTime, long endTime);
+            int userId, int interval, long beginTime, long endTime, boolean obfuscateInstantApps);
 }
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 5fabbb6..a3d6e9f 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -16,7 +16,6 @@
 
 package android.bluetooth;
 
-import android.content.Context;
 import android.os.Handler;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
@@ -927,6 +926,31 @@
     }
 
     /**
+     * Discovers a service by UUID. This is exposed only for passing PTS tests.
+     * It should never be used by real applications. The service is not searched
+     * for characteristics and descriptors, or returned in any callback.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * @return true, if the remote service discovery has been started
+     * @hide
+     */
+    public boolean discoverServiceByUuid(UUID uuid) {
+        if (DBG) Log.d(TAG, "discoverServiceByUuid() - device: " + mDevice.getAddress());
+        if (mService == null || mClientIf == 0) return false;
+
+        mServices.clear();
+
+        try {
+            mService.discoverServiceByUuid(mClientIf, mDevice.getAddress(), new ParcelUuid(uuid));
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+            return false;
+        }
+        return true;
+    }
+
+    /**
      * Returns a list of GATT services offered by the remote device.
      *
      * <p>This function requires that service discovery has been completed
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index dc5c7b6..167f5e9 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -80,6 +80,7 @@
     void clientReadPhy(in int clientIf, in String address);
     void refreshDevice(in int clientIf, in String address);
     void discoverServices(in int clientIf, in String address);
+    void discoverServiceByUuid(in int clientIf, in String address, in ParcelUuid uuid);
     void readCharacteristic(in int clientIf, in String address, in int handle, in int authReq);
     void readUsingCharacteristicUuid(in int clientIf, in String address, in ParcelUuid uuid,
                            in int startHandle, in int endHandle, in int authReq);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 702b91c..7aaf453 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -617,7 +617,7 @@
 
     int getInstallReason(String packageName, int userId);
 
-    ParceledListSlice getSharedLibraries(int flags, int userId);
+    ParceledListSlice getSharedLibraries(in String packageName, int flags, int userId);
 
     boolean canRequestPackageInstalls(String packageName, int userId);
 
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 426f3cf..87e6a84 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -341,4 +341,7 @@
      * Return the taget SDK version for the app with the given UID.
      */
     public abstract int getUidTargetSdkVersion(int uid);
+
+    /** Whether the binder caller can access instant apps. */
+    public abstract boolean canAccessInstantApps(int callingUid);
 }
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 8e57e85..b00e65a 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -100,8 +100,8 @@
     public static final int FINGERPRINT_ERROR_CANCELED = 5;
 
     /**
-     * The {@link FingerprintManager#remove(Fingerprint, RemovalCallback)} call failed. Typically
-     * this will happen when the provided fingerprint id was incorrect.
+     * The {@link FingerprintManager#remove} call failed. Typically this will happen when the
+     * provided fingerprint id was incorrect.
      *
      * @hide
      */
@@ -398,10 +398,10 @@
     };
 
     /**
-     * Callback structure provided to {@link FingerprintManager#remove(int). Users of
-     * {@link #FingerprintManager()} may optionally provide an implementation of this to
-     * {@link FingerprintManager#remove(int, int, RemovalCallback)} for listening to
-     * fingerprint template removal events.
+     * Callback structure provided to {@link #remove}. Users of {@link FingerprintManager} may
+     * optionally provide an implementation of this to
+     * {@link #remove(Fingerprint, int, RemovalCallback)} for listening to fingerprint template
+     * removal events.
      *
      * @hide
      */
@@ -416,9 +416,13 @@
 
         /**
          * Called when a given fingerprint is successfully removed.
-         * @param fingerprint the fingerprint template that was removed.
+         * @param fp The fingerprint template that was removed.
+         * @param remaining The number of fingerprints yet to be removed in this operation. If
+         *         {@link #remove} is called on one fingerprint, this should be 0. If
+         *         {@link #remove} is called on a group, this should be the number of remaining
+         *         fingerprints in the group, and 0 after the last fingerprint is removed.
          */
-        public void onRemovalSucceeded(Fingerprint fingerprint) { }
+        public void onRemovalSucceeded(Fingerprint fp, int remaining) { }
     };
 
     /**
@@ -878,8 +882,7 @@
                             msg.arg2 /* vendorCode */);
                     break;
                 case MSG_REMOVED:
-                    sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
-                            msg.arg2 /* groupId */);
+                    sendRemovedResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
                     break;
                 case MSG_ENUMERATED:
                     sendEnumeratedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
@@ -888,21 +891,29 @@
             }
         }
 
-        private void sendRemovedResult(long deviceId, int fingerId, int groupId) {
-            if (mRemovalCallback != null) {
-                int reqFingerId = mRemovalFingerprint.getFingerId();
-                int reqGroupId = mRemovalFingerprint.getGroupId();
-                if (reqFingerId != 0 && fingerId != 0  &&  fingerId != reqFingerId) {
-                    Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
-                    return;
-                }
-                if (groupId != reqGroupId) {
-                    Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
-                    return;
-                }
-                mRemovalCallback.onRemovalSucceeded(new Fingerprint(null, groupId, fingerId,
-                        deviceId));
+        private void sendRemovedResult(Fingerprint fingerprint, int remaining) {
+            if (mRemovalCallback == null) {
+                return;
             }
+            if (fingerprint == null) {
+                Log.e(TAG, "Received MSG_REMOVED, but fingerprint is null");
+                return;
+            }
+
+            int fingerId = fingerprint.getFingerId();
+            int reqFingerId = mRemovalFingerprint.getFingerId();
+            if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) {
+                Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
+                return;
+            }
+            int groupId = fingerprint.getGroupId();
+            int reqGroupId = mRemovalFingerprint.getGroupId();
+            if (groupId != reqGroupId) {
+                Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
+                return;
+            }
+
+            mRemovalCallback.onRemovalSucceeded(fingerprint, remaining);
         }
 
         private void sendEnumeratedResult(long deviceId, int fingerId, int groupId) {
@@ -1100,8 +1111,8 @@
 
         @Override // binder call
         public void onRemoved(long deviceId, int fingerId, int groupId, int remaining) {
-            // TODO: propagate remaining
-            mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
+            mHandler.obtainMessage(MSG_REMOVED, remaining, 0,
+                    new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
         }
 
         @Override // binder call
diff --git a/core/java/android/net/NetworkRecommendationProvider.java b/core/java/android/net/NetworkRecommendationProvider.java
index d7b58f7..fdb4ba0 100644
--- a/core/java/android/net/NetworkRecommendationProvider.java
+++ b/core/java/android/net/NetworkRecommendationProvider.java
@@ -20,19 +20,14 @@
 import android.annotation.SystemApi;
 import android.content.Context;
 import android.os.Build;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.IRemoteCallback;
 import android.os.RemoteException;
 import android.util.Log;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
 
-import java.util.Objects;
 import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * The base class for implementing a network recommendation provider.
@@ -55,34 +50,10 @@
 public abstract class NetworkRecommendationProvider {
     private static final String TAG = "NetworkRecProvider";
     private static final boolean VERBOSE = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.VERBOSE);
-    /** The key into the callback Bundle where the RecommendationResult will be found.
-     * @deprecated to be removed.
-     * @removed
-     */
-    public static final String EXTRA_RECOMMENDATION_RESULT =
-            "android.net.extra.RECOMMENDATION_RESULT";
-    /** The key into the callback Bundle where the sequence will be found.
-     * @deprecated to be removed.
-     * @removed
-     */
-    public static final String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
     private final IBinder mService;
 
     /**
      * Constructs a new instance.
-     * @param handler indicates which thread to use when handling requests. Cannot be {@code null}.
-     * @deprecated use {@link #NetworkRecommendationProvider(Context, Executor)}
-     * @removed
-     */
-    public NetworkRecommendationProvider(Handler handler) {
-        if (handler == null) {
-            throw new IllegalArgumentException("The provided handler cannot be null.");
-        }
-        mService = new ServiceWrapper(handler);
-    }
-
-    /**
-     * Constructs a new instance.
      * @param context the current context instance. Cannot be {@code null}.
      * @param executor used to execute the incoming requests. Cannot be {@code null}.
      */
@@ -93,19 +64,6 @@
     }
 
     /**
-     * Invoked when a recommendation has been requested.
-     *
-     * @param request a {@link RecommendationRequest} instance containing additional
-     *                request details
-     * @param callback a {@link ResultCallback} instance. When a {@link RecommendationResult} is
-     *                 available it must be passed into
-     *                 {@link ResultCallback#onResult(RecommendationResult)}.
-     * @deprecated to be removed.
-     * @removed
-     */
-    public void onRequestRecommendation(RecommendationRequest request, ResultCallback callback) {}
-
-    /**
      * Invoked when network scores have been requested.
      * <p>
      * Use {@link NetworkScoreManager#updateScores(ScoredNetwork[])} to respond to score requests.
@@ -123,66 +81,6 @@
     }
 
     /**
-     * A callback implementing applications should invoke when a {@link RecommendationResult}
-     * is available.
-     *
-     * @deprecated to be removed.
-     * @removed
-     */
-    public static class ResultCallback {
-        private final IRemoteCallback mCallback;
-        private final int mSequence;
-        private final AtomicBoolean mCallbackRun;
-
-        /**
-         * @hide
-         */
-        @VisibleForTesting
-        public ResultCallback(IRemoteCallback callback, int sequence) {
-            mCallback = callback;
-            mSequence = sequence;
-            mCallbackRun = new AtomicBoolean(false);
-        }
-
-        /**
-         * Run the callback with the available {@link RecommendationResult}.
-         * @param result a {@link RecommendationResult} instance.
-         */
-        public void onResult(RecommendationResult result) {
-            if (VERBOSE) Log.v(TAG, "onResult(seq=" + mSequence + ")");
-            if (!mCallbackRun.compareAndSet(false, true)) {
-                throw new IllegalStateException("The callback cannot be run more than once. "
-                        + "seq=" + mSequence);
-            }
-            final Bundle data = new Bundle();
-            data.putInt(EXTRA_SEQUENCE, mSequence);
-            data.putParcelable(EXTRA_RECOMMENDATION_RESULT, result);
-            try {
-                mCallback.sendResult(data);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Callback failed for seq: " + mSequence, e);
-            }
-            if (VERBOSE) Log.v(TAG, "onResult() complete. seq=" + mSequence);
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            ResultCallback that = (ResultCallback) o;
-
-            return mSequence == that.mSequence
-                    && Objects.equals(mCallback, that.mCallback);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(mCallback, mSequence);
-        }
-    }
-
-    /**
      * A wrapper around INetworkRecommendationProvider that dispatches to the provided Handler.
      */
     private final class ServiceWrapper extends INetworkRecommendationProvider.Stub {
@@ -190,12 +88,6 @@
         private final Executor mExecutor;
         private final Handler mHandler;
 
-        ServiceWrapper(Handler handler) {
-            mHandler = handler;
-            mExecutor = null;
-            mContext = null;
-        }
-
         ServiceWrapper(Context context, Executor executor) {
             mContext = context;
             mExecutor = executor;
diff --git a/core/java/android/net/RecommendationRequest.java b/core/java/android/net/RecommendationRequest.java
deleted file mode 100644
index 21641d9..0000000
--- a/core/java/android/net/RecommendationRequest.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.net;
-
-
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * A request for a network recommendation.
- *
- * @see {@link NetworkScoreManager#requestRecommendation(RecommendationRequest)}.
- * @hide
- * @deprecated to be removed.
- * @removed
- */
-public final class RecommendationRequest implements Parcelable {
-    private final ScanResult[] mScanResults;
-    private final WifiConfiguration mDefaultConfig;
-    private WifiConfiguration mConnectedConfig;
-    private WifiConfiguration[] mConnectableConfigs;
-    private final int mLastSelectedNetworkId;
-    private final long mLastSelectedNetworkTimestamp;
-
-    /**
-     * Builder class for constructing {@link RecommendationRequest} instances.
-     * @hide
-     * @deprecated to be removed.
-     * @removed
-     */
-    public static final class Builder {
-        private ScanResult[] mScanResults;
-        private WifiConfiguration mDefaultConfig;
-        private WifiConfiguration mConnectedConfig;
-        private WifiConfiguration[] mConnectableConfigs;
-        private int mLastSelectedNetworkId = -1;
-        private long mLastSelectedTimestamp;
-
-        public Builder setScanResults(ScanResult[] scanResults) {
-            mScanResults = scanResults;
-            return this;
-        }
-
-        /**
-         * @param config the {@link WifiConfiguration} to return if no recommendation is available.
-         * @return this
-         */
-        public Builder setDefaultWifiConfig(WifiConfiguration config) {
-            this.mDefaultConfig = config;
-            return this;
-        }
-
-        /**
-         * @param config the {@link WifiConfiguration} of the connected network at the time the
-         *               this request was made.
-         * @return this
-         */
-        public Builder setConnectedWifiConfig(WifiConfiguration config) {
-            this.mConnectedConfig = config;
-            return this;
-        }
-
-        /**
-         * @param connectableConfigs the set of saved {@link WifiConfiguration}s that can be
-         *                           connected to based on the current set of {@link ScanResult}s.
-         * @return this
-         */
-        public Builder setConnectableConfigs(WifiConfiguration[] connectableConfigs) {
-            this.mConnectableConfigs = connectableConfigs;
-            return this;
-        }
-
-        /**
-         * @param networkId The {@link WifiConfiguration#networkId} of the last user selected
-         *                  network.
-         * @param timestamp The {@link android.os.SystemClock#elapsedRealtime()} when the user
-         *                  selected {@code networkId}.
-         * @return this
-         */
-        public Builder setLastSelectedNetwork(int networkId, long timestamp) {
-            this.mLastSelectedNetworkId = networkId;
-            this.mLastSelectedTimestamp = timestamp;
-            return this;
-        }
-
-        /**
-         * @return a new {@link RecommendationRequest} instance
-         */
-        public RecommendationRequest build() {
-            return new RecommendationRequest(mScanResults, mDefaultConfig, mConnectedConfig,
-                    mConnectableConfigs, mLastSelectedNetworkId, mLastSelectedTimestamp);
-        }
-    }
-
-    /**
-     * @return the array of {@link ScanResult}s the recommendation must be constrained to i.e. if a
-     *         non-null wifi config recommendation is returned then it must be able to connect to
-     *         one of the networks in the results list.
-     *
-     *         If the array is {@code null} or empty then there is no constraint.
-     */
-    public ScanResult[] getScanResults() {
-        return mScanResults;
-    }
-
-    /**
-     * @return the {@link WifiConfiguration} to return if no recommendation is available.
-     */
-    public WifiConfiguration getDefaultWifiConfig() {
-        return mDefaultConfig;
-    }
-
-    /**
-     * @return the {@link WifiConfiguration} of the connected network at the time the this request
-     *         was made.
-     */
-    public WifiConfiguration getConnectedConfig() {
-        return mConnectedConfig;
-    }
-
-    /**
-     * @return the set of saved {@link WifiConfiguration}s that can be connected to based on the
-     *         current set of {@link ScanResult}s.
-     */
-    public WifiConfiguration[] getConnectableConfigs() {
-        return mConnectableConfigs;
-    }
-
-    /**
-     * @param connectedConfig the {@link WifiConfiguration} of the connected network at the time
-     *                        the this request was made.
-     */
-    public void setConnectedConfig(WifiConfiguration connectedConfig) {
-        mConnectedConfig = connectedConfig;
-    }
-
-    /**
-     * @param connectableConfigs the set of saved {@link WifiConfiguration}s that can be connected
-     *                           to based on the current set of {@link ScanResult}s.
-     */
-    public void setConnectableConfigs(WifiConfiguration[] connectableConfigs) {
-        mConnectableConfigs = connectableConfigs;
-    }
-
-    /**
-     * @return The {@link WifiConfiguration#networkId} of the last user selected network.
-     *         {@code -1} if not set.
-     */
-    public int getLastSelectedNetworkId() {
-        return mLastSelectedNetworkId;
-    }
-
-    /**
-     * @return The {@link android.os.SystemClock#elapsedRealtime()} when the user selected
-     *         {@link #getLastSelectedNetworkId()}. {@code 0} if not set.
-     */
-    public long getLastSelectedNetworkTimestamp() {
-        return mLastSelectedNetworkTimestamp;
-    }
-
-    @VisibleForTesting
-    RecommendationRequest(ScanResult[] scanResults,
-            WifiConfiguration defaultWifiConfig,
-            WifiConfiguration connectedWifiConfig,
-            WifiConfiguration[] connectableConfigs,
-            int lastSelectedNetworkId,
-            long lastSelectedNetworkTimestamp) {
-        mScanResults = scanResults;
-        mDefaultConfig = defaultWifiConfig;
-        mConnectedConfig = connectedWifiConfig;
-        mConnectableConfigs = connectableConfigs;
-        mLastSelectedNetworkId = lastSelectedNetworkId;
-        mLastSelectedNetworkTimestamp = lastSelectedNetworkTimestamp;
-    }
-
-    protected RecommendationRequest(Parcel in) {
-        final int resultCount = in.readInt();
-        if (resultCount > 0) {
-            mScanResults = new ScanResult[resultCount];
-            final ClassLoader classLoader = ScanResult.class.getClassLoader();
-            for (int i = 0; i < resultCount; i++) {
-                mScanResults[i] = in.readParcelable(classLoader);
-            }
-        } else {
-            mScanResults = null;
-        }
-
-        mDefaultConfig = in.readParcelable(WifiConfiguration.class.getClassLoader());
-        mConnectedConfig = in.readParcelable(WifiConfiguration.class.getClassLoader());
-
-        final int configCount = in.readInt();
-        if (configCount > 0) {
-            mConnectableConfigs = new WifiConfiguration[configCount];
-            final ClassLoader classLoader = WifiConfiguration.class.getClassLoader();
-            for (int i = 0; i < configCount; i++) {
-                mConnectableConfigs[i] = in.readParcelable(classLoader);
-            }
-        } else {
-            mConnectableConfigs = null;
-        }
-
-        mLastSelectedNetworkId = in.readInt();
-        mLastSelectedNetworkTimestamp = in.readLong();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        if (mScanResults != null) {
-            dest.writeInt(mScanResults.length);
-            for (int i = 0; i < mScanResults.length; i++) {
-                dest.writeParcelable(mScanResults[i], flags);
-            }
-        } else {
-            dest.writeInt(0);
-        }
-
-        dest.writeParcelable(mDefaultConfig, flags);
-        dest.writeParcelable(mConnectedConfig, flags);
-
-        if (mConnectableConfigs != null) {
-            dest.writeInt(mConnectableConfigs.length);
-            for (int i = 0; i < mConnectableConfigs.length; i++) {
-                dest.writeParcelable(mConnectableConfigs[i], flags);
-            }
-        } else {
-            dest.writeInt(0);
-        }
-
-        dest.writeInt(mLastSelectedNetworkId);
-        dest.writeLong(mLastSelectedNetworkTimestamp);
-    }
-
-    public static final Creator<RecommendationRequest> CREATOR =
-            new Creator<RecommendationRequest>() {
-                @Override
-                public RecommendationRequest createFromParcel(Parcel in) {
-                    return new RecommendationRequest(in);
-                }
-
-                @Override
-                public RecommendationRequest[] newArray(int size) {
-                    return new RecommendationRequest[size];
-                }
-            };
-}
diff --git a/core/java/android/net/RecommendationResult.java b/core/java/android/net/RecommendationResult.java
deleted file mode 100644
index d66dd22..0000000
--- a/core/java/android/net/RecommendationResult.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.net;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.net.wifi.WifiConfiguration;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.util.Preconditions;
-
-/**
- * The result of a network recommendation.
- *
- * @see {@link NetworkScoreManager#requestRecommendation(RecommendationRequest)}.
- * @hide
- * @deprecated to be removed.
- * @removed
- */
-public final class RecommendationResult implements Parcelable {
-    private final WifiConfiguration mWifiConfiguration;
-
-    /**
-     * Create a {@link RecommendationResult} that indicates that no network connection should be
-     * attempted at this time.
-     *
-     * @return a {@link RecommendationResult}
-     */
-    public static RecommendationResult createDoNotConnectRecommendation() {
-        return new RecommendationResult((WifiConfiguration) null);
-    }
-
-    /**
-     * Create a {@link RecommendationResult} that indicates that a connection attempt should be
-     * made for the given Wi-Fi network.
-     *
-     * @param wifiConfiguration {@link WifiConfiguration} with at least SSID and BSSID set.
-     * @return a {@link RecommendationResult}
-     */
-    public static RecommendationResult createConnectRecommendation(
-            @NonNull WifiConfiguration wifiConfiguration) {
-        Preconditions.checkNotNull(wifiConfiguration, "wifiConfiguration must not be null");
-        Preconditions.checkNotNull(wifiConfiguration.SSID, "SSID must not be null");
-        Preconditions.checkNotNull(wifiConfiguration.BSSID, "BSSID must not be null");
-        return new RecommendationResult(wifiConfiguration);
-    }
-
-    private RecommendationResult(@Nullable WifiConfiguration wifiConfiguration) {
-        mWifiConfiguration = wifiConfiguration;
-    }
-
-    private RecommendationResult(Parcel in) {
-        mWifiConfiguration = in.readParcelable(WifiConfiguration.class.getClassLoader());
-    }
-
-    /**
-     * @return {@code true} if a network recommendation exists. {@code false} indicates that
-     *         no connection should be attempted at this time.
-     */
-    public boolean hasRecommendation() {
-        return mWifiConfiguration != null;
-    }
-
-    /**
-     * @return The recommended {@link WifiConfiguration} to connect to. A {@code null} value
-     *         is returned if {@link #hasRecommendation} returns {@code false}.
-     */
-    @Nullable public WifiConfiguration getWifiConfiguration() {
-        return mWifiConfiguration;
-    }
-
-    @Override
-    public String toString() {
-      return "RecommendationResult{" +
-          "mWifiConfiguration=" + mWifiConfiguration +
-          "}";
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeParcelable(mWifiConfiguration, flags);
-    }
-
-    public static final Creator<RecommendationResult> CREATOR =
-            new Creator<RecommendationResult>() {
-                @Override
-                public RecommendationResult createFromParcel(Parcel in) {
-                    return new RecommendationResult(in);
-                }
-
-                @Override
-                public RecommendationResult[] newArray(int size) {
-                    return new RecommendationResult[size];
-                }
-            };
-}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 86fcfc8..4bad7ab 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -758,7 +758,7 @@
         /**
          * O.
          */
-        public static final int O = CUR_DEVELOPMENT; // STOPSHIP Replace with the real version.
+        public static final int O = 26;
     }
 
     /** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index e4cdbce..f9eaba9 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -20,6 +20,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.opengl.EGL14;
+import android.os.Build;
 import android.os.SystemProperties;
 import android.util.Log;
 
@@ -81,6 +82,12 @@
             }
             return;
         }
+        if (driverInfo.targetSdkVersion < Build.VERSION_CODES.O) {
+            // O drivers are restricted to the sphal linker namespace, so don't try to use
+            // packages unless they declare they're compatible with that restriction.
+            Log.w(TAG, "updated driver package is not known to be compatible with O");
+            return;
+        }
 
         StringBuilder sb = new StringBuilder();
         sb.append(driverInfo.nativeLibraryDir)
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 3212139..c091420 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -547,7 +547,8 @@
      * Converts a string representing a file mode, such as "rw", into a bitmask suitable for use
      * with {@link #open}.
      * <p>
-     * @param mode The string representation of the file mode.
+     * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw"
+     *             or "rwt".
      * @return A bitmask representing the given file mode.
      * @throws IllegalArgumentException if the given string does not match a known file mode.
      */
diff --git a/core/java/android/os/ProxyFileDescriptorCallback.java b/core/java/android/os/ProxyFileDescriptorCallback.java
index e69fb55..9f56802 100644
--- a/core/java/android/os/ProxyFileDescriptorCallback.java
+++ b/core/java/android/os/ProxyFileDescriptorCallback.java
@@ -22,7 +22,23 @@
 /**
  * Callback that handles file system requests from ProxyFileDescriptor.
  *
- * @see android.os.storage.StorageManager#openProxyFileDescriptor(int, ProxyFileDescriptorCallback)
+ * All callback methods except for onRelease should throw {@link android.system.ErrnoException}
+ * with proper errno on errors. See
+ * <a href="http://man7.org/linux/man-pages/man3/errno.3.html">errno(3)</a> and
+ * {@link android.system.OsConstants}.
+ *
+ * Typical errnos are
+ *
+ * <ul>
+ * <li>{@link android.system.OsConstants#EIO} for general I/O issues
+ * <li>{@link android.system.OsConstants#ENOENT} when the file is not found
+ * <li>{@link android.system.OsConstants#EBADF} if the file doesn't allow read/write operations
+ *     based on how it was opened.  (For example, trying to write a file that was opened read-only.)
+ * <li>{@link android.system.OsConstants#ENOSPC} if you cannot handle a write operation to
+ *     space/quota limitations.
+ * </ul>
+ * @see android.os.storage.StorageManager#openProxyFileDescriptor(int, ProxyFileDescriptorCallback,
+ *     Handler)
  */
 public abstract class ProxyFileDescriptorCallback {
     /**
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index 97da588..17f00c2 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -167,4 +167,12 @@
      * Remove user's running state
      */
     public abstract void removeUserState(int userId);
+
+    /**
+     * Returns an array of user ids. This array is cached in UserManagerService and passed as a
+     * reference, so do not modify the returned array.
+     *
+     * @return the array of user ids.
+     */
+    public abstract int[] getUserIds();
 }
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 2cc4b71..92f7f31 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -295,4 +295,5 @@
     long getCacheSizeBytes(String volumeUuid, int uid) = 76;
     long getAllocatableBytes(String volumeUuid, int flags) = 77;
     void allocateBytes(String volumeUuid, long bytes, int flags) = 78;
+    void secdiscard(in String path) = 79;
 }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index bd43d6a..f361c54 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1252,6 +1252,15 @@
     }
 
     /** {@hide} */
+    public void secdiscard(String path) {
+        try {
+            mStorageManager.secdiscard(path);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** {@hide} */
     public static boolean isUserKeyUnlocked(int userId) {
         if (sStorageManager == null) {
             sStorageManager = IStorageManager.Stub
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 2a83c4b..3eef31a 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -655,8 +655,12 @@
      * <p>
      * Your provider should return a reliable {@link ParcelFileDescriptor} to
      * detect when the remote caller has finished reading or writing the
-     * document. You may return a pipe or socket pair if the mode is exclusively
-     * "r" or "w", but complex modes like "rw" imply a normal file on disk that
+     * document.
+     * <p>
+     * Mode "r" should always be supported. Provider should throw
+     * {@link UnsupportedOperationException} if the passing mode is not supported.
+     * You may return a pipe or socket pair if the mode is exclusively "r" or
+     * "w", but complex modes like "rw" imply a normal file on disk that
      * supports seeking.
      * <p>
      * If you block while downloading content, you should periodically check
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 2ade9b5..2c33b60 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -245,6 +245,7 @@
         super.onAttachedToWindow();
 
         getViewRootImpl().addWindowStoppedCallback(this);
+        mWindowStopped = false;
 
         mParent.requestTransparentRegion(this);
         mViewVisibility = getVisibility() == VISIBLE;
@@ -855,7 +856,7 @@
      */
     @Deprecated
     public void setWindowType(int type) {
-        if (getContext().getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.N_MR1) {
+        if (getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O) {
             throw new UnsupportedOperationException(
                     "SurfaceView#setWindowType() has never been a public API.");
         }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d3d753b..2d48295 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20506,6 +20506,9 @@
      * @throws IllegalStateException if the drawable could not be found.
      */
     @Nullable private Drawable getAutofilledDrawable() {
+        if (mAttachInfo == null) {
+            return null;
+        }
         // Lazily load the isAutofilled drawable.
         if (mAttachInfo.mAutofilledDrawable == null) {
             Context rootContext = getRootView().getContext();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 109cac0..28ded55 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1561,16 +1561,6 @@
         host.dispatchApplyWindowInsets(getWindowInsets(true /* forceConstruct */));
     }
 
-    /**
-     * @return the last content insets for use in adjusting the source hint rect for the
-     * picture-in-picture transition.
-     *
-     * @hide
-     */
-    public Rect getLastContentInsets() {
-        return mAttachInfo.mContentInsets;
-    }
-
     private static boolean shouldUseDisplaySize(final WindowManager.LayoutParams lp) {
         return lp.type == TYPE_STATUS_BAR_PANEL
                 || lp.type == TYPE_INPUT_METHOD
@@ -2411,6 +2401,9 @@
     }
 
     private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
+        if (mView == null) {
+            return;
+        }
         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
         try {
             mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index e4d4e7b..0973d0a 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -334,7 +334,7 @@
      */
     ViewTreeObserver(Context context) {
         sIllegalOnDrawModificationIsFatal =
-                context.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.N_MR1;
+                context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O;
     }
 
     /**
diff --git a/core/java/android/webkit/UserPackage.java b/core/java/android/webkit/UserPackage.java
index f53b5d6..8920089 100644
--- a/core/java/android/webkit/UserPackage.java
+++ b/core/java/android/webkit/UserPackage.java
@@ -83,8 +83,7 @@
      * supported by the current framework version.
      */
     public static boolean hasCorrectTargetSdkVersion(PackageInfo packageInfo) {
-        // TODO(gsennton) use Build.VERSION_CODES.O when that has been updated.
-        return packageInfo.applicationInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1;
+        return packageInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O;
     }
 
     public UserInfo getUserInfo() {
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index be0967f..cfd1445 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -16,7 +16,7 @@
 
 package android.widget;
 
-import static android.os.Build.VERSION_CODES.N_MR1;
+import static android.os.Build.VERSION_CODES.O;
 
 import android.annotation.Nullable;
 import android.content.Context;
@@ -302,7 +302,7 @@
         getTempCalendarForTime(timeInMillis);
 
         final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
-        if (targetSdkVersion > N_MR1) {
+        if (targetSdkVersion >= O) {
             if (mTempCalendar.before(mMinDate) || mTempCalendar.after(mMaxDate)) {
                 throw new IllegalArgumentException("timeInMillis must be between the values of "
                         + "getMinDate() and getMaxDate()");
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 77f27d9..8542bec0 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11227,8 +11227,10 @@
                 return true;
 
             case DragEvent.ACTION_DRAG_LOCATION:
-                final int offset = getOffsetForPosition(event.getX(), event.getY());
-                Selection.setSelection((Spannable) mText, offset);
+                if (mText instanceof Spannable) {
+                    final int offset = getOffsetForPosition(event.getX(), event.getY());
+                    Selection.setSelection((Spannable) mText, offset);
+                }
                 return true;
 
             case DragEvent.ACTION_DROP:
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 3605585..05d0f96 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -248,7 +248,7 @@
             mRadialTimePickerHeader.setVisibility(View.GONE);
             mTextInputPickerHeader.setVisibility(View.VISIBLE);
             mTextInputPickerView.setVisibility(View.VISIBLE);
-            mRadialTimePickerModeButton.setImageResource(R.drawable.btn_event_material);
+            mRadialTimePickerModeButton.setImageResource(R.drawable.btn_clock_material);
             mRadialTimePickerModeButton.setContentDescription(
                     mRadialTimePickerModeEnabledDescription);
             mRadialPickerModeEnabled = false;
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 13ebe5c..d807120 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -449,6 +449,11 @@
         public void handleShow(IBinder windowToken) {
             if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
                     + " mNextView=" + mNextView);
+            // If a cancel/hide is pending - no need to show - at this point
+            // the window token is already invalid and no need to do any work.
+            if (mHandler.hasMessages(CANCEL) || mHandler.hasMessages(HIDE)) {
+                return;
+            }
             if (mView != mNextView) {
                 // remove the old view if necessary
                 handleHide();
@@ -483,8 +488,16 @@
                     mWM.removeView(mView);
                 }
                 if (localLOGV) Log.v(TAG, "ADD! " + mView + " in " + this);
-                mWM.addView(mView, mParams);
-                trySendAccessibilityEvent();
+                // Since the notification manager service cancels the token right
+                // after it notifies us to cancel the toast there is an inherent
+                // race and we may attempt to add a window after the token has been
+                // invalidated. Let us hedge against that.
+                try {
+                    mWM.addView(mView, mParams);
+                    trySendAccessibilityEvent();
+                } catch (WindowManager.BadTokenException e) {
+                    /* ignore */
+                }
             }
         }
 
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index 797cf2b..d279746 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -47,6 +47,7 @@
     public static String RETAIL_MODE = "RETAIL_MODE";
     public static String USB = "USB";
     public static String FOREGROUND_SERVICE = "FOREGROUND_SERVICE";
+    public static String ALERT_WINDOW = "ALERT_WINDOW";
 
     public static void createAll(Context context) {
         final NotificationManager nm = context.getSystemService(NotificationManager.class);
@@ -137,6 +138,11 @@
                 context.getString(R.string.notification_channel_foreground_service),
                 NotificationManager.IMPORTANCE_MIN));
 
+        channelsList.add(new NotificationChannel(
+                ALERT_WINDOW,
+                context.getString(R.string.alert_windows_notification_channel_name),
+                NotificationManager.IMPORTANCE_MIN));
+
         nm.createNotificationChannels(channelsList);
     }
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 0d0d099..25d5fae 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -967,14 +967,15 @@
         }
     }
 
+    @VisibleForTesting
     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
         final TimeBase mTimeBase;
-        long[] mCounts;
-        long[] mLoadedCounts;
-        long[] mUnpluggedCounts;
-        long[] mPluggedCounts;
+        public long[] mCounts;
+        public long[] mLoadedCounts;
+        public long[] mUnpluggedCounts;
+        public long[] mPluggedCounts;
 
-        LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
+        private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
             mTimeBase = timeBase;
             mPluggedCounts = in.createLongArray();
             mCounts = copyArray(mPluggedCounts, mCounts);
@@ -983,12 +984,12 @@
             timeBase.add(this);
         }
 
-        LongSamplingCounterArray(TimeBase timeBase) {
+        public LongSamplingCounterArray(TimeBase timeBase) {
             mTimeBase = timeBase;
             timeBase.add(this);
         }
 
-        public void writeToParcel(Parcel out) {
+        private void writeToParcel(Parcel out) {
             out.writeLongArray(mCounts);
             out.writeLongArray(mLoadedCounts);
             out.writeLongArray(mUnpluggedCounts);
@@ -1024,7 +1025,7 @@
                     + " mPluggedCounts=" + Arrays.toString(mPluggedCounts));
         }
 
-        void addCountLocked(long[] counts) {
+        public void addCountLocked(long[] counts) {
             if (counts == null) {
                 return;
             }
@@ -1039,7 +1040,7 @@
         /**
          * Clear state of this counter.
          */
-        void reset(boolean detachIfReset) {
+        public void reset(boolean detachIfReset) {
             fillArray(mCounts, 0);
             fillArray(mLoadedCounts, 0);
             fillArray(mPluggedCounts, 0);
@@ -1049,21 +1050,60 @@
             }
         }
 
-        void detach() {
+        public void detach() {
             mTimeBase.remove(this);
         }
 
-        void writeSummaryFromParcelLocked(Parcel out) {
+        private void writeSummaryToParcelLocked(Parcel out) {
             out.writeLongArray(mCounts);
         }
 
-        void readSummaryFromParcelLocked(Parcel in) {
+        private void readSummaryFromParcelLocked(Parcel in) {
             mCounts = in.createLongArray();
             mLoadedCounts = copyArray(mCounts, mLoadedCounts);
             mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
             mPluggedCounts = copyArray(mCounts, mPluggedCounts);
         }
 
+        public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
+            if (counterArray != null) {
+                out.writeInt(1);
+                counterArray.writeToParcel(out);
+            } else {
+                out.writeInt(0);
+            }
+        }
+
+        public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
+            if (in.readInt() != 0) {
+                return new LongSamplingCounterArray(timeBase, in);
+            } else {
+                return null;
+            }
+        }
+
+        public static void writeSummaryToParcelLocked(Parcel out,
+                LongSamplingCounterArray counterArray) {
+            if (counterArray != null) {
+                out.writeInt(1);
+                counterArray.writeSummaryToParcelLocked(out);
+            } else {
+                out.writeInt(0);
+            }
+        }
+
+        public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
+                TimeBase timeBase) {
+            if (in.readInt() != 0) {
+                final LongSamplingCounterArray counterArray
+                        = new LongSamplingCounterArray(timeBase);
+                counterArray.readSummaryFromParcelLocked(in);
+                return counterArray;
+            } else {
+                return null;
+            }
+        }
+
         private void fillArray(long[] a, long val) {
             if (a != null) {
                 Arrays.fill(a, val);
@@ -6927,18 +6967,8 @@
                 out.writeInt(0);
             }
 
-            if (mCpuFreqTimeMs != null) {
-                out.writeInt(1);
-                mCpuFreqTimeMs.writeToParcel(out);
-            } else {
-                out.writeInt(0);
-            }
-            if (mScreenOffCpuFreqTimeMs != null) {
-                out.writeInt(1);
-                mScreenOffCpuFreqTimeMs.writeToParcel(out);
-            } else {
-                out.writeInt(0);
-            }
+            LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
+            LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
 
             if (mMobileRadioApWakeupCount != null) {
                 out.writeInt(1);
@@ -7187,17 +7217,9 @@
                 mCpuClusterSpeed = null;
             }
 
-            if (in.readInt() != 0) {
-                mCpuFreqTimeMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
-            } else {
-                mCpuFreqTimeMs = null;
-            }
-            if (in.readInt() != 0) {
-                mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
-                        mBsi.mOnBatteryScreenOffTimeBase, in);
-            } else {
-                mScreenOffCpuFreqTimeMs = null;
-            }
+            mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
+            mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
+                    in, mBsi.mOnBatteryScreenOffTimeBase);
 
             if (in.readInt() != 0) {
                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
@@ -10129,7 +10151,7 @@
 
                     @Override
                     public void onUidCpuFreqTime(int uid, long[] cpuFreqTimeMs) {
-                        final Uid u = getUidStatsLocked(uid);
+                        final Uid u = getUidStatsLocked(mapUid(uid));
                         if (u.mCpuFreqTimeMs == null) {
                             u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
                         }
@@ -11355,19 +11377,10 @@
                 u.mCpuClusterSpeed = null;
             }
 
-            if (in.readInt() != 0) {
-                u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
-                u.mCpuFreqTimeMs.readSummaryFromParcelLocked(in);
-            } else {
-                u.mCpuFreqTimeMs = null;
-            }
-            if (in.readInt() != 0) {
-                u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
-                        mOnBatteryScreenOffTimeBase);
-                u.mScreenOffCpuFreqTimeMs.readSummaryFromParcelLocked(in);
-            } else {
-                u.mScreenOffCpuFreqTimeMs = null;
-            }
+            u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
+                    in, mOnBatteryTimeBase);
+            u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
+                    in, mOnBatteryScreenOffTimeBase);
 
             if (in.readInt() != 0) {
                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
@@ -11765,18 +11778,8 @@
                 out.writeInt(0);
             }
 
-            if (u.mCpuFreqTimeMs != null) {
-                out.writeInt(1);
-                u.mCpuFreqTimeMs.writeSummaryFromParcelLocked(out);
-            } else {
-                out.writeInt(0);
-            }
-            if (u.mScreenOffCpuFreqTimeMs != null) {
-                out.writeInt(1);
-                u.mScreenOffCpuFreqTimeMs.writeSummaryFromParcelLocked(out);
-            } else {
-                out.writeInt(0);
-            }
+            LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
+            LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
 
             if (u.mMobileRadioApWakeupCount != null) {
                 out.writeInt(1);
diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java
index e86932c..6b53368 100644
--- a/core/java/com/android/internal/widget/ImageFloatingTextView.java
+++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java
@@ -169,4 +169,8 @@
         }
         return false;
     }
+
+    public int getLayoutHeight() {
+        return getLayout().getHeight();
+    }
 }
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
index 1104318..70473a0 100644
--- a/core/java/com/android/internal/widget/MessagingLinearLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -138,7 +138,7 @@
                 first = false;
                 boolean measuredTooSmall = false;
                 if (textChild != null) {
-                    measuredTooSmall = childHeight < textChild.getLayout().getHeight()
+                    measuredTooSmall = childHeight < textChild.getLayoutHeight()
                             + textChild.getPaddingTop() + textChild.getPaddingBottom();
                 }
 
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index b529e37..214d97c 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -60,17 +60,14 @@
 static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jobject jbitmap,
         jint tileModeX, jint tileModeY) {
     const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
-    sk_sp<SkImage> image;
+    SkBitmap bitmap;
     if (jbitmap) {
         // Only pass a valid SkBitmap object to the constructor if the Bitmap exists. Otherwise,
         // we'll pass an empty SkBitmap to avoid crashing/excepting for compatibility.
-        image = android::bitmap::toBitmap(env, jbitmap).makeImage(nullptr);
+        android::bitmap::toBitmap(env, jbitmap).getSkBitmapForShaders(&bitmap);
     }
 
-    if (!image.get()) {
-        SkBitmap bitmap;
-        image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
-    }
+    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
     sk_sp<SkShader> baseShader = image->makeShader(
             (SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY);
 
diff --git a/core/jni/android_app_ApplicationLoaders.cpp b/core/jni/android_app_ApplicationLoaders.cpp
index 3e7c039..8bbf24a 100644
--- a/core/jni/android_app_ApplicationLoaders.cpp
+++ b/core/jni/android_app_ApplicationLoaders.cpp
@@ -32,7 +32,7 @@
         loader_data.layer_path = layerPathChars.c_str();
         loader_data.app_namespace = ns;
     } else {
-        ALOGD("ignored Vulkan layer search path %s for namespace %p",
+        ALOGV("Vulkan layer search path already set, not clobbering with '%s' for namespace %p'",
                 layerPathChars.c_str(), ns);
     }
 }
diff --git a/core/res/res/anim/lock_screen_behind_enter.xml b/core/res/res/anim/lock_screen_behind_enter.xml
index c96e280..c1d26e3 100644
--- a/core/res/res/anim/lock_screen_behind_enter.xml
+++ b/core/res/res/anim/lock_screen_behind_enter.xml
@@ -17,8 +17,7 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:detachWallpaper="true"
-        android:shareInterpolator="false"
-        android:startOffset="100">
+        android:shareInterpolator="false">
 
     <translate android:fromYDelta="110%p" android:toYDelta="0"
             android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
diff --git a/core/res/res/anim/lock_screen_behind_enter_fade_in.xml b/core/res/res/anim/lock_screen_behind_enter_fade_in.xml
index 94e40a8..e9475f5 100644
--- a/core/res/res/anim/lock_screen_behind_enter_fade_in.xml
+++ b/core/res/res/anim/lock_screen_behind_enter_fade_in.xml
@@ -22,6 +22,5 @@
     android:interpolator="@interpolator/linear"
     android:fromAlpha="0" android:toAlpha="1"
     android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-    android:duration="250"
-    android:startOffset="100">
+    android:duration="250">
 </alpha>
\ No newline at end of file
diff --git a/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml b/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml
index 660b662..50156fb 100644
--- a/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml
+++ b/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml
@@ -16,12 +16,12 @@
   -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-    android:detachWallpaper="true" android:shareInterpolator="false" android:startOffset="100">
+    android:detachWallpaper="true" android:shareInterpolator="false" >
     <alpha
         android:fromAlpha="0.0" android:toAlpha="1.0"
         android:fillEnabled="true" android:fillBefore="true"
         android:interpolator="@interpolator/decelerate_quint"
-        android:duration="400"/>
+        android:duration="300"/>
 
     <translate android:fromYDelta="11%p" android:toYDelta="0"
         android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
diff --git a/core/res/res/anim/lock_screen_wallpaper_exit.xml b/core/res/res/anim/lock_screen_wallpaper_exit.xml
index 49d0327..ba8741a 100644
--- a/core/res/res/anim/lock_screen_wallpaper_exit.xml
+++ b/core/res/res/anim/lock_screen_wallpaper_exit.xml
@@ -16,12 +16,12 @@
   -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:shareInterpolator="false" android:startOffset="100">
+        android:shareInterpolator="false">
     <alpha
         android:fromAlpha="1.0" android:toAlpha="0.0"
         android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
         android:interpolator="@interpolator/fast_out_linear_in"
-        android:duration="150"/>
+        android:duration="200"/>
 
     <!-- Empty animation so the animation has same duration as lock_screen_behind_enter animation
          -->
diff --git a/core/res/res/drawable/btn_event_material.xml b/core/res/res/drawable/btn_clock_material.xml
similarity index 73%
rename from core/res/res/drawable/btn_event_material.xml
rename to core/res/res/drawable/btn_clock_material.xml
index 47c49cf..f785ebf 100644
--- a/core/res/res/drawable/btn_event_material.xml
+++ b/core/res/res/drawable/btn_clock_material.xml
@@ -18,12 +18,9 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="24dp"
         android:height="24dp"
-        android:viewportWidth="24"
-        android:viewportHeight="24">
-
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#90ffffff"
-        android:pathData="M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99 .9 -1.99 2L3 19c0 1.1 .89 2 2
-2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z" />
-    <path android:pathData="M0 0h24v24H0z" />
-</vector>
\ No newline at end of file
+        android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"/>
+</vector>
diff --git a/core/res/res/layout-land/time_picker_material.xml b/core/res/res/layout-land/time_picker_material.xml
index 8b95f9f..863efef 100644
--- a/core/res/res/layout-land/time_picker_material.xml
+++ b/core/res/res/layout-land/time_picker_material.xml
@@ -20,11 +20,10 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
-    <LinearLayout
+    <RelativeLayout
         android:id="@+id/time_header"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:orientation="vertical"
         android:gravity="center"
         android:paddingStart="?attr/dialogPreferredPadding"
         android:paddingEnd="?attr/dialogPreferredPadding">
@@ -112,7 +111,7 @@
                 android:includeFontPadding="false"
                 android:button="@null" />
         </RadioGroup>
-    </LinearLayout>
+    </RelativeLayout>
 
     <TextView
         android:visibility="gone"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index be38c83..bafd40d 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Opdaterings"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Netwerkstatus"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Netwerkwaarskuwings"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Netwerk is beskikbaar"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-status"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Toesteladministrasie"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Opletberigte"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vingerafdrukuittelling is bereik. Probeer weer."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Vingerafdrukhandeling is gekanselleer."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Te veel pogings. Probeer later weer."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Probeer weer."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Vinger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index fa2d60b..d91c185 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"ዝማኔዎች"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"የአውታረ መረብ ሁኔታ"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"የአውታረ መረብ ማንቂያዎች"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"አውታረ መረብ ይገኛል"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"የቪፒኤን ሁኔታ"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"የመሣሪያ አስተዳደር"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"ማንቂያዎች"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"የጣት አሻራ ማብቂያ ጊዜ ደርሷል። እንደገና ይሞክሩ።"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"የጣት አሻራ ስርዓተ ክወና ተትቷል።"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ከልክ በላይ ብዙ ሙከራዎች። በኋላ ላይ እንደገና ይሞክሩ።"</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"እንደገና ይሞክሩ።"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ጣት <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 91d360f..2646333 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -272,8 +272,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"التحديثات"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"حالة الشبكة"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"تنبيهات الشبكة"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"الشبكة متوفرة"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"حالة الشبكة الظاهرية الخاصة"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"إدارة الجهاز"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"التنبيهات"</string>
@@ -504,6 +503,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"تم بلوغ مهلة إدخال بصمة الإصبع. أعد المحاولة."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"تم إلغاء تشغيل بصمة الإصبع."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"تم إجراء عدد كبير من المحاولات. أعد المحاولة لاحقًا."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"أعد المحاولة."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"الإصبع <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index f5fe77e..a4a3881 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Güncəlləmələr"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Şəbəkə statusu"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Şəbəkə siqnalları"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Şəbəkə əlçatandır"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN statusu"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Cihaz administrasiyası"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Siqnallar"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Barmaq izinin vaxtı başa çatdı. Yenidən cəhd edin."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Barmaq izi əməliyyatı ləğv edildi."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Cəhdlər çox oldu. Sonraya saxlayın."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Yenidən cəhd edin."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Barmaq <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 9cee985..ebb5cd0 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -263,8 +263,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Ažuriranja"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Status mreže"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Obaveštenja u vezi sa mrežom"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Mreža je dostupna"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Status VPN-a"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administriranje uređaja"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Obaveštenja"</string>
@@ -495,6 +494,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vremensko ograničenje za otisak prsta je isteklo. Probajte ponovo."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja sa otiskom prsta je otkazana."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Probajte ponovo kasnije."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Probajte ponovo."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 2f46637..32cec88 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -266,8 +266,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Абнаўленні"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Стан сеткі"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Абвесткі сеткі"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Сетка даступная"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Стан VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Адміністраванне прылады"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Абвесткi"</string>
@@ -498,6 +497,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час чакання адбіткаў пальцаў выйшаў. Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Аперацыя з адбіткамі пальцаў скасавана."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Занадта шмат спроб. Паспрабуйце яшчэ раз пазней."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Палец <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 42dfd9b..e72b2f9 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Времето за изчакване за отпечатък изтече. Опитайте отново."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Операцията за отпечатък е анулирана."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Твърде много опити. Пробвайте отново по-късно."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Опитайте отново."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Пръст <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index d185ad5..954c910 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"আঙ্গুলের ছাপ নেওয়ার সময়সীমা শেষ হযেছে৷ আবার চেষ্টা করুন৷"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"আঙ্গুলের ছাপ অপারেশন বাতিল করা হয়েছে৷"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"অনেকবার প্রচেষ্টা করা হয়েছে৷ পরে আবার চেষ্টা করুন৷"</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"আবার চেষ্টা করুন৷"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"আঙ্গুল <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index cedc392..101afb7 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -263,8 +263,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Ažuriranja"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Status mreže"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Mrežna upozorenja"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Mreža je dostupna"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Status VPN-a"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administracija uređaja"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string>
@@ -495,6 +494,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vremensko ograničenje za otisak prsta je isteklo. Pokušajte ponovo."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja sa otiskom prsta je otkazana."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Pokušajte ponovo."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 04afd6c..e928cd9 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Actualitzacions"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Estat de la xarxa"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertes de xarxa"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Hi ha una xarxa disponible"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Estat de la VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administració del dispositiu"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"S\'ha esgotat el temps d\'espera per a l\'empremta digital. Torna-ho a provar."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"S\'ha cancel·lat l\'operació d\'empremta digital."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"S\'han produït massa intents. Torna-ho a provar més tard."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Torna-ho a provar."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dit <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 0cffb88..5b5dbcf 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -266,8 +266,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Aktualizace"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Stav sítě"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Síťová upozornění"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"K dispozici je síť"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Stav sítě VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administrace zařízení"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornění"</string>
@@ -498,6 +497,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit sejmutí otisku prstu vypršel. Zkuste to znovu."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operace otisku prstu byla zrušena."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Příliš mnoho pokusů. Zkuste to později."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Zkuste to znovu."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 15a3fee..441a25b 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Opdateringer"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Netværksstatus"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Netværksunderretninger"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Tilgængeligt netværk"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-status"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Enhedsadministration"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Underretninger"</string>
@@ -301,7 +300,7 @@
     <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"observere tekst, du skriver"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Dette omfatter personlige data såsom kreditkortnumre og adgangskoder."</string>
     <string name="capability_title_canControlMagnification" msgid="3593493281059424855">"administrere skærmforstørrelsen"</string>
-    <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrollér skærmens zoomniveau og position."</string>
+    <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Tjek skærmens zoomniveau og position."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Udfør bevægelser"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan trykke, stryge, knibe sammen og udføre andre bevægelser."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingeraftryksbevægelser"</string>
@@ -408,8 +407,8 @@
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Tillader, at appen sender kommandoer til SIM-kortet. Dette er meget farligt."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"tage billeder og optage video"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Med denne app kan du tage billeder og optage video med kameraet når som helst."</string>
-    <string name="permlab_vibrate" msgid="7696427026057705834">"kontrollere vibration"</string>
-    <string name="permdesc_vibrate" msgid="6284989245902300945">"Tillader, at appen kan kontrollere vibratoren."</string>
+    <string name="permlab_vibrate" msgid="7696427026057705834">"administrere vibration"</string>
+    <string name="permdesc_vibrate" msgid="6284989245902300945">"Tillader, at appen kan administrere vibratoren."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"ringe direkte op til telefonnumre"</string>
     <string name="permdesc_callPhone" msgid="3740797576113760827">"Tillader, at appen kan ringe til telefonnumre uden din indgriben. Dette kan resultere i uventede opkrævninger eller opkald. Bemærk, at appen med denne tilladelse ikke kan ringe til nødopkaldsnumre. Skadelige apps kan koste dig penge ved at foretage opkald uden din bekræftelse."</string>
     <string name="permlab_accessImsCallService" msgid="3574943847181793918">"få adgang til chat-opkaldstjeneste"</string>
@@ -472,7 +471,7 @@
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Tillader, at appen kan læse konfigurationen af ​​Bluetooth på tabletten samt kan oprette og acceptere forbindelser med parrede enheder."</string>
     <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"Giver appen lov til at se fjernsynets Bluetooth-konfiguration og til at oprette og acceptere forbindelser til parrede enheder."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Tillader, at appen kan læse konfigurationen af ​​Bluetooth på telefonen samt kan oprette og acceptere forbindelser med parrede enheder."</string>
-    <string name="permlab_nfc" msgid="4423351274757876953">"kontrollere Near Field Communication"</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"administrere Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Tillader, at appen kan kommunikere med NFC-tags (Near Field Communication), -kort og -læsere."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"deaktivere din skærmlås"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Tillader, at appen kan deaktivere tastaturlåsen og anden form for tilknyttet adgangskodesikkerhed. Telefonen deaktiverer f.eks. tastaturlåsen ved indgående telefonopkald og aktiverer tastaturlåsen igen, når opkaldet er afsluttet."</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Registrering af fingeraftryk fik timeout. Prøv igen."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingeraftrykshandlingen blev annulleret."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Du har prøvet for mange gange. Prøv igen senere."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Prøv igen."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Fingeraftryk <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
@@ -558,7 +559,7 @@
     <string name="permlab_access_notification_policy" msgid="4247510821662059671">"have adgang til Forstyr ikke"</string>
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Giver appen tilladelse til at læse og skrive konfigurationen af Forstyr ikke."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Angiv regler for adgangskoder"</string>
-    <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrollér længden samt tilladte tegn i adgangskoder og pinkoder til skærmlåsen."</string>
+    <string name="policydesc_limitPassword" msgid="2502021457917874968">"Tjek længden samt tilladte tegn i adgangskoder og pinkoder til skærmlåsen."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Overvåg forsøg på oplåsning af skærm"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Overvåg antallet af forkert indtastede adgangskoder, når du låser skærmen op, og lås din tablet, eller slet alle data i den, hvis der er indtastet for mange forkerte adgangskoder."</string>
     <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Overvåg antallet af forkert indtastede adgangskoder ved oplåsning af skærmen, og lås tv\'et eller slet alle dets data, hvis der indtastes for mange forkerte adgangskoder."</string>
@@ -1291,7 +1292,7 @@
     <string name="vpn_text" msgid="1610714069627824309">"Tryk for at administrere netværket."</string>
     <string name="vpn_text_long" msgid="4907843483284977618">"Forbundet til <xliff:g id="SESSION">%s</xliff:g>. Tryk for at administrere netværket."</string>
     <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Opretter forbindelse til altid aktiveret VPN…"</string>
-    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN er forbundet"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Altid aktiveret VPN er forbundet"</string>
     <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Forbindelsen til altid aktiveret VPN er afbrudt"</string>
     <string name="vpn_lockdown_error" msgid="6009249814034708175">"Fejl i altid aktiveret VPN"</string>
     <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tryk for at konfigurere"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 6d1ebc8..c158ad5 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Updates"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Netzwerkstatus"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Netzwerkwarnungen"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Netzwerk verfügbar"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-Status"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Geräteverwaltung"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Warnmeldungen"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Zeitüberschreitung für Fingerabdruck. Versuche es erneut."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerabdruckvorgang abgebrochen"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Zu viele Versuche. Versuche es später erneut."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Bitte versuche es erneut."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index d61fdca..10db204 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Ενημερώσεις"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Κατάσταση δικτύου"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Ειδοποιήσεις δικτύου"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Το δίκτυο είναι διαθέσιμο"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Κατάσταση VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Διαχείριση συσκευής"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Ειδοποιήσεις"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Λήξη χρονικού ορίου μοναδικού χαρακτηριστικού. Δοκιμάστε ξανά."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Η λειτουργία μοναδικού χαρακτηριστικού ακυρώθηκε."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Πάρα πολλές προσπάθειες. Δοκιμάστε ξανά αργότερα."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Δοκιμάστε ξανά."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Δάχτυλο <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index c076e16..8a1b42c 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Updates"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Network status"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Network alerts"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Network available"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN status"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Device administration"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerprint operation cancelled."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Too many attempts. Try again later."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Try again."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index c076e16..8a1b42c 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Updates"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Network status"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Network alerts"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Network available"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN status"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Device administration"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerprint operation cancelled."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Too many attempts. Try again later."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Try again."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index c076e16..8a1b42c 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Updates"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Network status"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Network alerts"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Network available"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN status"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Device administration"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerprint operation cancelled."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Too many attempts. Try again later."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Try again."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index ab195df..ba5af6d 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Actualizaciones"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Estado de la red"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertas de red"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Red disponible"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Estado de VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administración del dispositivo"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Finalizó el tiempo de espera para la huella digital. Vuelve a intentarlo."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Se canceló la operación de huella digital."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiados intentos. Vuelve a intentarlo más tarde."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Vuelve a intentarlo."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
@@ -1754,7 +1755,7 @@
     <string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opciones de autocompletar"</string>
     <string name="autofill_save_accessibility_title" msgid="7244365268417107822">"Guardar para Autocompletar"</string>
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"El contenido no puede autocompletarse"</string>
-    <string name="autofill_picker_no_suggestions" msgid="3908514303773350735">"Sin sugerencias de Autocompletar"</string>
+    <string name="autofill_picker_no_suggestions" msgid="3908514303773350735">"No hay sugerencias de Autocompletar"</string>
     <plurals name="autofill_picker_some_suggestions" formatted="false" msgid="5506565809835815274">
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugerencias de Autocompletar</item>
       <item quantity="one">Una sugerencia de Autocompletar</item>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 0891aa2..9369ee5 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Actualizaciones"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Estado de la red"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertas de la red"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Red disponible"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Estado de la VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administración del dispositivo"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Se ha alcanzado el tiempo de espera de la huella digital. Vuelve a intentarlo."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Se ha cancelado la operación de huella digital."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiados intentos. Vuelve a intentarlo más tarde."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Vuelve a intentarlo."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 95d6bb0..d85a37f 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Värskendused"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Võrgu olek"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Võrguteavitused"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Võrk on saadaval"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-i olek"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Seadme haldamine"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Teatised"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Sõrmejälje riistvara taimeri ajalõpp. Proovige uuesti."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Sõrmejälje toiming tühistati."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Liiga palju katseid. Proovige hiljem uuesti."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Proovige uuesti."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Sõrm <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 2208e91..2abdeef 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Eguneratzeak"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Sarearen egoera"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Sarearen alertak"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Sare bat erabilgarri dago"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN egoera"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Gailuen administrazioa"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Abisuak"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Hatz-marka digitalak prozesatzeko denbora-muga gainditu da. Saiatu berriro."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Hatz-markaren eragiketa bertan behera utzi da."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Saiakera gehiegi egin dituzu. Saiatu berriro geroago."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Saiatu berriro."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> hatza"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 942bc88..319a5a1 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"مهلت زمانی ثبت اثر انگشت به پایان رسید. دوباره امتحان کنید."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"عملکرد اثر انگشت لغو شد."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"تلاش‌های زیادی انجام شده است. بعداً دوباره امتحان کنید."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"دوباره امتحان کنید."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"انگشت <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 69b4b3c..f8fd2b3 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Päivitykset"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Verkon tila"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Verkkoilmoitukset"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Verkko käytettävissä"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-tila"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Laitteen järjestelmänvalvonta"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Ilmoitukset"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Sormenjälkitunnistimen toiminta aikakatkaistiin. Yritä uudelleen."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Sormenjälkitoiminto peruutettiin."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Liian monta yritystä. Yritä myöhemmin uudelleen."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Yritä uudelleen."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Sormi <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 7e62890..15071e9 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Le temps attribué pour lire l\'empreinte est écoulé. Veuillez essayer de nouveau."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Opération d\'empreinte numérique annulée."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Trop de tentatives. Veuillez réessayer plus tard."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Réessayer."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Doigt <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 2f6ea57..6a1b8b7 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Mises à jour"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"État du réseau"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertes réseau"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Réseau disponible"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"État du VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Gestion de l\'appareil"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Délai de détection de l\'empreinte numérique expiré. Veuillez réessayer."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Opération d\'empreinte numérique annulée."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Trop de tentatives. Veuillez réessayer plus tard."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Veuillez réessayer."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Doigt <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index aeae75b..cfbb5c3 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Actualizacións"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Estado da rede"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertas de rede"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"A rede está dispoñible"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Estado da VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administración de dispositivos"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Esgotouse o tempo de espera da impresión dixital. Téntao de novo."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Cancelouse a operación da impresión dixital."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiados intentos. Téntao de novo máis tarde."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Téntao de novo."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index ab0edb8..e78dfa9 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"અપડેટ્સ"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"નેટવર્ક સ્થિતિ"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"નેટવર્ક ચેતવણીઓ"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"નેટવર્ક ઉપલબ્ધ છે"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN સ્થિતિ"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"ઉપકરણ વ્યવસ્થાપન"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"ચેતવણીઓ"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ફિંગરપ્રિન્ટનો સમય બાહ્ય થયો. ફરી પ્રયાસ કરો."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ફિંગરપ્રિન્ટ ઓપરેશન રદ કર્યું."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ઘણા બધા પ્રયત્નો. પછીથી ફરી પ્રયાસ કરો."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ફરી પ્રયાસ કરો."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"આંગળી <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index f7bcbc6..30be4d5 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"अपडेट"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"नेटवर्क की स्थिति"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"नेटवर्क संबंधी सूचनाएं"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"नेटवर्क उपलब्ध है"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN की स्थिति"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"डिवाइस का व्‍यवस्‍थापन"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"सूचनाएं"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फ़िंगरप्रिंट का समय समाप्त हो गया. पुनः प्रयास करें."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"फ़िंगरप्रिंट क्रियान्वयन रोक दिया गया."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"बहुत अधिक प्रयास कर लिए गए हैं. बाद में पुन: प्रयास करें."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"पुन: प्रयास करें."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"अंगुली <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index b2c325f..9eaf027 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -263,8 +263,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Ažuriranja"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Mrežni status"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Mrežna upozorenja"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Mreža je dostupna"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Status VPN-a"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administracija uređaja"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string>
@@ -495,6 +494,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Isteklo je vrijeme čekanja za otisak prsta. Pokušajte ponovo."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja otiska prsta otkazana je."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Pokušajte ponovo."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 64e1c8a..1270eb3 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Az ujjlenyomat-beolvasási műveletkor időtúllépés történt. Próbálkozzon újra."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Ujjlenyomattal kapcsolatos művelet megszakítva"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Túl sok próbálkozás. Próbálja újra később."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Próbálkozzon újra."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g>. ujj"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index be3cfdd..28a01c0 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Թարմացումներ"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Ցանցի կարգավիճակ"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Ցանցային զգուշացումներ"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Ցանցը հասանելի է"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN կարգավիճակ"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Սարքի կառավարում"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Ծանուցումներ"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Մատնահետքի գրանցման ժամանակը սպառվել է: Փորձեք նորից:"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Իսկորոշումը մատնահետքի միջոցով չեղարկվեց:"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Չափից շատ փորձ եք կատարել: Փորձեք նորից քիչ հետո:"</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Փորձեք նորից:"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Մատնահետք <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 2fda698..e7d160b 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Update"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Status jaringan"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Notifikasi jaringan"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Jaringan tersedia"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Status VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administrasi perangkat"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Notifikasi"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Waktu sidik jari habis. Coba lagi."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operasi sidik jari dibatalkan."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Terlalu banyak upaya. Coba lagi nanti."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Coba lagi."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Jari <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index b43b21e..8313cba12 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Uppfærslur"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Staða netkerfis"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Viðvaranir netkerfis"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Net í boði"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Staða VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Stjórnun tækis"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Tilkynningar"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tímamörk runnu út fyrir fingrafar. Reyndu aftur."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Hætt við fingrafarsaðgerð."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Of margar tilraunir. Reyndu aftur síðar."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Reyndu aftur."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Fingur <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index b9af901..53c00b2 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Aggiornamenti"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Stato della rete"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Avvisi di rete"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Rete disponibile"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Stato della VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Amministrazione dispositivo"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Avvisi"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Timeout impronta digitale. Riprova."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operazione associata all\'impronta digitale annullata."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Troppi tentativi. Riprova più tardi."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Riprova."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dito <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 29579ec..7761209 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -266,8 +266,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"עדכונים"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"סטטוס הרשת"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"התראות רשת"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"יש רשת זמינה"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"‏סטטוס ה-VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"ניהול מכשירים"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"התראות"</string>
@@ -498,6 +497,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"חלף הזמן הקצוב לטביעת אצבע. נסה שוב."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"פעולת טביעת האצבע בוטלה."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"יותר מדי ניסיונות. נסה שוב מאוחר יותר."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"נסה שוב."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"אצבע <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 3f5044b..b3af109 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"アップデート"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"ネットワークのステータス"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"ネットワーク通知"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"ネットワークを利用できます"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN のステータス"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"端末管理"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋の読み取りがタイムアウトになりました。もう一度お試しください。"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"指紋の操作をキャンセルしました。"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"所定の回数以上間違えました。しばらくしてからもう一度お試しください。"</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"もう一度お試しください。"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"指紋<xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index c193ee8..1301220 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"თითის ანაბეჭდის ლოდინის დრო ამოიწურა. სცადეთ ხელახლა."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"თითის ანაბეჭდის აღების ოპერაცია გაუქმდა."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ძალიან ბევრი მცდელობა იყო. სცადეთ მოგვიანებით."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ხელახლა სცადეთ"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"თითი <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index c2cf55f..4c9cd5d 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Жаңартылған нұсқалар"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Желі күйі"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Желі дабылдары"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Желі қолжетімді"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN күйі"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Құрылғыны басқару"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Дабылдар"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Саусақ ізін күту уақыты бітті. Әрекетті қайталаңыз."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Саусақ ізі операциясынан бас тартылған."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Талпыныстар тым көп. Кейінірек қайталап көріңіз."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Әрекетті қайталаңыз."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> саусағы"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index d164467..213f305 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"បច្ចុប្បន្នភាព"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"ស្ថានភាព​បណ្តាញ"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"ការ​ជូនដំណឹង​អំពី​បណ្តាញ"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"មានបណ្តាញ"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"ស្ថានភាព VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"ការ​គ្រប់គ្រង​ឧបករណ៍"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"ការ​ជូនដំណឹង"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ការផ្តិតម្រាមដៃបានអស់ពេល។ សូមព្យាយាមម្តងទៀត។"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"បានបោះបង់ប្រតិបត្តិការស្នាមម្រាមដៃ។"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ព្យាយាមចូលច្រើនពេកហើយ។ សូមព្យាយាមម្តងទៀតពេលក្រោយ។"</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ព្យាយាមម្ដងទៀត។"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ម្រាមដៃ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 1581520..9a6e89a 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ಬೆರಳಚ್ಚು ಅವಧಿ ಮೀರಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ಬೆರಳಚ್ಚು ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಮಾಡಲಾಗಿದೆ."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ಹಲವಾರು ಪ್ರಯತ್ನಗಳು. ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ಫಿಂಗರ್ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 266ecf1..cc7aff3 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"지문 인식 시간이 초과되었습니다. 다시 시도하세요."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"지문 인식 작업이 취소되었습니다."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"시도 횟수가 너무 많습니다. 나중에 다시 시도하세요."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"다시 시도해 보세요."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"손가락 <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 5833d04..0f5f403 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Жаңыртуулар"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Тармактын абалы"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Тармактын эскертүүлөрү"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Жеткиликтүү тармактар"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN абалы"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Түзмөктү администрациялоо"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Эскертүүлөр"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Манжа изин күтүү мөөнөтү бүттү. Кайра аракет кылыңыз."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Манжа изи иш-аракети жокко чыгарылды."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Аракеттер өтө көп болду. Кийинчерээк кайра аракет кылыңыз."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Кайра бир аракеттениңиз."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> манжасы"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index c29fe19..f6eb279 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"ອັບເດດ"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"ສະຖານະເຄືອຂ່າຍ"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"ແຈ້ງເຕືອນເຄືອຂ່າຍ"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"ມີເຄືອຂ່າຍທີ່ສາມາດໃຊ້ໄດ້"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"ສະຖານະ VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"ການເບິ່ງແຍງອຸປະກອນ"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"ການເຕືອນ"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ເວ​ລາ​ລາຍ​ນີ້ວ​ມື​ບໍ່​ເຂົ້າ​ເຖິງ​ໄດ້. ລອງ​ໃໝ່​ອີກ."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ຍົກ​ເລີກ​ການ​ດຳ​ເນີນ​ການ​ລາຍ​ນີ້ວ​ມື​ແລ້ວ."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ມີ​ຄວາມ​ພະ​ຍາ​ຍາມ​ຫຼາຍ​ຄັ້ງ​ເກີນ​ໄປ. ລອງ​ໃໝ່​ພາຍ​ຫຼັງ."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ລອງໃໝ່ອີກຄັ້ງ."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ນີ້ວ​ມື <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index d5924bc..7838067 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -266,8 +266,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Naujiniai"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Tinklo būsena"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Tinklo įspėjimai"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Tinklas pasiekiamas"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN būsena"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Įrenginio administravimas"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Įspėjimai"</string>
@@ -498,6 +497,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Baigėsi kontrolinio kodo nustatymo skirtasis laikas. Bandykite dar kartą."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Kontrolinio kodo operacija atšaukta."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Per daug bandymų. Vėliau bandykite dar kartą."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Bandykite dar kartą."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> pirštas"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 100f3df..b71a220 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -263,8 +263,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Atjauninājumi"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Tīkla statuss"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Tīkla brīdinājumi"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Tīkls ir pieejams"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN statuss"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Ierīces administrēšana"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Brīdinājumi"</string>
@@ -495,6 +494,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Pirkstu nospiedumu nolasīšanas aparatūras noildze. Mēģiniet vēlreiz."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Nospieduma darbība neizdevās."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Pārāk daudz mēģinājumu. Vēlāk mēģiniet vēlreiz."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Mēģiniet vēlreiz."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g>. pirksts"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 38eb49b..febacb2 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Ажурирања"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Статус на мрежа"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Известувања на мрежа"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Има достапна мрежа"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-статус"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Управување со уред"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Предупредувања"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Се достигна времето на истекување на отпечатокот. Обидете се повторно."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Операцијата со отпечаток од прст се откажа."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Премногу обиди. Обидете се повторно подоцна."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Обидете се повторно."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Прст <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index ddd6117..03e21aa 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"വിരലടയാളം നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ഫിംഗർപ്രിന്റ് പ്രവർത്തനം റദ്ദാക്കി."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"നിരവധി തവണ ശ്രമിച്ചു. പിന്നീട് വീണ്ടും ശ്രമിക്കുക."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"വീണ്ടും ശ്രമിക്കൂ."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"കൈവിരൽ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 8fdad78..7a8e821 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Шинэчлэлтүүд"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Сүлжээний төлөв"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Сүлжээний сануулга"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Сүлжээ боломжтой"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN төлөв"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Төхөөрөмжийн удирдлага"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Сануулга"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Хурууны хээ оруулах хугацаа өнгөрсөн байна. Дахин оруулна уу."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Хурууны хээний бүртгэл амжилтгүй боллоо."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Хэтэрхий олон оролдлоо.  Түр хүлээгээд дахин оролдоно уу."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Дахин оролдно уу."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Хурууны хээ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index ebdf0e4..d44f900 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"अद्यतने"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"नेटवर्क स्थिती"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"नेटवर्क सूचना"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"नेटवर्क उपलब्ध"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN स्थिती"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"डिव्हाइस प्रशासन"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"सूचना"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फिंगरप्रिंट कालबाह्य झाले. पुन्हा प्रयत्न करा."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"फिंगरप्रिंट ऑपरेशन रद्द झाले."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"खूप प्रयत्न केले. नंतर पुन्हा प्रयत्न करा."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"पुन्हा प्रयत्न करा."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> बोट"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 6ec0fe3..4f0f557 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tamat masa cap jari dicapai. Cuba lagi."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Pengendalian cap jari dibatalkan."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Terlalu banyak percubaan. Cuba sebentar lagi."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Cuba lagi."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Jari <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 53ae1ca..f801df5 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"အပ်ဒိတ်များ"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"ကွန်ရက် အခြေအနေ"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"ကွန်ရက် သတိပေးချက်များ"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"ကွန်ရက်ချိတ်ဆက်မှု ရရှိနိုင်ပါသည်"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN အခြေအနေ"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"စက်ပစ္စည်း စီမံခန့်ခွဲမှု"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"သတိပေးချက်များ"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"လက်ဗွေရာအချိန်ကုန် သွားပါသည်။ ထပ်မံကြိုးစားပါ။"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"လက်ဗွေရာ လုပ်ငန်း ဖျက်သိမ်းခဲ့၏။"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ကြိုးစာမှု အကြိမ်များနေ၏။ နောက်မှ ထပ်မံကြိုးစားပါ။"</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ပြန်ကြိုးစားပါ"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"လက်ချောင်း <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index f0c5a98..f9b73e0 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tidsavbrudd for fingeravtrykk er nådd. Prøv på nytt."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingeravtrykk-operasjonen ble avbrutt."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"For mange forsøk. Prøve på nytt senere."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Prøv igjen."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index a10724b..30c6e8c 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"औँठाछापको समय सकिएको छ। फेरि प्रयास गर्नुहोस्।"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"औँठाछाप सञ्चालन रद्द गरियो।"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"धेरै प्रयासहरू। केहि समय पछि पुन: प्रयास गर्नुहोला"</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"पुन: प्रयास गर्नुहोला।"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"औंला <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index f30b85c..f102451 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Updates"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Netwerkstatus"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Netwerkmeldingen"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Netwerk beschikbaar"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-status"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Apparaatbeheer"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Meldingen"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Time-out bereikt voor vingerafdruk. Probeer het opnieuw."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Vingerafdrukbewerking geannuleerd."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Te veel pogingen. Probeer het later opnieuw."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Probeer het opnieuw."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Vinger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 7eab363..4a4bb62 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋ ਗਿਆ ਹੈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ਫਿੰਗਰ"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ਬਹੁਤ ਸਾਰੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ. ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ਉਂਗਲ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 22133df..72cc52a 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -266,8 +266,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Aktualizacje"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Stan sieci"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alerty dotyczące sieci"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Sieć dostępna"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Stan sieci VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administracja urządzeniem"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerty"</string>
@@ -498,6 +497,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Osiągnięto limit czasu odczytu linii papilarnych. Spróbuj ponownie."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Odczyt odcisku palca został anulowany."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Zbyt wiele prób. Spróbuj ponownie później."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Spróbuj ponownie."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Odcisk palca <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index a2dc606..7157dab 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operação de impressão digital cancelada."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Excesso de tentativas. Tente novamente mais tarde."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tente novamente."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 641c115..026a866 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Atualizações"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Estado da rede"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertas da rede"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Rede disponível"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Estado da VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administração do dispositivo"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Foi atingido o limite de tempo da impressão digital. Tente novamente."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operação de impressão digital cancelada."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiadas tentativas. Tente novamente mais tarde."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tente novamente."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index a2dc606..7157dab 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operação de impressão digital cancelada."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Excesso de tentativas. Tente novamente mais tarde."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tente novamente."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index b093298..1a3e0c5 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -263,8 +263,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Actualizări"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Starea rețelei"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alerte privind rețeaua"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Rețea disponibilă"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Stare VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administrarea dispozitivului"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerte"</string>
@@ -495,6 +494,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Timpul pentru amprentare a expirat. Încercați din nou."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operațiunea privind amprenta a fost anulată."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Prea multe încercări. Încercați din nou mai târziu."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Încercați din nou."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Degetul <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 61f6dc1..ab91c0a 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -266,8 +266,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Обновления"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Статус сети"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Оповещения сети"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Сеть доступна"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Статус VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Управление устройством"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Уведомления"</string>
@@ -498,6 +497,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Превышено время ожидания. Повторите попытку."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Операция с отпечатком отменена."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Слишком много попыток. Повторите позже."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Повторите попытку."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Палец <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 81f735e..71466bc 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"යාවත්කාලීන කිරීම්"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"ජාල තත්ත්වය"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"ජාල ඇඟවීම්"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"ජාලය ලබා ගැනීමට හැකිය"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN තත්ත්වය"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"උපාංග පරිපාලනය"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"ඇඟවීම්"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ඇඟිලි සලකුණු කාල නිමාව ළඟා විය. නැවත උත්සාහ කරන්න."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ඇඟිලි සලකුණු මෙහෙයුම අවලංගු කරන ලදී."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"උත්සාහයන් ඉතා වැඩි ගණනකි. කරුණාකර පසුව නැවත උත්සාහ කරන්න."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"නැවත උත්සාහ කරන්න."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ඇඟිලි <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 01de743..08efcd9 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -498,6 +498,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit rozpoznania odtlačku vypršal. Skúste to znova."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operácia týkajúca sa odtlačku prsta bola zrušená"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Príliš veľa pokusov. Skúste to znova neskôr."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Skúste to znova"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Prst: <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 9a41492e..9aa39e9 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -266,8 +266,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Posodobitve"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Stanje omrežja"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Opozorila omrežja"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Omrežje je na voljo"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Stanje omrežja VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Skrbništvo naprave"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Opozorila"</string>
@@ -498,6 +497,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Dosežena časovna omejitev za prstni odtis. Poskusite znova."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Dejanje s prstnim odtisom je bilo preklicano."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Preveč poskusov. Poskusite znova pozneje."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Poskusite znova."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 2a030a2..b9b8e98 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Përditësimet"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Statusi i rrjetit"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Sinjalizimet e rrjetit"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Ka rrjet të disponueshëm"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Statusi i VPN-së"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administrimi i pajisjes"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Sinjalizimet"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Koha e veprimit për gjurmën e gishtit skadoi. Provo përsëri."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operacioni i gjurmës së gishtit u anulua."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Keni bërë shumë tentativa. Provo përsëri më vonë."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Provo përsëri."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Gishti <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 8e314f8..b85df9f 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -263,8 +263,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Ажурирања"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Статус мреже"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Обавештења у вези са мрежом"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Мрежа је доступна"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Статус VPN-а"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Администрирање уређаја"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Обавештења"</string>
@@ -495,6 +494,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Временско ограничење за отисак прста је истекло. Пробајте поново."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Радња са отиском прста је отказана."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Превише покушаја. Пробајте поново касније."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Пробајте поново."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Прст <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 253dcac..c6865a1 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tidsgränsen för fingeravtrycket har uppnåtts. Försök igen."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingeravtrycksåtgärden avbröts."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Du har gjort för många försök. Försök igen senare."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Försök igen."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 86ec23b..55da8d9 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -207,7 +207,7 @@
     <string name="reboot_to_update_prepare" msgid="6305853831955310890">"Inajiandaa kusasisha..."</string>
     <string name="reboot_to_update_package" msgid="3871302324500927291">"Inachakata kifurushi cha kusasisha…"</string>
     <string name="reboot_to_update_reboot" msgid="6428441000951565185">"Inazima na kuwasha upya..."</string>
-    <string name="reboot_to_reset_title" msgid="4142355915340627490">"Rejesha data ya mwanzo"</string>
+    <string name="reboot_to_reset_title" msgid="4142355915340627490">"Rejesha mipangilio ya kiwandani"</string>
     <string name="reboot_to_reset_message" msgid="2432077491101416345">"Inazima na kuwasha upya..."</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Inafunga..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Kompyuta kibao yako itazima."</string>
@@ -258,8 +258,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Taarifa"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Hali ya mtandao"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Arifa za mtandao"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Mtandao unapatikana"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Hali ya VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Udhibiti wa kifaa"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Arifa"</string>
@@ -490,6 +489,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Muda wa kitambulisho umekwisha. Jaribu tena."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Utendaji wa kitambulisho imeghairiwa."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Majaribio mengi mno. Jaribu tena baadaye."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Jaribu tena."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Kitambulisho <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
@@ -569,7 +570,7 @@
     <string name="policylab_forceLock" msgid="2274085384704248431">"Kufunga skrini"</string>
     <string name="policydesc_forceLock" msgid="1141797588403827138">"Kudhibiti jinsi na wakati skrini inapofunga."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Kufuta data yote"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Futa data ya kompyuta kibao bila ilani kwa kurejesha mipangilio ya mwanzo."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Futa data ya kompyuta kibao bila ilani kwa kurejesha mipangilio ambayo kompyuta ilitoka nayo kiwandani."</string>
     <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"Futa data ya runinga bila onyo kwa kurejesha katika hali iliyotoka nayo kiwandani."</string>
     <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Kufuta data ya simu bila ilani kwa kurejesha data ambayo kifaa kilitoka nayo kiwandani"</string>
     <string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"Futa data yote ya mtumiaji"</string>
@@ -749,9 +750,9 @@
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Umekosea katika kuweka mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%2$d</xliff:g> bila kufaulu, utaulizwa kufungua kompyuta yako ndogo kwa kuingia kwa Google.\n\n Jaribu tena katika sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Umekosea kuchora mchoro wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukikosea majaribio mengine <xliff:g id="NUMBER_1">%2$d</xliff:g>, utaombwa ufungue runinga yako ukitumia Google.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Umekosea kuchora mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%2$d</xliff:g> yasiyofaulu, utaulizwa kufungua simu kupitia kuingia Google.\n\n Jaribu tena katika sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
-    <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Umejaribu kufungua kompyuta ndogo kwa njia isiyo sahihi mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Baada ya zaidi ya <xliff:g id="NUMBER_1">%2$d</xliff:g> majaribio yasiyofanikiwa, kompyuta ndogo itawekwa upya kwa kiwanda chaguo-msingi na data yote ya mtumiaji itapotea."</string>
+    <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Umejaribu kufungua kompyuta kibao kwa njia isiyo sahihi mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukijaribu tena mara <xliff:g id="NUMBER_1">%2$d</xliff:g> bila mafanikio, kompyuta ndogo itarejeshwa kwenye mipangilio iliyotoka nayo kiwandani na data yote iliyomo itafutwa."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"Umekosea majaribio ya kufungua runinga mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukikosea majaribio <xliff:g id="NUMBER_1">%2$d</xliff:g> zaidi, runinga itarejeshwa katika hali iliyotoka nayo kiwandani na data yote ya watumiaji itafutwa."</string>
-    <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Umejaribu kufungua simu kwa njia isiyo sahihi mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%2$d</xliff:g> zaidi yasiyofanikiwa, simu itawekwa upya kwa kiwanda chaguo-msingi na data yote ya mtumiaji itapotea."</string>
+    <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Umejaribu kufungua simu kwa njia isiyo sahihi mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukijaribu tena mara <xliff:g id="NUMBER_1">%2$d</xliff:g> bila mafanikio, simu itarejeshwa kwenye mipangilio iliyotoka nayo kiwandani na data yote iliyomo itafutwa."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Umejaribu kufungua kompyuta ndogo kwa njia isiyo sahihi mara <xliff:g id="NUMBER">%d</xliff:g>. Kompyuta ndogo haitaweza kuwekwa upya kwa kiwanda chaguo-msingi."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"Umekosea majaribio ya kufungua runinga mara <xliff:g id="NUMBER">%d</xliff:g>. Sasa runinga itarejeshwa katika mipangilio iliyotoka nayo kiwandani."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Umejaribu kufungua kompyuta ndogo kwa njia isiyo sahihi mara <xliff:g id="NUMBER">%d</xliff:g>. Kompyuta ndogo haitaweza kuwekwa upya kwa kiwanda chaguo-msingi."</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index c832173..6cbfba5 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"புதுப்பிப்புகள்"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"நெட்வொர்க்கின் நிலை"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"நெட்வொர்க் விழிப்பூட்டல்கள்"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"நெட்வொர்க் உள்ளது"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN நிலை"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"சாதன நிர்வாகம்"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"விழிப்பூட்டல்கள்"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"கைரேகைக்கான நேரம் முடிந்தது. மீண்டும் முயலவும்."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"கைரேகை செயல்பாடு ரத்துசெய்யப்பட்டது."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"அதிகமான முயற்சிகள். பிறகு முயற்சிக்கவும்."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"மீண்டும் முயற்சிக்கவும்."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"கைரேகை <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index e2791b7..b3e5e4a 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"వేలిముద్ర గడువు సమయం చేరుకుంది. మళ్లీ ప్రయత్నించండి."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"వేలిముద్ర కార్యాచరణ రద్దయింది."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"చాలా ఎక్కువ ప్రయత్నాలు చేసారు. తర్వాత మళ్లీ ప్రయత్నించండి."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"మళ్లీ ప్రయత్నించండి."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"వేలు <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index b1d40267..c2ae15e 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"การอัปเดต"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"สถานะเครือข่าย"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"การแจ้งเตือนเครือข่าย"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"มีเครือข่ายพร้อมใช้งาน"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"สถานะ VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"การดูแลระบบอุปกรณ์"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"การแจ้งเตือน"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"หมดเวลาใช้ลายนิ้วมือแล้ว โปรดลองอีกครั้ง"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ยกเลิกการทำงานของลายนิ้วมือ"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ดำเนินการหลายครั้งเกินไป ลองอีกครั้งในภายหลัง"</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ลองอีกครั้ง"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"นิ้ว <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 33bb5b1..2ef0c7a 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Mga Update"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Status ng network"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Mga alerto sa network"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Available ang network"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Status ng VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Pamamahala ng device"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Mga Alerto"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Nag-time out ang fingerprint. Subukang muli."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Nakansela ang operasyong ginagamitan ng fingerprint."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Masyadong maraming beses sumubok. Subukang muli sa ibang pagkakataon."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Subukang muli."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Daliri <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 9d4ea40..c3b2001 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Parmak izi için zaman aşımı oluştu. Tekrar deneyin."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Parmak izi işlemi iptal edildi."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Çok fazla deneme yapıldı. Daha sonra tekrar deneyin."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tekrar deneyin."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g>. parmak"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index e6fb07a..a5a289c 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -266,8 +266,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Оновлення"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Статус мережі"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Сповіщення мережі"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Мережа доступна"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Статус мережі VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Адміністрування пристрою"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Сповіщення"</string>
@@ -498,6 +497,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час очікування відбитка минув. Повторіть спробу."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Дію з відбитком скасовано."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Забагато спроб. Спробуйте пізніше."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Повторіть спробу."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Відбиток пальця <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 192a2e9..c16c0c6 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"فنگر پرنٹ کی میعاد ختم ہوگئی۔ دوبارہ کوشش کریں۔"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"فنگر پرنٹ کی کارروائی منسوخ ہوگئی۔"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"کافی زیادہ کوششیں کی گئیں۔ بعد میں دوبارہ کوشش کریں۔"</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"دوبارہ کوشش کریں۔"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"انگلی <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 68cfc85..b2ea945 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Yangilanishlar"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Tarmoq holati"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Tarmoqqa oid bildirgilar"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Tarmoq mavjud"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN holati"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Qurilma boshqaruvi"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Ogohlantirishlar"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Barmoq izini aniqlash vaqti tugab qoldi. Qayta urinib ko‘ring."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Barmoq izi tekshiruvi bekor qilindi."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Urinishlar soni ko‘payib ketdi. Keyinroq qayta urinib ko‘ring."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Qayta urinib ko‘ring."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Barmoq izi <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
@@ -770,7 +771,7 @@
     <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"Tekshirilmoqda…"</string>
     <string name="lockscreen_unlock_label" msgid="737440483220667054">"Qulfdan chiqarish"</string>
     <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"Ovozni yoqish"</string>
-    <string name="lockscreen_sound_off_label" msgid="996822825154319026">"Ovozni o‘chirish"</string>
+    <string name="lockscreen_sound_off_label" msgid="996822825154319026">"Ovozsiz qilish"</string>
     <string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"Grafik kalitni chizish boshlandi"</string>
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Grafik kalit tozalandi"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Katak qo‘shildi"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index dacc9da..504ef5f 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Cập nhật"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Trạng thái mạng"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Cảnh báo mạng"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Có mạng"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Trạng thái VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Quản lý thiết bị"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Cảnh báo"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Đã hết thời gian chờ vân tay. Hãy thử lại."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Thao tác dùng dấu vân tay bị hủy."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Quá nhiều lần thử. Hãy thử lại sau."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Thử lại."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Ngón tay <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index fcb6917..d195de8 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指纹录入操作超时,请重试。"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"指纹操作已取消。"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"尝试次数过多,请稍后重试。"</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"请重试。"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index c8e30e1..4eed27c 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋已逾時。請再試一次。"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"指紋操作已取消。"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"嘗試次數過多,請稍後再試。"</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"再試一次。"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 49fe199..0c4ffad 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -492,6 +492,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋處理作業逾時,請再試一次。"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"指紋作業已取消。"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"嘗試次數過多,請稍後再試。"</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"請再試一次。"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 3e2ca18..2ce9696 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Izibuyekezo"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Isimo senethiwekhi"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Izexwayiso zenethiwekhi"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Inethiwekhi iyatholakala"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Isimo se-VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Ukulawula idivayisi"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Izexwayiso"</string>
@@ -492,6 +491,8 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Kufinyelelwe isikhathi sokuvala sezigxivizo zeminwe. Zama futhi"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Ukusebenza kwezingxivizo zeminwe kukhanseliwe."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Imizamo eminingi kakhulu. Zama futhi emuva kwesikhathi."</string>
+    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+    <skip />
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Zama futhi."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Umunwe ongu-<xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6640102..8e6c402 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2849,6 +2849,11 @@
     <!-- Default data warning level in mb -->
     <integer name="default_data_warning_level_mb">2048</integer>
 
+    <!-- When true, indicates that the vendor's IMS implementation requires a workaround when
+     sending a request to enable or disable the camera while the video session is also
+     paused. -->
+    <bool name="config_useVideoPauseWorkaround">false</bool>
+
     <!-- Whether to send a custom package name with the PSD.-->
     <bool name="config_sendPackageName">false</bool>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 42d3f27..4868774 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2761,81 +2761,80 @@
     <eat-comment />
 
     <public type="attr" name="visibleToInstantApps" id="0x01010531" />
+    <public type="attr" name="font" id="0x01010532" />
+    <public type="attr" name="fontWeight" id="0x01010533" />
+    <public type="attr" name="tooltipText" id="0x01010534" />
+    <public type="attr" name="autoSizeTextType" id="0x01010535" />
+    <public type="attr" name="autoSizeStepGranularity" id="0x01010536" />
+    <public type="attr" name="autoSizePresetSizes" id="0x01010537" />
+    <public type="attr" name="autoSizeMinTextSize" id="0x01010538" />
+    <public type="attr" name="min" id="0x01010539" />
+    <public type="attr" name="rotationAnimation" id="0x0101053a" />
+    <public type="attr" name="layout_marginHorizontal" id="0x0101053b" />
+    <public type="attr" name="layout_marginVertical" id="0x0101053c" />
+    <public type="attr" name="paddingHorizontal" id="0x0101053d" />
+    <public type="attr" name="paddingVertical" id="0x0101053e" />
+    <public type="attr" name="fontStyle" id="0x0101053f" />
+    <public type="attr" name="keyboardNavigationCluster" id="0x01010540" />
+    <public type="attr" name="targetProcesses" id="0x01010541" />
+    <public type="attr" name="nextClusterForward" id="0x01010542" />
+    <public type="attr" name="colorError" id="0x01010543" />
+    <public type="attr" name="focusedByDefault" id="0x01010544" />
+    <public type="attr" name="appCategory" id="0x01010545" />
+    <public type="attr" name="autoSizeMaxTextSize" id="0x01010546" />
+    <public type="attr" name="recreateOnConfigChanges" id="0x01010547" />
+    <public type="attr" name="certDigest" id="0x01010548" />
+    <public type="attr" name="splitName" id="0x01010549" />
+    <public type="attr" name="colorMode" id="0x0101054a" />
+    <public type="attr" name="isolatedSplits" id="0x0101054b" />
+    <public type="attr" name="targetSandboxVersion" id="0x0101054c" />
+    <public type="attr" name="canRequestFingerprintGestures" id="0x0101054d" />
+    <public type="attr" name="alphabeticModifiers" id="0x0101054e" />
+    <public type="attr" name="numericModifiers" id="0x0101054f" />
+    <public type="attr" name="fontProviderAuthority" id="0x01010550" />
+    <public type="attr" name="fontProviderQuery" id="0x01010551" />
+    <public type="attr" name="primaryContentAlpha" id="0x01010552" />
+    <public type="attr" name="secondaryContentAlpha" id="0x01010553" />
+    <public type="attr" name="requiredFeature" id="0x01010554" />
+    <public type="attr" name="requiredNotFeature" id="0x01010555" />
+    <public type="attr" name="autofillHints" id="0x01010556" />
+    <public type="attr" name="fontProviderPackage" id="0x01010557" />
+    <public type="attr" name="importantForAutofill" id="0x01010558" />
+    <public type="attr" name="recycleEnabled" id="0x01010559"/>
+    <public type="attr" name="isStatic" id="0x0101055a" />
+    <public type="attr" name="isFeatureSplit" id="0x0101055b" />
+    <public type="attr" name="singleLineTitle" id="0x0101055c" />
+    <public type="attr" name="fontProviderCerts" id="0x0101055d" />
+    <public type="attr" name="iconTint" id="0x0101055e" />
+    <public type="attr" name="iconTintMode" id="0x0101055f" />
+    <public type="attr" name="maxAspectRatio" id="0x01010560"/>
+    <public type="attr" name="iconSpaceReserved" id="0x01010561"/>
+    <public type="attr" name="defaultFocusHighlightEnabled" id="0x01010562" />
+    <public type="attr" name="persistentWhenFeatureAvailable" id="0x01010563"/>
+    <public type="attr" name="windowSplashscreenContent" id="0x01010564" />
+    <!-- @hide @SystemApi -->
+    <public type="attr" name="requiredSystemPropertyName" id="0x01010565" />
+    <!-- @hide @SystemApi -->
+    <public type="attr" name="requiredSystemPropertyValue" id="0x01010566" />
+    <public type="attr" name="justificationMode" id="0x01010567" />
+    <public type="attr" name="autofilledHighlight" id="0x01010568" />
 
-    <public-group type="attr" first-id="0x01010532">
-        <public name="font" />
-        <public name="fontWeight" />
-        <public name="tooltipText" />
-        <public name="autoSizeTextType" />
-        <public name="autoSizeStepGranularity" />
-        <public name="autoSizePresetSizes" />
-        <public name="autoSizeMinTextSize" />
-        <public name="min" />
-        <public name="rotationAnimation" />
-        <public name="layout_marginHorizontal" />
-        <public name="layout_marginVertical" />
-        <public name="paddingHorizontal" />
-        <public name="paddingVertical" />
-        <public name="fontStyle" />
-        <public name="keyboardNavigationCluster" />
-        <public name="targetProcesses" />
-        <public name="nextClusterForward" />
-        <public name="__removed1" />
-        <public name="colorError" />
-        <public name="focusedByDefault" />
-        <public name="appCategory" />
-        <public name="autoSizeMaxTextSize" />
-        <public name="__removed2" />
-        <public name="recreateOnConfigChanges" />
-        <public name="certDigest" />
-        <public name="splitName" />
-        <public name="colorMode" />
-        <public name="isolatedSplits" />
-        <public name="targetSandboxVersion" />
-        <public name="canRequestFingerprintGestures" />
-        <public name="alphabeticModifiers" />
-        <public name="numericModifiers" />
-        <public name="fontProviderAuthority" />
-        <public name="fontProviderQuery" />
-        <public name="__removed3" />
-        <public name="primaryContentAlpha" />
-        <public name="secondaryContentAlpha" />
-        <public name="requiredFeature" />
-        <public name="requiredNotFeature" />
-        <public name="autofillHints" />
-        <public name="fontProviderPackage" />
-        <public name="importantForAutofill" />
-        <public name="recycleEnabled"/>
-        <public name="isStatic" />
-        <public name="isFeatureSplit" />
-        <public name="singleLineTitle" />
-        <public name="fontProviderCerts" />
-        <public name="iconTint" />
-        <public name="iconTintMode" />
-        <public name="maxAspectRatio"/>
-        <public name="iconSpaceReserved"/>
-        <public name="defaultFocusHighlightEnabled" />
-        <public name="persistentWhenFeatureAvailable"/>
-        <public name="windowSplashscreenContent" />
-        <!-- @hide @SystemApi -->
-        <public name="requiredSystemPropertyName" />
-        <!-- @hide @SystemApi -->
-        <public name="requiredSystemPropertyValue" />
-        <public name="justificationMode" />
-        <public name="autofilledHighlight" />
+    <public type="id" name="textAssist" id="0x01020041" />
+    <public type="id" name="accessibilityActionMoveWindow" id="0x01020042" />
+    <public type="id" name="autofill" id="0x01020043" />
+
+    <public type="string" name="paste_as_plain_text" id="0x01040019" />
+
+    <public-group type="attr" first-id="0x01010569">
     </public-group>
 
     <public-group type="style" first-id="0x010302e0">
     </public-group>
 
-    <public-group type="id" first-id="0x01020041">
-        <public name="textAssist" />
-        <public name="accessibilityActionMoveWindow" />
-        <public name="autofill" />
+    <public-group type="id" first-id="0x01020044">
     </public-group>
 
-    <public-group type="string" first-id="0x01040019">
-        <public name="paste_as_plain_text" />
+    <public-group type="string" first-id="0x0104001a">
     </public-group>
 
   <!-- ===============================================================
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f747d3d..fcabe31 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3225,7 +3225,7 @@
     <skip />
     <!-- Name of notification channel the system post notification to inform the use about apps
          that are drawing ui on-top of other apps (alert-windows) [CHAR LIMIT=NONE] -->
-    <string name="alert_windows_notification_channel_name"><xliff:g id="name" example="Google Maps">%s</xliff:g> displaying over other apps</string>
+    <string name="alert_windows_notification_channel_name">App activity</string>
     <!-- Notification title when an application is displaying ui on-top of other apps
          [CHAR LIMIT=30] -->
     <string name="alert_windows_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> is displaying over other apps</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6e3f0e0..8d2666e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2936,7 +2936,7 @@
   <java-symbol type="id" name="label_error"/>
   <java-symbol type="layout" name="time_picker_text_input_material"/>
   <java-symbol type="drawable" name="btn_keyboard_key_material"/>
-  <java-symbol type="drawable" name="btn_event_material"/>
+  <java-symbol type="drawable" name="btn_clock_material"/>
   <java-symbol type="string" name="time_picker_text_input_mode_description"/>
   <java-symbol type="string" name="time_picker_radial_mode_description"/>
 
@@ -3005,7 +3005,7 @@
   <java-symbol type="bool" name="enable_pbap_pce_profile" />
 
   <java-symbol type="integer" name="default_data_warning_level_mb" />
-
+  <java-symbol type="bool" name="config_useVideoPauseWorkaround" />
   <java-symbol type="bool" name="config_sendPackageName" />
   <java-symbol type="string" name="config_helpPackageNameKey" />
   <java-symbol type="string" name="config_helpPackageNameValue" />
diff --git a/core/tests/coretests/res/layout/messaging_linear_layout_test.xml b/core/tests/coretests/res/layout/messaging_linear_layout_test.xml
index 8ba3e07..9e70ca3 100644
--- a/core/tests/coretests/res/layout/messaging_linear_layout_test.xml
+++ b/core/tests/coretests/res/layout/messaging_linear_layout_test.xml
@@ -19,7 +19,6 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:maxHeight="300px"
     android:spacing="5px">
 
 </com.android.internal.widget.MessagingLinearLayout>
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/app/LoaderLifecycleTest.java b/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
index 1850d57..c83e798 100644
--- a/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
+++ b/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
@@ -17,6 +17,13 @@
 
 package android.app;
 
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertNotSame;
+import static junit.framework.TestCase.assertSame;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 import android.content.Context;
 import android.os.Handler;
 import android.os.Parcelable;
@@ -24,14 +31,11 @@
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.util.ArrayMap;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import static junit.framework.TestCase.assertNotNull;
-import static junit.framework.TestCase.assertNotSame;
-import static junit.framework.TestCase.assertSame;
-
 @RunWith(AndroidJUnit4.class)
 public class LoaderLifecycleTest {
     @Rule
@@ -203,6 +207,16 @@
 
             // Test that the fragments are in the configuration we expect
             final Fragment restoredOne = fm2.findFragmentByTag("one");
+            try {
+                restoredOne.getLoaderManager();
+                fail("A restored fragment on the back stack doesn't have a host, so it should "
+                        + "throw an exception");
+            } catch (IllegalStateException e) {
+                // expected
+            }
+            fm2.popBackStackImmediate();
+            // Now restoredOne should be added and should be in a good state.
+            assertTrue(restoredOne.isAdded());
             final LoaderManager lm2 = restoredOne.getLoaderManager();
 
             assertSame("didn't get same LoaderManager instance back", lm2, lm1);
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 33a0493..1ffc1b3 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -1317,24 +1317,8 @@
             return;
         }
         Runtime.getRuntime().gc();
-
-        final String packageName = ip.pkg.packageName;
-        Log.i(TAG, "Deleting package : " + packageName);
-
-        ApplicationInfo info = null;
         try {
-            info = getPm().getApplicationInfo(packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES);
-        } catch (NameNotFoundException ignored) {
-        }
-
-        DeleteObserver observer = new DeleteObserver(packageName);
-        getPm().deletePackage(packageName, observer, PackageManager.DELETE_ALL_USERS);
-        observer.waitForCompletion(MAX_WAIT_TIME);
-
-        try {
-            if (info != null) {
-                assertUninstalled(info);
-            }
+            cleanUpInstall(ip.pkg.packageName);
         } finally {
             File outFile = new File(ip.pkg.codePath);
             if (outFile != null && outFile.exists()) {
@@ -1349,16 +1333,15 @@
         }
         Log.i(TAG, "Deleting package : " + pkgName);
         try {
-            ApplicationInfo info = getPm().getApplicationInfo(pkgName,
+            final ApplicationInfo info = getPm().getApplicationInfo(pkgName,
                     PackageManager.MATCH_UNINSTALLED_PACKAGES);
-
             if (info != null) {
                 DeleteObserver observer = new DeleteObserver(pkgName);
                 getPm().deletePackage(pkgName, observer, PackageManager.DELETE_ALL_USERS);
                 observer.waitForCompletion(MAX_WAIT_TIME);
                 assertUninstalled(info);
             }
-        } catch (NameNotFoundException e) {
+        } catch (IllegalArgumentException | NameNotFoundException e) {
         }
     }
 
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
index ad8221b..620acae 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
@@ -18,6 +18,7 @@
 
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 import android.support.test.filters.SmallTest;
@@ -27,6 +28,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 import java.io.BufferedReader;
@@ -70,18 +72,70 @@
                 times[i][j] = uids[i] * freqs[j] * 10;
             }
         }
-        final String[] uidsTimesLines = getUidTimesLines(uids, times);
-        final String[] lines = new String[uidsTimesLines.length + 1];
-        System.arraycopy(uidsTimesLines, 0, lines, 0, uidsTimesLines.length);
-        lines[uidsTimesLines.length] = null;
         when(mBufferedReader.readLine())
-                .thenReturn(getFreqsLine(freqs), lines);
+                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, times));
         mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
         verify(mCallback).onCpuFreqs(freqs);
         for (int i = 0; i < uids.length; ++i) {
             verify(mCallback).onUidCpuFreqTime(uids[i], times[i]);
         }
         verifyNoMoreInteractions(mCallback);
+
+        // Verify that a second call will only return deltas.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] newTimes1 = new long[uids.length][freqs.length];
+        for (int i = 0; i < uids.length; ++i) {
+            for (int j = 0; j < freqs.length; ++j) {
+                newTimes1[i][j] = (times[i][j] + uids[i] + freqs[j]) * 10;
+            }
+        }
+        when(mBufferedReader.readLine())
+                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes1));
+        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
+        verify(mCallback).onCpuFreqs(freqs);
+        for (int i = 0; i < uids.length; ++i) {
+            verify(mCallback).onUidCpuFreqTime(uids[i], subtract(newTimes1[i], times[i]));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that calling with a null callback doesn't result in any crashes
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] newTimes2 = new long[uids.length][freqs.length];
+        for (int i = 0; i < uids.length; ++i) {
+            for (int j = 0; j < freqs.length; ++j) {
+                newTimes2[i][j] = (newTimes1[i][j] + uids[i] * freqs[j]) * 10;
+            }
+        }
+        when(mBufferedReader.readLine())
+                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes2));
+        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, null);
+        verifyZeroInteractions(mCallback);
+
+        // Verify that the readDelta call will only return deltas when
+        // the previous call had null callback.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] newTimes3 = new long[uids.length][freqs.length];
+        for (int i = 0; i < uids.length; ++i) {
+            for (int j = 0; j < freqs.length; ++j) {
+                newTimes3[i][j] = (newTimes2[i][j] * (uids[i] + freqs[j])) * 10;
+            }
+        }
+        when(mBufferedReader.readLine())
+                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes3));
+        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
+        verify(mCallback).onCpuFreqs(freqs);
+        for (int i = 0; i < uids.length; ++i) {
+            verify(mCallback).onUidCpuFreqTime(uids[i], subtract(newTimes3[i], newTimes2[i]));
+        }
+        verifyNoMoreInteractions(mCallback);
+    }
+
+    private long[] subtract(long[] a1, long[] a2) {
+        long[] val = new long[a1.length];
+        for (int i = 0; i < val.length; ++i) {
+            val[i] = a1[i] - a2[i];
+        }
+        return val;
     }
 
     private String getFreqsLine(long[] freqs) {
@@ -94,7 +148,7 @@
     }
 
     private String[] getUidTimesLines(int[] uids, long[][] times) {
-        final String[] lines = new String[uids.length];
+        final String[] lines = new String[uids.length + 1];
         final StringBuilder sb = new StringBuilder();
         for (int i = 0; i < uids.length; ++i) {
             sb.setLength(0);
@@ -104,6 +158,7 @@
             }
             lines[i] = sb.toString();
         }
+        lines[uids.length] = null;
         return lines;
     }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
new file mode 100644
index 0000000..4a23f40
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static android.os.BatteryStats.STATS_SINCE_CHARGED;
+
+import static com.android.internal.os.BatteryStatsImpl.LongSamplingCounterArray;
+import static com.android.internal.os.BatteryStatsImpl.TimeBase;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+
+/**
+ * Test class for {@link BatteryStatsImpl.LongSamplingCounterArray}.
+ *
+ * To run the tests, use
+ *
+ * runtest -c com.android.internal.os.LongSamplingCounterArrayTest frameworks-core
+ *
+ * or the following steps:
+ *
+ * Build: m FrameworksCoreTests
+ * Install: adb install -r \
+ *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
+ * Run: adb shell am instrument -e class com.android.internal.os.LongSamplingCounterArrayTest -w \
+ *     com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class LongSamplingCounterArrayTest {
+
+    private static final long[] COUNTS = {1111, 2222, 3333, 4444};
+    private static final long[] LOADED_COUNTS = {5555, 6666, 7777, 8888};
+    private static final long[] PLUGGED_COUNTS = {9999, 11111, 22222, 33333};
+    private static final long[] UNPLUGGED_COUNTS = {44444, 55555, 66666, 77777};
+    private static final long[] ZEROES = {0, 0, 0, 0};
+
+    @Mock private TimeBase mTimeBase;
+    private LongSamplingCounterArray mCounterArray;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mCounterArray = new LongSamplingCounterArray(mTimeBase);
+        Mockito.reset(mTimeBase);
+    }
+
+    @Test
+    public void testReadWriteParcel() {
+        final Parcel parcel = Parcel.obtain();
+        initializeCounterArrayWithDefaultValues();
+        LongSamplingCounterArray.writeToParcel(parcel, mCounterArray);
+        parcel.setDataPosition(0);
+
+        // Now clear counterArray and verify values are read from parcel correctly.
+        updateCounts(null, null, null, null);
+        mCounterArray = LongSamplingCounterArray.readFromParcel(parcel, mTimeBase);
+        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
+                "Unexpected unpluggedCounts");
+        parcel.recycle();
+    }
+
+    @Test
+    public void testReadWriteSummaryParcel() {
+        final Parcel parcel = Parcel.obtain();
+        initializeCounterArrayWithDefaultValues();
+        LongSamplingCounterArray.writeSummaryToParcelLocked(parcel, mCounterArray);
+        parcel.setDataPosition(0);
+
+        // Now clear counterArray and verify values are read from parcel correctly.
+        updateCounts(null, null, null, null);
+        mCounterArray = LongSamplingCounterArray.readSummaryFromParcelLocked(parcel, mTimeBase);
+        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(COUNTS, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+        parcel.recycle();
+    }
+
+    @Test
+    public void testOnTimeStarted() {
+        initializeCounterArrayWithDefaultValues();
+        mCounterArray.onTimeStarted(0, 0, 0);
+        assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
+                "Unexpected unpluggedCounts");
+    }
+
+    @Test
+    public void testOnTimeStopped() {
+        initializeCounterArrayWithDefaultValues();
+        mCounterArray.onTimeStopped(0, 0, 0);
+        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
+                "Unexpected unpluggedCounts");
+    }
+
+    @Test
+    public void testGetCountsLocked() {
+        initializeCounterArrayWithDefaultValues();
+
+        when(mTimeBase.isRunning()).thenReturn(false);
+        long[] actualVal = mCounterArray.getCountsLocked(STATS_SINCE_CHARGED);
+        long[] expectedVal = PLUGGED_COUNTS;
+        assertArrayEquals(expectedVal, actualVal, "Unexpected values");
+
+        when(mTimeBase.isRunning()).thenReturn(true);
+        actualVal = mCounterArray.getCountsLocked(STATS_SINCE_CHARGED);
+        expectedVal = COUNTS;
+        assertArrayEquals(expectedVal, actualVal, "Unexpected values");
+    }
+
+    @Test
+    public void testAddCountLocked() {
+        final long[] deltas = {123, 234, 345, 456};
+        mCounterArray.addCountLocked(deltas);
+        assertArrayEquals(deltas, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(null, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+
+        initializeCounterArrayWithDefaultValues();
+        final long[] newCounts = new long[deltas.length];
+        for (int i = 0; i < deltas.length; ++i) {
+            newCounts[i] = COUNTS[i] + deltas[i];
+        }
+        mCounterArray.addCountLocked(deltas);
+        assertArrayEquals(newCounts, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
+                "Unexpected unpluggedCounts");
+    }
+
+    @Test
+    public void testReset() {
+        initializeCounterArrayWithDefaultValues();
+        // Test with detachIfReset=false
+        mCounterArray.reset(false /* detachIfReset */);
+        assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(ZEROES, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+        verifyZeroInteractions(mTimeBase);
+
+        initializeCounterArrayWithDefaultValues();
+        // Test with detachIfReset=true
+        mCounterArray.reset(true /* detachIfReset */);
+        assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(ZEROES, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+        verify(mTimeBase).remove(mCounterArray);
+        verifyNoMoreInteractions(mTimeBase);
+    }
+
+    @Test
+    public void testDetach() {
+        mCounterArray.detach();
+        verify(mTimeBase).remove(mCounterArray);
+        verifyNoMoreInteractions(mTimeBase);
+    }
+
+    private void initializeCounterArrayWithDefaultValues() {
+        updateCounts(COUNTS, LOADED_COUNTS, PLUGGED_COUNTS, UNPLUGGED_COUNTS);
+    }
+
+    private void assertArrayEquals(long[] expected, long[] actual, String msg) {
+        assertTrue(msg + ", expected: " + Arrays.toString(expected)
+                + ", actual: " + Arrays.toString(actual), Arrays.equals(expected, actual));
+    }
+
+    private void updateCounts(long[] counts, long[] loadedCounts,
+            long[] pluggedCounts, long[] unpluggedCounts) {
+        mCounterArray.mCounts = counts;
+        mCounterArray.mLoadedCounts = loadedCounts;
+        mCounterArray.mPluggedCounts = pluggedCounts;
+        mCounterArray.mUnpluggedCounts = unpluggedCounts;
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java b/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
index 5dc07c2..906d7e9 100644
--- a/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.widget;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
 import android.support.test.InstrumentationRegistry;
@@ -111,6 +111,9 @@
         mTextView.measure(widthMeasureSpec, heightMeasureSpec);
         mView.measure(widthMeasureSpec, heightMeasureSpec);
 
-        assertEquals(mTextView.getMeasuredHeight(), mView.getMeasuredHeight());
+        // We're at most allowed to be the same height as the regular textview and maybe a bit
+        // smaller since our layout snaps to full textlines.
+        assertTrue("The measured view should never be taller then the normal textview!",
+                mView.getMeasuredHeight() <= mTextView.getMeasuredHeight());
     }
 }
diff --git a/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
index 75b2c1d..20fd4d3 100644
--- a/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
@@ -21,7 +21,6 @@
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
-import android.os.Debug;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.espresso.core.deps.guava.base.Function;
 import android.support.test.filters.SmallTest;
@@ -46,8 +45,7 @@
     @Before
     public void setup() {
         mContext = InstrumentationRegistry.getTargetContext();
-        // maxHeight: 300px
-        // spacing: 50px
+        // spacing: 5px
         mView = (MessagingLinearLayout) LayoutInflater.from(mContext).inflate(
                 R.layout.messaging_linear_layout_test, null);
     }
@@ -81,8 +79,8 @@
 
         assertEquals(3, child1.getNumIndentLines());
         assertEquals(0, child2.getNumIndentLines());
-        assertFalse(child1.isHidden());
-        assertFalse(child2.isHidden());
+        assertFalse("child1 should not be hidden", child1.isHidden());
+        assertFalse("child2 should not be hidden", child2.isHidden());
         assertEquals(205, mView.getMeasuredHeight());
     }
 
@@ -100,8 +98,8 @@
 
         assertEquals(2, child1.getNumIndentLines());
         assertEquals(1, child2.getNumIndentLines());
-        assertFalse(child1.isHidden());
-        assertFalse(child2.isHidden());
+        assertFalse("child1 should not be hidden", child1.isHidden());
+        assertFalse("child2 should not be hidden", child2.isHidden());
         assertEquals(105, mView.getMeasuredHeight());
     }
 
@@ -118,14 +116,14 @@
         mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
 
         assertEquals(3, child2.getNumIndentLines());
-        assertTrue(child1.isHidden());
-        assertFalse(child2.isHidden());
-        assertEquals(300, mView.getMeasuredHeight());
+        assertTrue("child1 should be hidden", child1.isHidden());
+        assertFalse("child2 should not be hidden", child2.isHidden());
+        assertEquals(350, mView.getMeasuredHeight());
     }
 
     @Test
-    public void testLargeSmall_largeWrapsWith3indentbutnot3_andHitsMax() {
-        FakeImageFloatingTextView child1 = fakeChild((i) -> i > 2 ? 5 : 4);
+    public void testLargeSmall_largeWrapsWith3indentbutNotFullHeight_andHitsMax() {
+        FakeImageFloatingTextView child1 = fakeChild((i) -> i > 2 ? 7 : 6);
         FakeImageFloatingTextView child2 = fakeChild((i) -> 1);
 
         mView.setNumIndentLines(2);
@@ -135,10 +133,11 @@
         mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
         mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
 
-        assertTrue(child1.isHidden());
-        assertFalse(child2.isHidden());
-        assertEquals(50, mView.getMeasuredHeight());
-        assertEquals(2, child2.getNumIndentLines());
+        assertFalse("child1 should not be hidden", child1.isHidden());
+        assertFalse("child2 should not be hidden", child2.isHidden());
+        assertEquals(355, mView.getMeasuredHeight());
+        assertEquals(3, child1.getNumIndentLines());
+        assertEquals(0, child2.getNumIndentLines());
     }
 
     @Test
@@ -153,8 +152,8 @@
         mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
         mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
 
-        assertFalse(child1.isHidden());
-        assertFalse(child2.isHidden());
+        assertFalse("child1 should not be hidden", child1.isHidden());
+        assertFalse("child2 should not be hidden", child2.isHidden());
         assertEquals(255, mView.getMeasuredHeight());
         assertEquals(3, child1.getNumIndentLines());
         assertEquals(0, child2.getNumIndentLines());
@@ -184,10 +183,23 @@
         }
 
         @Override
+        public int getLayoutHeight() {
+            return Math.max(LINE_HEIGHT, getMeasuredHeight());
+        }
+
+        @Override
         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
             setMeasuredDimension(
                     getDefaultSize(500, widthMeasureSpec),
-                    resolveSize(getDesiredHeight(), heightMeasureSpec));
+                    clampToMultiplesOfLineHeight(resolveSize(getDesiredHeight(),
+                            heightMeasureSpec)));
+        }
+
+        private int clampToMultiplesOfLineHeight(int size) {
+            if (size <= LINE_HEIGHT) {
+                return size;
+            }
+            return (size / LINE_HEIGHT) * LINE_HEIGHT;
         }
 
         @Override
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index b0e486d..d765584 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -16,7 +16,6 @@
 #include "Bitmap.h"
 
 #include "Caches.h"
-#include "pipeline/skia/SkiaOpenGLPipeline.h"
 #include "renderthread/EglManager.h"
 #include "renderthread/RenderThread.h"
 #include "renderthread/RenderProxy.h"
@@ -35,15 +34,11 @@
 #include <private/gui/ComposerService.h>
 #include <binder/IServiceManager.h>
 #include <ui/PixelFormat.h>
-#include <GrTexture.h>
 
 #include <SkCanvas.h>
-#include <SkImagePriv.h>
 
 namespace android {
 
-Mutex Bitmap::gLock;
-
 static bool computeAllocationSize(size_t rowBytes, int height, size_t* size) {
     int32_t rowBytes32 = SkToS32(rowBytes);
     int64_t bigSize = (int64_t) height * rowBytes32;
@@ -322,7 +317,8 @@
         return nullptr;
     }
     SkImageInfo info = SkImageInfo::Make(graphicBuffer->getWidth(), graphicBuffer->getHeight(),
-            kRGBA_8888_SkColorType, kPremul_SkAlphaType, SkColorSpace::MakeSRGB());
+            kRGBA_8888_SkColorType, kPremul_SkAlphaType,
+            SkColorSpace::MakeSRGB());
     return sk_sp<Bitmap>(new Bitmap(graphicBuffer.get(), info));
 }
 
@@ -397,7 +393,6 @@
     mPixelStorage.hardware.buffer = buffer;
     buffer->incStrong(buffer);
     mRowBytes = bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride();
-    setImmutable(); // HW bitmaps are always immutable
 }
 
 Bitmap::~Bitmap() {
@@ -491,13 +486,7 @@
 void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
     outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
     if (isHardware()) {
-        if (uirenderer::Properties::isSkiaEnabled()) {
-            // TODO: add color correctness for Skia pipeline - pass null color space for now
-            outBitmap->allocPixels(SkImageInfo::Make(info().width(), info().height(),
-                    info().colorType(), info().alphaType(), nullptr));
-        } else {
-            outBitmap->allocPixels(info());
-        }
+        outBitmap->allocPixels(info());
         uirenderer::renderthread::RenderProxy::copyGraphicBufferInto(graphicBuffer(), outBitmap);
         return;
     }
@@ -523,28 +512,4 @@
     return nullptr;
 }
 
-sk_sp<SkImage> Bitmap::makeImage(const uirenderer::renderthread::RenderThread* renderThread) {
-    AutoMutex _lock(gLock); //TODO: implement lock free solution
-    auto image = mImage;
-    //TODO: use new API SkImage::isValid() instead of SkImage::getTexture()->getContext()
-    if (!image.get() || (image->getTexture() && nullptr == image->getTexture()->getContext())) {
-        if (isHardware() && uirenderer::RenderPipelineType::SkiaGL
-                == uirenderer::Properties::getRenderPipelineType()) {
-            //TODO: add Vulkan support
-            if (renderThread) {
-                image = uirenderer::skiapipeline::SkiaOpenGLPipeline::makeTextureImage(
-                        *renderThread, this);
-            } else {
-                image = uirenderer::renderthread::RenderProxy::makeTextureImage(this);
-            }
-        } else {
-            SkBitmap skiaBitmap;
-            getSkBitmapForShaders(&skiaBitmap);
-            image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
-        }
-        mImage = image;
-    }
-    return image;
-}
-
 } // namespace android
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 621e439..da45f76 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -22,8 +22,6 @@
 #include <SkPixelRef.h>
 #include <cutils/compiler.h>
 #include <ui/GraphicBuffer.h>
-#include <utils/Mutex.h>
-#include <SkImage.h>
 
 namespace android {
 
@@ -113,13 +111,6 @@
     }
 
     GraphicBuffer* graphicBuffer();
-
-    // makeImage creates or returns a cached SkImage. Can be invoked from UI or render thread.
-    // If invoked on the render thread, then RenderThread* argument is required.
-    // If not invoked on the render thread, then RenderThread* must be nullptr.
-    // makeImage is wrapping a gralloc buffer with an EGLImage and is passing a texture to Skia.
-    // This is a temporary implementation until Skia can wrap the gralloc buffer in a SkImage.
-    sk_sp<SkImage> makeImage(const uirenderer::renderthread::RenderThread*);
 protected:
     virtual bool onNewLockPixels(LockRec* rec) override;
     virtual void onUnlockPixels() override { };
@@ -154,9 +145,6 @@
             GraphicBuffer* buffer;
         } hardware;
     } mPixelStorage;
-
-    sk_sp<SkImage> mImage;
-    static Mutex gLock;
 };
 
 } //namespace android
\ No newline at end of file
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 4885873..ae13131 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -28,8 +28,6 @@
 
 #include <cutils/properties.h>
 #include <strings.h>
-#include <SkImagePriv.h>
-#include <gl/GrGLTypes.h>
 
 using namespace android::uirenderer::renderthread;
 
@@ -199,87 +197,6 @@
     }
 }
 
-static void deleteImageTexture(void* context) {
-     EGLImageKHR EGLimage = reinterpret_cast<EGLImageKHR>(context);
-     if (EGLimage != EGL_NO_IMAGE_KHR) {
-        EGLDisplay display = eglGetCurrentDisplay();
-        if (EGL_NO_DISPLAY == display) {
-            display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-        }
-        eglDestroyImageKHR(display, EGLimage);
-     }
-}
-
-sk_sp<SkImage> SkiaOpenGLPipeline::makeTextureImage(
-        const uirenderer::renderthread::RenderThread& renderThread, Bitmap* bitmap) {
-    renderThread.eglManager().initialize();
-
-    GraphicBuffer* buffer = bitmap->graphicBuffer();
-    EGLDisplay display = eglGetCurrentDisplay();
-    if (EGL_NO_DISPLAY == display) {
-        display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    }
-    LOG_ALWAYS_FATAL_IF(!bitmap->isHardware(),
-                "Texture image requires a HW bitmap.");
-    // We use an EGLImage to access the content of the GraphicBuffer
-    // The EGL image is later bound to a 2D texture
-    EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer->getNativeBuffer();
-    EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
-    EGLImageKHR EGLimage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-            clientBuffer, imageAttrs);
-    if (EGLimage == EGL_NO_IMAGE_KHR) {
-        ALOGW("Could not create EGL image, err =%s",
-                uirenderer::renderthread::EglManager::eglErrorString());
-        return nullptr;
-    }
-
-    GLuint textureId = 0;
-    glGenTextures(1, &textureId);
-    glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
-    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, EGLimage);
-
-    GLenum status = GL_NO_ERROR;
-    while ((status = glGetError()) != GL_NO_ERROR) {
-        ALOGW("glEGLImageTargetTexture2DOES failed (%#x)", status);
-        eglDestroyImageKHR(display, EGLimage);
-        return nullptr;
-    }
-
-    sk_sp<GrContext> grContext = sk_ref_sp(renderThread.getGrContext());
-    grContext->resetContext();
-
-    GrGLTextureInfo textureInfo;
-    textureInfo.fTarget = GL_TEXTURE_EXTERNAL_OES;
-    textureInfo.fID = textureId;
-
-    GrBackendTextureDesc textureDescription;
-    textureDescription.fWidth = bitmap->info().width();
-    textureDescription.fHeight = bitmap->info().height();
-    textureDescription.fOrigin = kTopLeft_GrSurfaceOrigin;
-    textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&textureInfo);
-    PixelFormat format = buffer->getPixelFormat();
-    switch (format) {
-    case PIXEL_FORMAT_RGBA_8888:
-        textureDescription.fConfig = kRGBA_8888_GrPixelConfig;
-        break;
-    case PIXEL_FORMAT_RGBA_FP16:
-        textureDescription.fConfig = kRGBA_half_GrPixelConfig;
-        break;
-    default:
-        eglDestroyImageKHR(display, EGLimage);
-        return nullptr;
-    }
-
-    // TODO: add color correctness - pass null color space for now
-    sk_sp<SkImage> image = SkImage::MakeFromTexture(grContext.get(), textureDescription,
-                bitmap->info().alphaType(), nullptr, deleteImageTexture, EGLimage);
-    if (!image.get()) {
-        eglDestroyImageKHR(display, EGLimage);
-        return nullptr;
-    }
-    return image;
-}
-
 } /* namespace skiapipeline */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
index f3ce189..36685dd 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -46,8 +46,6 @@
     bool isContextReady() override;
 
     static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
-    static sk_sp<SkImage> makeTextureImage(
-            const uirenderer::renderthread::RenderThread& renderThread, Bitmap* bitmap);
 
 private:
     renderthread::EglManager& mEglManager;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
index 1a6e709..a18d264 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
@@ -61,7 +61,6 @@
     textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture);
 
     CopyResult copyResult = CopyResult::UnknownError;
-    // TODO: add color correctness - pass null color space for now
     sk_sp<SkImage> image(SkImage::MakeFromAdoptedTexture(grContext.get(), textureDescription));
     if (image) {
         SkAutoLockPixels alp(*bitmap);
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 349d4cc..10c1865 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -155,11 +155,11 @@
     GrContext* context = thread.getGrContext();
     if (context) {
         ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
-        auto image = bitmap->makeImage(&thread);
-        if (image.get() && !bitmap->isHardware()) {
-            SkImage_pinAsTexture(image.get(), context);
-            SkImage_unpinAsTexture(image.get(), context);
-        }
+        SkBitmap skiaBitmap;
+        bitmap->getSkBitmap(&skiaBitmap);
+        sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
+        SkImage_pinAsTexture(image.get(), context);
+        SkImage_unpinAsTexture(image.get(), context);
     }
 }
 
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 5d7bbfa..559d268 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -168,8 +168,11 @@
 }
 
 void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
-    sk_sp<SkImage> image = bitmap.makeImage(nullptr);
-    if (!bitmap.isImmutable()) {
+    SkBitmap skBitmap;
+    bitmap.getSkBitmap(&skBitmap);
+
+    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skBitmap, kNever_SkCopyPixelsMode);
+    if (!skBitmap.isImmutable()) {
         mDisplayList->mMutableImages.push_back(image.get());
     }
     SkPaint tmpPaint;
@@ -178,10 +181,12 @@
 
 void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix,
         const SkPaint* paint) {
+    SkBitmap bitmap;
+    hwuiBitmap.getSkBitmap(&bitmap);
     SkAutoCanvasRestore acr(&mRecorder, true);
     concat(matrix);
-    sk_sp<SkImage> image = hwuiBitmap.makeImage(nullptr);
-    if (!hwuiBitmap.isImmutable()) {
+    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+    if (!bitmap.isImmutable()) {
         mDisplayList->mMutableImages.push_back(image.get());
     }
     SkPaint tmpPaint;
@@ -191,10 +196,12 @@
 void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop,
         float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight,
         float dstBottom, const SkPaint* paint) {
+    SkBitmap bitmap;
+    hwuiBitmap.getSkBitmap(&bitmap);
     SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
     SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
-    sk_sp<SkImage> image = hwuiBitmap.makeImage(nullptr);
-    if (!hwuiBitmap.isImmutable()) {
+    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+    if (!bitmap.isImmutable()) {
         mDisplayList->mMutableImages.push_back(image.get());
     }
     SkPaint tmpPaint;
@@ -203,8 +210,11 @@
 
 void SkiaRecordingCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk,
         float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) {
+    SkBitmap bitmap;
+    hwuiBitmap.getSkBitmap(&bitmap);
+
     SkCanvas::Lattice lattice;
-    NinePatchUtils::SetLatticeDivs(&lattice, chunk, hwuiBitmap.width(), hwuiBitmap.height());
+    NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height());
 
     lattice.fFlags = nullptr;
     int numFlags = 0;
@@ -221,8 +231,8 @@
 
     lattice.fBounds = nullptr;
     SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
-    sk_sp<SkImage> image = hwuiBitmap.makeImage(nullptr);
-    if (!hwuiBitmap.isImmutable()) {
+    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+    if (!bitmap.isImmutable()) {
         mDisplayList->mMutableImages.push_back(image.get());
     }
 
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 5c2ec0e..a1f1717 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -693,18 +693,6 @@
     }
 }
 
-CREATE_BRIDGE2(makeTextureImage, RenderThread* thread, Bitmap* bitmap) {
-    return args->thread->makeTextureImage(args->bitmap).release();
-}
-
-sk_sp<SkImage> RenderProxy::makeTextureImage(Bitmap* bitmap) {
-    SETUP_TASK(makeTextureImage);
-    args->bitmap = bitmap;
-    args->thread = &RenderThread::getInstance();
-    sk_sp<SkImage> hardwareImage(reinterpret_cast<SkImage*>(staticPostAndWait(task)));
-    return hardwareImage;
-}
-
 void RenderProxy::post(RenderTask* task) {
     mRenderThread.queue(task);
 }
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 97ad796..a60ed55 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -135,8 +135,6 @@
     static sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& bitmap);
 
     static int copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap);
-
-    static sk_sp<SkImage> makeTextureImage(Bitmap* bitmap);
 private:
     RenderThread& mRenderThread;
     CanvasContext* mContext;
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index d62b556..1450ec9 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -17,7 +17,6 @@
 #include "RenderThread.h"
 
 #include "../renderstate/RenderState.h"
-#include "../pipeline/skia/SkiaOpenGLPipeline.h"
 #include "../pipeline/skia/SkiaOpenGLReadback.h"
 #include "CanvasContext.h"
 #include "EglManager.h"
@@ -434,24 +433,6 @@
     return next;
 }
 
-sk_sp<SkImage> RenderThread::makeTextureImage(Bitmap* bitmap) {
-    auto renderType = Properties::getRenderPipelineType();
-    sk_sp<SkImage> hardwareImage;
-    switch (renderType) {
-        case RenderPipelineType::SkiaGL:
-            hardwareImage = skiapipeline::SkiaOpenGLPipeline::makeTextureImage(*this, bitmap);
-            break;
-        case RenderPipelineType::SkiaVulkan:
-            //TODO: add Vulkan support
-            break;
-        default:
-            LOG_ALWAYS_FATAL("makeTextureImage: canvas context type %d not supported",
-                    (int32_t) renderType);
-            break;
-    }
-    return hardwareImage;
-}
-
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 34542c6..9bc5985 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -33,7 +33,6 @@
 
 namespace android {
 
-class Bitmap;
 class DisplayEventReceiver;
 
 namespace uirenderer {
@@ -105,8 +104,6 @@
 
     VulkanManager& vulkanManager() { return *mVkManager; }
 
-    sk_sp<SkImage> makeTextureImage(Bitmap* bitmap);
-
 protected:
     virtual bool threadLoop() override;
 
diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java
index b1dc3ad..9841815 100644
--- a/media/java/android/media/AudioFocusRequest.java
+++ b/media/java/android/media/AudioFocusRequest.java
@@ -40,7 +40,7 @@
  * <p>When an application requests audio focus, it expresses its intention to “own” audio focus to
  * play audio. Let’s review the different types of focus requests, the return value after a request,
  * and the responses to a loss.
- * <br><b>Note:<b> applications should not play anything until granted focus.
+ * <p class="note">Note: applications should not play anything until granted focus.</p>
  *
  * <h3>The different types of focus requests</h3>
  * <p>There are four focus request types. A successful focus request with each will yield different
@@ -77,9 +77,10 @@
  *
  * <p>An {@code AudioFocusRequest} instance always contains one of the four types of requests
  * explained above. It is passed when building an {@code AudioFocusRequest} instance with its
- * builder in the {@link Builder} constructor {@link Builder#Builder(int)}, or with
- * {@link Builder#setFocusGain(int)} after copying an existing instance with
- * {@link Builder#Builder(AudioFocusRequest)}.
+ * builder in the {@link Builder} constructor
+ * {@link AudioFocusRequest.Builder#AudioFocusRequest.Builder(int)}, or
+ * with {@link AudioFocusRequest.Builder#setFocusGain(int)} after copying an existing instance with
+ * {@link AudioFocusRequest.Builder#AudioFocusRequest.Builder(AudioFocusRequest)}.
  *
  * <h3>Qualifying your focus request</h3>
  * <h4>Use case requiring a focus request</h4>
@@ -105,10 +106,11 @@
  * <h4>Pausing vs ducking</h4>
  * <p>When an application requested audio focus with
  * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, the system will duck the current focus
- * owner. Note that this behavior is <b>new for Android O<b>, whereas applications targeting SDK
- * up to API 25, applications had to implement the ducking themselves when they received a focus
+ * owner.
+ * <p class="note">Note: this behavior is <b>new for Android O</b>, whereas applications targeting
+ * SDK level up to API 25 had to implement the ducking themselves when they received a focus
  * loss of {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}.
- * <br>But ducking is not always the behavior expected by the user. A typical example is when the
+ * <p>But ducking is not always the behavior expected by the user. A typical example is when the
  * device plays driving directions while the user is listening to an audio book or podcast, and
  * expects the audio playback to pause, instead of duck, as it is hard to understand a navigation
  * prompt and spoken content at the same time. Therefore the system will not automatically duck
@@ -126,7 +128,92 @@
  * speech, you can also declare so with {@link Builder#setWillPauseWhenDucked(boolean)}, which will
  * cause the system to call your focus listener instead of automatically ducking.
  *
+ * <h4>Example</h4>
+ * <p>The example below covers the following steps to be found in any application that would play
+ * audio, and use audio focus. Here we play an audio book, and our application is intended to pause
+ * rather than duck when it loses focus. These steps consist in:
+ * <ul>
+ * <li>Creating {@code AudioAttributes} to be used for the playback and the focus request.</li>
+ * <li>Configuring and creating the {@code AudioFocusRequest} instance that defines the intended
+ *     focus behaviors.</li>
+ * <li>Requesting audio focus and checking the return code to see if playback can happen right
+ *     away, or is delayed.</li>
+ * <li>Implementing a focus change listener to respond to focus gains and losses.</li>
+ * </ul>
+ * <p>
+ * <pre class="prettyprint">
+ * // initialization of the audio attributes and focus request
+ * mAudioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE);
+ * mPlaybackAttributes = new AudioAttributes.Builder()
+ *         .setUsage(AudioAttributes.USAGE_MEDIA)
+ *         .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
+ *         .build();
+ * mFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
+ *         .setAudioAttributes(mPlaybackAttributes)
+ *         .setAcceptsDelayedFocusGain(true)
+ *         .setWillPauseWhenDucked(true)
+ *         .setOnAudioFocusChangeListener(this, mMyHandler)
+ *         .build();
+ * mMediaPlayer = new MediaPlayer();
+ * mMediaPlayer.setAudioAttributes(mPlaybackAttributes);
+ * final Object mFocusLock = new Object();
+ *
+ * boolean mPlaybackDelayed = false;
+ *
+ * // requesting audio focus
+ * int res = mAudioManager.requestAudioFocus(mFocusRequest);
+ * synchronized (mFocusLock) {
+ *     if (res == AUDIOFOCUS_REQUEST_FAILED) {
+ *         mPlaybackDelayed = false;
+ *     } else if (res == AUDIOFOCUS_REQUEST_GRANTED) {
+ *         mPlaybackDelayed = false;
+ *         playbackNow();
+ *     } else if (res == AUDIOFOCUS_REQUEST_DELAYED) {
+ *        mPlaybackDelayed = true;
+ *     }
+ * }
+ *
+ * // implementation of the OnAudioFocusChangeListener
+ * &#64;Override
+ * public void onAudioFocusChange(int focusChange) {
+ *     switch (focusChange) {
+ *         case AudioManager.AUDIOFOCUS_GAIN:
+ *             if (mPlaybackDelayed || mResumeOnFocusGain) {
+ *                 synchronized (mFocusLock) {
+ *                     mPlaybackDelayed = false;
+ *                     mResumeOnFocusGain = false;
+ *                 }
+ *                 playbackNow();
+ *             }
+ *             break;
+ *         case AudioManager.AUDIOFOCUS_LOSS:
+ *             synchronized (mFocusLock) {
+ *                 // this is not a transient loss, we shouldn't automatically resume for now
+ *                 mResumeOnFocusGain = false;
+ *                 mPlaybackDelayed = false;
+ *             }
+ *             pausePlayback();
+ *             break;
+ *         case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
+ *         case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
+ *             // we handle all transient losses the same way because we never duck audio books
+ *             synchronized (mFocusLock) {
+ *                 // we should only resume if playback was interrupted
+ *                 mResumeOnFocusGain = mMediaPlayer.isPlaying();
+ *                 mPlaybackDelayed = false;
+ *             }
+ *             pausePlayback();
+ *             break;
+ *     }
+ * }
+ *
+ * // Important:
+ * // Also set "mResumeOnFocusGain" to false when the user pauses or stops playback: this way your
+ * // application doesn't automatically restart when it gains focus, even though the user had
+ * // stopped it.
+ * </pre>
  */
+
 public final class AudioFocusRequest {
 
     // default attributes for the request when not specified
@@ -244,36 +331,15 @@
 
     /**
      * Builder class for {@link AudioFocusRequest} objects.
-     * <p> Here is an example where {@code Builder} is used to define the
-     * {@link AudioFocusRequest} for requesting audio focus:
-     *
-     * <pre class="prettyprint">
-     * mAudioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE);
-     * mPlaybackAttributes = new AudioAttributes.Builder()
-     *         .setUsage(AudioAttributes.USAGE_GAME)
-     *         .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
-     *         .build();
-     * mFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
-     *         .setAudioAttributes(mPlaybackAttributes)
-     *         .setAcceptsDelayedFocusGain(true)
-     *         .setOnAudioFocusChangeListener(mMyFocusListener, mMyHandler)
-     *         .build();
-     * mMediaPlayer = new MediaPlayer();
-     *  ...
-     * mMediaPlayer.setAudioAttributes(mPlaybackAttributes);
-     *  ...
-     * boolean mPlaybackAuthorized = true;;
-     * int res = mAudioManager.requestAudioFocus(mFocusRequest);
-     * if (res == AUDIOFOCUS_REQUEST_FAILED) {
-     *     mPlaybackAuthorized = false;
-     *     cancelPlayback();
-     * } else if (res == AUDIOFOCUS_REQUEST_DELAYED) {
-     *     playbackDelayed();
-     * } else { // res == AUDIOFOCUS_REQUEST_GRANTED
-     *     playbackNow();
-     * }
-     * </pre>
-     *
+     * <p>See {@link AudioFocusRequest} for an example of building an instance with this builder.
+     * <br>The default values for the instance to be built are:
+     * <table>
+     * <tr><td>focus listener and handler</td><td>none</td></tr>
+     * <tr><td>{@code AudioAttributes}</td><td>attributes with usage set to
+     *     {@link AudioAttributes#USAGE_MEDIA}</td></tr>
+     * <tr><td>pauses on duck</td><td>false</td></tr>
+     * <tr><td>supports delayed focus grant</td><td>false</td></tr>
+     * </table>
      */
     public static final class Builder {
         private OnAudioFocusChangeListener mFocusListener;
diff --git a/media/java/android/media/VolumeAutomation.java b/media/java/android/media/VolumeAutomation.java
index dff8801..ff2e645 100644
--- a/media/java/android/media/VolumeAutomation.java
+++ b/media/java/android/media/VolumeAutomation.java
@@ -31,9 +31,9 @@
      * @param configuration the {@link VolumeShaper.Configuration configuration}
      *        that specifies the curve and duration to use.
      * @return a {@code VolumeShaper} object
-     * @throws IllegalArgumentException if the configuration is not allowed by the player.
-     * @throws IllegalStateException if too many VolumeShapers are requested or the state of
-     * the player does not permit its creation (e.g. player is released).
+     * @throws IllegalArgumentException if the {@code configuration} is not allowed by the player.
+     * @throws IllegalStateException if too many {@code VolumeShaper}s are requested
+     *         or the state of the player does not permit its creation (e.g. player is released).
      */
     public @NonNull VolumeShaper createVolumeShaper(
             @NonNull VolumeShaper.Configuration configuration);
diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java
index 8f4721f..3068706 100644
--- a/media/java/android/media/VolumeShaper.java
+++ b/media/java/android/media/VolumeShaper.java
@@ -31,8 +31,16 @@
 /**
  * The {@code VolumeShaper} class is used to automatically control audio volume during media
  * playback, allowing simple implementation of transition effects and ducking.
+ * It is created from implementations of {@code VolumeAutomation},
+ * such as {@code MediaPlayer} and {@code AudioTrack} (referred to as "players" below),
+ * by {@link MediaPlayer#createVolumeShaper} or {@link AudioTrack#createVolumeShaper}.
  *
- * The {@link VolumeShaper} appears as an additional scaling on the audio output,
+ * A {@code VolumeShaper} is intended for short volume changes.
+ * If the audio output sink changes during
+ * a {@code VolumeShaper} transition, the precise curve position may be lost, and the
+ * {@code VolumeShaper} may advance to the end of the curve for the new audio output sink.
+ *
+ * The {@code VolumeShaper} appears as an additional scaling on the audio output,
  * and adjusts independently of track or stream volume controls.
  */
 public final class VolumeShaper implements AutoCloseable {
@@ -52,7 +60,19 @@
 
     /**
      * Applies the {@link VolumeShaper.Operation} to the {@code VolumeShaper}.
+     *
+     * Applying {@link VolumeShaper.Operation#PLAY} after {@code PLAY}
+     * or {@link VolumeShaper.Operation#REVERSE} after
+     * {@code REVERSE} has no effect.
+     *
+     * Applying {@link VolumeShaper.Operation#PLAY} when the player
+     * hasn't started will synchronously start the {@code VolumeShaper} when
+     * playback begins.
+     *
      * @param operation the {@code operation} to apply.
+     * @throws IllegalStateException if the player is uninitialized or if there
+     *         is a critical failure. In that case, the {@code VolumeShaper} should be
+     *         recreated.
      */
     public void apply(@NonNull Operation operation) {
         /* void */ applyPlayer(new VolumeShaper.Configuration(mId), operation);
@@ -65,11 +85,24 @@
      * This allows the user to change the volume shape
      * while the existing {@code VolumeShaper} is in effect.
      *
+     * The effect of {@code replace()} is similar to an atomic close of
+     * the existing {@code VolumeShaper} and creation of a new {@code VolumeShaper}.
+     *
+     * If the {@code operation} is {@link VolumeShaper.Operation#PLAY} then the
+     * new curve starts immediately.
+     *
+     * If the {@code operation} is
+     * {@link VolumeShaper.Operation#REVERSE}, then the new curve will
+     * be delayed until {@code PLAY} is applied.
+     *
      * @param configuration the new {@code configuration} to use.
-     * @param operation the operation to apply to the {@code VolumeShaper}
+     * @param operation the {@code operation} to apply to the {@code VolumeShaper}
      * @param join if true, match the start volume of the
      *             new {@code configuration} to the current volume of the existing
      *             {@code VolumeShaper}, to avoid discontinuity.
+     * @throws IllegalStateException if the player is uninitialized or if there
+     *         is a critical failure. In that case, the {@code VolumeShaper} should be
+     *         recreated.
      */
     public void replace(
             @NonNull Configuration configuration, @NonNull Operation operation, boolean join) {
@@ -81,7 +114,14 @@
     /**
      * Returns the current volume scale attributable to the {@code VolumeShaper}.
      *
+     * This is the last volume from the {@code VolumeShaper} used for the player,
+     * or the initial volume if the {@code VolumeShaper} hasn't been started with
+     * {@link VolumeShaper.Operation#PLAY}.
+     *
      * @return the volume, linearly represented as a value between 0.f and 1.f.
+     * @throws IllegalStateException if the player is uninitialized or if there
+     *         is a critical failure.  In that case, the {@code VolumeShaper} should be
+     *         recreated.
      */
     public float getVolume() {
         return getStatePlayer(mId).getVolume();
@@ -89,7 +129,14 @@
 
     /**
      * Releases the {@code VolumeShaper} object; any volume scale due to the
-     * {@code VolumeShaper} is removed.
+     * {@code VolumeShaper} is removed after closing.
+     *
+     * If the volume does not reach 1.f when the {@code VolumeShaper} is closed
+     * (or finalized), there may be an abrupt change of volume.
+     *
+     * {@code close()} may be safely called after a prior {@code close()}.
+     * This class implements the Java {@code AutoClosable} interface and
+     * may be used with try-with-resources.
      */
     @Override
     public void close() {
@@ -107,11 +154,11 @@
 
     @Override
     protected void finalize() {
-        close(); // ensure we remove the native volume shaper
+        close(); // ensure we remove the native VolumeShaper
     }
 
     /**
-     * Internal call to apply the configuration and operation to the Player.
+     * Internal call to apply the {@code configuration} and {@code operation} to the player.
      * Returns a valid shaper id or throws the appropriate exception.
      * @param configuration
      * @param operation
@@ -137,7 +184,7 @@
             // Due to RPC handling, we translate integer codes to exceptions right before
             // delivering to the user.
             if (id == VOLUME_SHAPER_INVALID_OPERATION) {
-                throw new IllegalStateException("player or volume shaper deallocated");
+                throw new IllegalStateException("player or VolumeShaper deallocated");
             } else {
                 throw new IllegalArgumentException("invalid configuration or operation: " + id);
             }
@@ -146,9 +193,9 @@
     }
 
     /**
-     * Internal call to retrieve the current VolumeShaper state.
+     * Internal call to retrieve the current {@code VolumeShaper} state.
      * @param id
-     * @return the current {@vode VolumeShaper.State}
+     * @return the current {@code VolumeShaper.State}
      * @throws IllegalStateException if the player has been deallocated or is uninitialized.
      */
     private @NonNull VolumeShaper.State getStatePlayer(int id) {
@@ -180,6 +227,9 @@
      * by {@link VolumeShaper#replace(Configuration, Operation, boolean)
      * VolumeShaper.replace(Configuration, Operation, boolean)}
      * to replace an existing {@code configuration}.
+     * <p>
+     * The {@link AudioTrack} and {@link MediaPlayer} classes implement
+     * the {@link VolumeAutomation} interface.
      */
     public static final class Configuration implements Parcelable {
         private static final int MAXIMUM_CURVE_POINTS = 16;
@@ -485,7 +535,7 @@
 
         /**
          * @hide
-         * Constructs a volume shaper from an id.
+         * Constructs a {@code VolumeShaper} from an id.
          *
          * This is an opaque handle for controlling a {@code VolumeShaper} that has
          * already been sent to a player.  The {@code id} is returned from the
@@ -756,7 +806,7 @@
             /**
              * Sets the interpolator type.
              *
-             * If omitted the interplator type is {@link #INTERPOLATOR_TYPE_CUBIC}.
+             * If omitted the default interpolator type is {@link #INTERPOLATOR_TYPE_CUBIC}.
              *
              * @param interpolatorType method of interpolation used for the volume curve.
              *        One of {@link #INTERPOLATOR_TYPE_STEP},
@@ -802,7 +852,7 @@
             }
 
             /**
-             * Sets the volume shaper duration in milliseconds.
+             * Sets the {@code VolumeShaper} duration in milliseconds.
              *
              * If omitted, the default duration is 1 second.
              *
@@ -1059,13 +1109,13 @@
 
         /**
          * Defer playback until next operation is sent. This is used
-         * when starting a VolumeShaper effect.
+         * when starting a {@code VolumeShaper} effect.
          */
         private static final int FLAG_DEFER = 1 << 3;
 
         /**
          * Use the id specified in the configuration, creating
-         * VolumeShaper as needed; the configuration should be
+         * {@code VolumeShaper} as needed; the configuration should be
          * TYPE_SCALE.
          */
         private static final int FLAG_CREATE_IF_NEEDED = 1 << 4;
@@ -1074,18 +1124,20 @@
 
         private final int mFlags;
         private final int mReplaceId;
+        private final float mXOffset;
 
         @Override
         public String toString() {
             return "VolumeShaper.Operation{"
                     + "mFlags = 0x" + Integer.toHexString(mFlags).toUpperCase()
                     + ", mReplaceId = " + mReplaceId
+                    + ", mXOffset = " + mXOffset
                     + "}";
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(mFlags, mReplaceId);
+            return Objects.hash(mFlags, mReplaceId, mXOffset);
         }
 
         @Override
@@ -1093,10 +1145,10 @@
             if (!(o instanceof Operation)) return false;
             if (o == this) return true;
             final Operation other = (Operation) o;
-            // if xOffset (native field only) is brought into Java
-            // we need to do proper NaN comparison as that is allowed.
+
             return mFlags == other.mFlags
-                    && mReplaceId == other.mReplaceId;
+                    && mReplaceId == other.mReplaceId
+                    && Float.compare(mXOffset, other.mXOffset) == 0;
         }
 
         @Override
@@ -1109,7 +1161,7 @@
             // this needs to match the native VolumeShaper.Operation parceling
             dest.writeInt(mFlags);
             dest.writeInt(mReplaceId);
-            dest.writeFloat(Float.NaN); // xOffset (ignored at Java level)
+            dest.writeFloat(mXOffset);
         }
 
         public static final Parcelable.Creator<VolumeShaper.Operation> CREATOR
@@ -1119,11 +1171,12 @@
                 // this needs to match the native VolumeShaper.Operation parceling
                 final int flags = p.readInt();
                 final int replaceId = p.readInt();
-                final float xOffset = p.readFloat(); // ignored at Java level
+                final float xOffset = p.readFloat();
 
                 return new VolumeShaper.Operation(
                         flags
-                        , replaceId);
+                        , replaceId
+                        , xOffset);
             }
 
             @Override
@@ -1132,9 +1185,10 @@
             }
         };
 
-        private Operation(@Flag int flags, int replaceId) {
+        private Operation(@Flag int flags, int replaceId, float xOffset) {
             mFlags = flags;
             mReplaceId = replaceId;
+            mXOffset = xOffset;
         }
 
         /**
@@ -1146,6 +1200,7 @@
         public static final class Builder {
             int mFlags;
             int mReplaceId;
+            float mXOffset;
 
             /**
              * Constructs a new {@code Builder} with the defaults.
@@ -1153,23 +1208,27 @@
             public Builder() {
                 mFlags = 0;
                 mReplaceId = -1;
+                mXOffset = Float.NaN;
             }
 
             /**
-             * Constructs a new Builder from a given {@code VolumeShaper.Operation}
+             * Constructs a new {@code Builder} from a given {@code VolumeShaper.Operation}
              * @param operation the {@code VolumeShaper.operation} whose data will be
-             *        reused in the new Builder.
+             *        reused in the new {@code Builder}.
              */
             public Builder(@NonNull VolumeShaper.Operation operation) {
                 mReplaceId = operation.mReplaceId;
                 mFlags = operation.mFlags;
+                mXOffset = operation.mXOffset;
             }
 
             /**
-             * Replaces the previous {@code VolumeShaper} specified by id.
-             * It has no other effect if the {@code VolumeShaper} is
-             * already expired.
-             * @param id the id of the previous {@code VolumeShaper}.
+             * Replaces the previous {@code VolumeShaper} specified by {@code id}.
+             *
+             * The {@code VolumeShaper} specified by the {@code id} is removed
+             * if it exists. The configuration should be TYPE_SCALE.
+             *
+             * @param id the {@code id} of the previous {@code VolumeShaper}.
              * @param join if true, match the volume of the previous
              * shaper to the start volume of the new {@code VolumeShaper}.
              * @return the same {@code Builder} instance.
@@ -1194,8 +1253,9 @@
             }
 
             /**
-             * Terminates the VolumeShaper.
-             * Do not call directly, use {@link VolumeShaper#release()}.
+             * Terminates the {@code VolumeShaper}.
+             *
+             * Do not call directly, use {@link VolumeShaper#close()}.
              * @return the same {@code Builder} instance.
              */
             public @NonNull Builder terminate() {
@@ -1214,8 +1274,12 @@
 
             /**
              * Use the id specified in the configuration, creating
-             * VolumeShaper as needed; the configuration should be
+             * {@code VolumeShaper} only as needed; the configuration should be
              * TYPE_SCALE.
+             *
+             * If the {@code VolumeShaper} with the same id already exists
+             * then the operation has no effect.
+             *
              * @return the same {@code Builder} instance.
              */
             public @NonNull Builder createIfNeeded() {
@@ -1224,6 +1288,28 @@
             }
 
             /**
+             * Sets the {@code xOffset} to use for the {@code VolumeShaper}.
+             *
+             * The {@code xOffset} is the position on the volume curve,
+             * and setting takes effect when the {@code VolumeShaper} is used next.
+             *
+             * @param xOffset a value between (or equal to) 0.f and 1.f, or Float.NaN to ignore.
+             * @return the same {@code Builder} instance.
+             * @throws IllegalArgumentException if {@code xOffset} is not between 0.f and 1.f,
+             *         or a Float.NaN.
+             */
+            public @NonNull Builder setXOffset(float xOffset) {
+                if (xOffset < -0.f) {
+                    throw new IllegalArgumentException("Negative xOffset not allowed");
+                } else if (xOffset > 1.f) {
+                    throw new IllegalArgumentException("xOffset > 1.f not allowed");
+                }
+                // Float.NaN passes through
+                mXOffset = xOffset;
+                return this;
+            }
+
+            /**
              * Sets the operation flag.  Do not call this directly but one of the
              * other builder methods.
              *
@@ -1245,7 +1331,7 @@
              * @return a new {@code VolumeShaper.Operation} object
              */
             public @NonNull Operation build() {
-                return new Operation(mFlags, mReplaceId);
+                return new Operation(mFlags, mReplaceId, mXOffset);
             }
         } // Operation.Builder
     } // Operation
@@ -1316,15 +1402,18 @@
 
         /**
          * Gets the volume of the {@link VolumeShaper.State}.
+         * @return linear volume between 0.f and 1.f.
          */
         public float getVolume() {
             return mVolume;
         }
 
         /**
-         * Gets the elapsed ms of the {@link VolumeShaper.State}
+         * Gets the {@code xOffset} position on the normalized curve
+         * of the {@link VolumeShaper.State}.
+         * @return the curve x position between 0.f and 1.f.
          */
-        public double getXOffset() {
+        public float getXOffset() {
             return mXOffset;
         }
     } // State
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 789d5e0..ece19e4 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -148,62 +148,60 @@
      * </p>
      */
     public void connect() {
-        if (mState != CONNECT_STATE_DISCONNECTED) {
-            throw new IllegalStateException("connect() called while not disconnected (state="
-                    + getStateLabel(mState) + ")");
-        }
-        // TODO: remove this extra check.
-        if (DBG) {
-            if (mServiceConnection != null) {
-                throw new RuntimeException("mServiceConnection should be null. Instead it is "
-                        + mServiceConnection);
-            }
-        }
-        if (mServiceBinder != null) {
-            throw new RuntimeException("mServiceBinder should be null. Instead it is "
-                    + mServiceBinder);
-        }
-        if (mServiceCallbacks != null) {
-            throw new RuntimeException("mServiceCallbacks should be null. Instead it is "
-                    + mServiceCallbacks);
+        if (mState != CONNECT_STATE_DISCONNECTING && mState != CONNECT_STATE_DISCONNECTED) {
+            throw new IllegalStateException("connect() called while neither disconnecting nor "
+                    + "disconnected (state=" + getStateLabel(mState) + ")");
         }
 
         mState = CONNECT_STATE_CONNECTING;
-
-        final Intent intent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
-        intent.setComponent(mServiceComponent);
-
-        final ServiceConnection thisConnection = mServiceConnection = new MediaServiceConnection();
-
-        boolean bound = false;
-        try {
-            bound = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
-        } catch (Exception ex) {
-            Log.e(TAG, "Failed binding to service " + mServiceComponent);
-        }
-
-        if (!bound) {
-            // Tell them that it didn't work. We are already on the main thread,
-            // but we don't want to do callbacks inside of connect(). So post it,
-            // and then check that we are on the same ServiceConnection. We know
-            // we won't also get an onServiceConnected or onServiceDisconnected,
-            // so we won't be doing double callbacks.
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    // Ensure that nobody else came in or tried to connect again.
-                    if (thisConnection == mServiceConnection) {
-                        forceCloseConnection();
-                        mCallback.onConnectionFailed();
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (mState == CONNECT_STATE_DISCONNECTING) {
+                    return;
+                }
+                mState = CONNECT_STATE_CONNECTING;
+                // TODO: remove this extra check.
+                if (DBG) {
+                    if (mServiceConnection != null) {
+                        throw new RuntimeException("mServiceConnection should be null. Instead it"
+                                + " is " + mServiceConnection);
                     }
                 }
-            });
-        }
+                if (mServiceBinder != null) {
+                    throw new RuntimeException("mServiceBinder should be null. Instead it is "
+                            + mServiceBinder);
+                }
+                if (mServiceCallbacks != null) {
+                    throw new RuntimeException("mServiceCallbacks should be null. Instead it is "
+                            + mServiceCallbacks);
+                }
 
-        if (DBG) {
-            Log.d(TAG, "connect...");
-            dump();
-        }
+                final Intent intent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
+                intent.setComponent(mServiceComponent);
+
+                mServiceConnection = new MediaServiceConnection();
+
+                boolean bound = false;
+                try {
+                    bound = mContext.bindService(intent, mServiceConnection,
+                            Context.BIND_AUTO_CREATE);
+                } catch (Exception ex) {
+                    Log.e(TAG, "Failed binding to service " + mServiceComponent);
+                }
+
+                if (!bound) {
+                    // Tell them that it didn't work.
+                    forceCloseConnection();
+                    mCallback.onConnectionFailed();
+                }
+
+                if (DBG) {
+                    Log.d(TAG, "connect...");
+                    dump();
+                }
+            }
+        });
     }
 
     /**
@@ -218,6 +216,7 @@
         mHandler.post(new Runnable() {
             @Override
             public void run() {
+                // connect() could be called before this. Then we will disconnect and reconnect.
                 if (mServiceCallbacks != null) {
                     try {
                         mServiceBinder.disconnect(mServiceCallbacks);
@@ -227,7 +226,13 @@
                         Log.w(TAG, "RemoteException during connect for " + mServiceComponent);
                     }
                 }
+                int state = mState;
                 forceCloseConnection();
+                // If the state was not CONNECT_STATE_DISCONNECTING, keep the state so that
+                // the operation came after disconnect() can be handled properly.
+                if (state != CONNECT_STATE_DISCONNECTING) {
+                    mState = state;
+                }
                 if (DBG) {
                     Log.d(TAG, "disconnect...");
                     dump();
@@ -245,6 +250,9 @@
      * a call to mCallback.onConnectionFailed(). Disconnect doesn't do that callback
      * for a clean shutdown, but everywhere else is a dirty shutdown and should
      * notify the app.
+     * <p>
+     * Also, mState should be updated properly. Mostly it should be CONNECT_STATE_DIACONNECTED
+     * except for disconnect().
      */
     private void forceCloseConnection() {
         if (mServiceConnection != null) {
@@ -684,8 +692,9 @@
      * Return true if {@code callback} is the current ServiceCallbacks. Also logs if it's not.
      */
     private boolean isCurrent(IMediaBrowserServiceCallbacks callback, String funcName) {
-        if (mServiceCallbacks != callback) {
-            if (mState != CONNECT_STATE_DISCONNECTED) {
+        if (mServiceCallbacks != callback || mState == CONNECT_STATE_DISCONNECTING
+                || mState == CONNECT_STATE_DISCONNECTED) {
+            if (mState != CONNECT_STATE_DISCONNECTING && mState != CONNECT_STATE_DISCONNECTED) {
                 Log.i(TAG, funcName + " for " + mServiceComponent + " with mServiceConnection="
                         + mServiceCallbacks + " this=" + this);
             }
@@ -1040,8 +1049,9 @@
          * Return true if this is the current ServiceConnection. Also logs if it's not.
          */
         private boolean isCurrent(String funcName) {
-            if (mServiceConnection != this) {
-                if (mState != CONNECT_STATE_DISCONNECTED) {
+            if (mServiceConnection != this || mState == CONNECT_STATE_DISCONNECTING
+                    || mState == CONNECT_STATE_DISCONNECTED) {
+                if (mState != CONNECT_STATE_DISCONNECTING && mState != CONNECT_STATE_DISCONNECTED) {
                     // Check mState, because otherwise this log is noisy.
                     Log.i(TAG, funcName + " for " + mServiceComponent + " with mServiceConnection="
                             + mServiceConnection + " this=" + this);
diff --git a/media/jni/android_media_MediaCrypto.cpp b/media/jni/android_media_MediaCrypto.cpp
index 2adbfee..cbdb8ce 100644
--- a/media/jni/android_media_MediaCrypto.cpp
+++ b/media/jni/android_media_MediaCrypto.cpp
@@ -51,6 +51,9 @@
 }
 
 JCrypto::~JCrypto() {
+    if (mCrypto != NULL) {
+        mCrypto->destroyPlugin();
+    }
     mCrypto.clear();
 
     JNIEnv *env = AndroidRuntime::getJNIEnv();
diff --git a/media/jni/android_media_VolumeShaper.h b/media/jni/android_media_VolumeShaper.h
index 73498a2..1a13ffa 100644
--- a/media/jni/android_media_VolumeShaper.h
+++ b/media/jni/android_media_VolumeShaper.h
@@ -40,6 +40,7 @@
         jmethodID opConstructId;
         jfieldID  opFlagsId;
         jfieldID  opReplaceIdId;
+        jfieldID  opXOffsetId;
 
         // VolumeShaper.State
         jclass    stClazz;
@@ -74,9 +75,10 @@
             if (opClazz == nullptr) {
                 return;
             }
-            opConstructId = env->GetMethodID(opClazz, "<init>", "(II)V");
+            opConstructId = env->GetMethodID(opClazz, "<init>", "(IIF)V");
             opFlagsId = env->GetFieldID(opClazz, "mFlags", "I");
             opReplaceIdId = env->GetFieldID(opClazz, "mReplaceId", "I");
+            opXOffsetId = env->GetFieldID(opClazz, "mXOffset", "F");
             env->DeleteLocalRef(lclazz);
 
             lclazz = env->FindClass("android/media/VolumeShaper$State");
@@ -179,17 +181,20 @@
         VolumeShaper::Operation::Flag flags =
             (VolumeShaper::Operation::Flag)env->GetIntField(joperation, fields.opFlagsId);
         int replaceId = env->GetIntField(joperation, fields.opReplaceIdId);
+        float xOffset = env->GetFloatField(joperation, fields.opXOffsetId);
 
-        sp<VolumeShaper::Operation> operation = new VolumeShaper::Operation(flags, replaceId);
+        sp<VolumeShaper::Operation> operation =
+                new VolumeShaper::Operation(flags, replaceId, xOffset);
         return operation;
     }
 
     static jobject convertOperationToJobject(
             JNIEnv *env, const fields_t &fields, const sp<VolumeShaper::Operation> &operation) {
         // prepare constructor args
-        jvalue args[2];
+        jvalue args[3];
         args[0].i = (jint)operation->getFlags();
         args[1].i = (jint)operation->getReplaceId();
+        args[2].f = (jfloat)operation->getXOffset();
 
         jobject joperation = env->NewObjectA(fields.opClazz, fields.opConstructId, args);
         return joperation;
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index 401012f..d4cc3fb 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -86,6 +86,7 @@
     case NO_MEMORY:
         return AUDIOEFFECT_ERROR_NO_MEMORY;
     case DEAD_OBJECT:
+    case FAILED_TRANSACTION: // Hidl crash shows as FAILED_TRANSACTION: -2147483646
         return AUDIOEFFECT_ERROR_DEAD_OBJECT;
     default:
         return AUDIOEFFECT_ERROR;
diff --git a/packages/MtpDocumentsProvider/AndroidManifest.xml b/packages/MtpDocumentsProvider/AndroidManifest.xml
index 843b313..8d79f62 100644
--- a/packages/MtpDocumentsProvider/AndroidManifest.xml
+++ b/packages/MtpDocumentsProvider/AndroidManifest.xml
@@ -22,7 +22,6 @@
                   android:label="@string/downloads_app_label"
                   android:icon="@mipmap/ic_launcher_download"
                   android:theme="@android:style/Theme.NoDisplay"
-                  android:screenOrientation="locked"
                   android:excludeFromRecents="true">
             <intent-filter>
                 <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java b/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
index c5292b8..fe79266 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
@@ -18,6 +18,8 @@
 
 import android.annotation.NonNull;
 import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -27,10 +29,21 @@
  * Sends intent to MtpDocumentsService.
  */
 class ServiceIntentSender {
+    private final static String CHANNEL_ID = "device_notification_channel";
     private Context mContext;
 
     ServiceIntentSender(Context context) {
         mContext = context;
+
+        // Create notification channel.
+        final NotificationChannel mChannel = new NotificationChannel(
+                CHANNEL_ID,
+                context.getResources().getString(
+                        com.android.internal.R.string.default_notification_channel_label),
+                NotificationManager.IMPORTANCE_LOW);
+        final NotificationManager notificationManager =
+                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        notificationManager.createNotificationChannel(mChannel);
     }
 
     /**
@@ -60,12 +73,11 @@
         final String title = context.getResources().getString(
                 R.string.accessing_notification_title,
                 device.name);
-        return new Notification.Builder(context)
+        return new Notification.Builder(context, CHANNEL_ID)
                 .setLocalOnly(true)
                 .setContentTitle(title)
                 .setSmallIcon(com.android.internal.R.drawable.stat_sys_data_usb)
                 .setCategory(Notification.CATEGORY_SYSTEM)
-                .setPriority(Notification.PRIORITY_LOW)
                 .setFlag(Notification.FLAG_NO_CLEAR, true)
                 .build();
     }
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 0447c52..aa0becf 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -210,7 +210,7 @@
     <string name="dev_settings_warning_title" msgid="7244607768088540165">"Vil du tillade udviklingsindstillinger?"</string>
     <string name="dev_settings_warning_message" msgid="2298337781139097964">"Disse indstillinger er kun beregnet til brug i forbindelse med udvikling. De kan forårsage, at din enhed og dens applikationer går ned eller ikke fungerer korrekt."</string>
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificer apps via USB"</string>
-    <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrollér apps, der er installeret via ADB/ADT, for skadelig adfærd."</string>
+    <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Tjek apps, der er installeret via ADB/ADT, for skadelig adfærd."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Deaktiverer funktionen til absolut lydstyrke via Bluetooth i tilfælde af problemer med lydstyrken på eksterne enheder, f.eks. uacceptabel høj lyd eller manglende kontrol."</string>
     <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Tillad, at ringetoner på telefonen kan afspilles i Bluetooth-headset"</string>
     <string name="enable_terminal_title" msgid="95572094356054120">"Lokal terminal"</string>
@@ -298,7 +298,7 @@
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inaktiv. Tryk for at skifte."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktiv. Tryk for at skifte."</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"Kørende tjenester"</string>
-    <string name="runningservices_settings_summary" msgid="854608995821032748">"Vis og kontrollér kørende tjenester"</string>
+    <string name="runningservices_settings_summary" msgid="854608995821032748">"Vis og administrer kørende tjenester"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Konfigurer WebView-implementering"</string>
     <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Dette valg er ikke længere gyldigt. Prøv igen."</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 3250d03..399199d 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -109,7 +109,7 @@
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Ton"</string>
     <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afecta ao ton da voz sintetizada"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
-    <string name="tts_lang_use_system" msgid="2679252467416513208">"Utilizar idioma do sistema"</string>
+    <string name="tts_lang_use_system" msgid="2679252467416513208">"Utiliza o idioma do sistema"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma non seleccionado"</string>
     <string name="tts_default_lang_summary" msgid="5219362163902707785">"Define a voz específica do idioma para o texto falado"</string>
     <string name="tts_play_example_title" msgid="7094780383253097230">"Escoitar un exemplo"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 41a116e..3ed642d 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -294,7 +294,7 @@
     <item msgid="8280754435979370728">"നമ്മൾ കാണുന്നത് പോലെയുള്ള സ്വാഭാവിക വർണ്ണങ്ങൾ"</item>
     <item msgid="5363960654009010371">"ഡിജിറ്റൽ ഉള്ളടക്കത്തിനായി വർണ്ണങ്ങൾ ഒപ്റ്റിമൈസ് ചെയ്തു"</item>
   </string-array>
-    <string name="inactive_apps_title" msgid="1317817863508274533">"നിഷ്‌ക്രിയ ആപ്പ്‌സ്"</string>
+    <string name="inactive_apps_title" msgid="1317817863508274533">"നിഷ്‌ക്രിയ ആപ്പുകൾ"</string>
     <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"നിഷ്‌ക്രിയം. മാറ്റുന്നതിനു ടാപ്പുചെയ്യുക."</string>
     <string name="inactive_app_active_summary" msgid="4174921824958516106">"സജീവം. മാറ്റുന്നതിന് ടാപ്പുചെയ്യുക."</string>
     <string name="runningservices_settings_title" msgid="8097287939865165213">"പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 24ede16..7268d00 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -19,6 +19,8 @@
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothCodecStatus;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
@@ -26,16 +28,22 @@
 import android.os.ParcelUuid;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.R;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
-public final class A2dpProfile implements LocalBluetoothProfile {
+public class A2dpProfile implements LocalBluetoothProfile {
     private static final String TAG = "A2dpProfile";
     private static boolean V = false;
 
+    private Context mContext;
+
     private BluetoothA2dp mService;
+    BluetoothA2dpWrapper.Factory mWrapperFactory;
+    private BluetoothA2dpWrapper mServiceWrapper;
     private boolean mIsProfileReady;
 
     private final LocalBluetoothAdapter mLocalAdapter;
@@ -59,6 +67,7 @@
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
             if (V) Log.d(TAG,"Bluetooth service connected");
             mService = (BluetoothA2dp) proxy;
+            mServiceWrapper = mWrapperFactory.getInstance(mService);
             // We just bound to the service, so refresh the UI for any connected A2DP devices.
             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
             while (!deviceList.isEmpty()) {
@@ -88,13 +97,20 @@
     A2dpProfile(Context context, LocalBluetoothAdapter adapter,
             CachedBluetoothDeviceManager deviceManager,
             LocalBluetoothProfileManager profileManager) {
+        mContext = context;
         mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mProfileManager = profileManager;
+        mWrapperFactory = new BluetoothA2dpWrapperImpl.Factory();
         mLocalAdapter.getProfileProxy(context, new A2dpServiceListener(),
                 BluetoothProfile.A2DP);
     }
 
+    @VisibleForTesting
+    void setWrapperFactory(BluetoothA2dpWrapper.Factory factory) {
+        mWrapperFactory = factory;
+    }
+
     public boolean isConnectable() {
         return true;
     }
@@ -173,6 +189,72 @@
         return false;
     }
 
+    public boolean supportsHighQualityAudio(BluetoothDevice device) {
+        int support = mServiceWrapper.supportsOptionalCodecs(device);
+        return support == BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED;
+    }
+
+    public boolean isHighQualityAudioEnabled(BluetoothDevice device) {
+        int enabled = mServiceWrapper.getOptionalCodecsEnabled(device);
+        if (enabled != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN) {
+            return enabled == BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED;
+        } else if (getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED &&
+                supportsHighQualityAudio(device)) {
+            // Since we don't have a stored preference and the device isn't connected, just return
+            // true since the default behavior when the device gets connected in the future would be
+            // to have optional codecs enabled.
+            return true;
+        }
+        BluetoothCodecConfig codecConfig = null;
+        if (mServiceWrapper.getCodecStatus() != null) {
+            codecConfig = mServiceWrapper.getCodecStatus().getCodecConfig();
+        }
+        if (codecConfig != null)  {
+            return !codecConfig.isMandatoryCodec();
+        } else {
+            return false;
+        }
+    }
+
+    public void setHighQualityAudioEnabled(BluetoothDevice device, boolean enabled) {
+        int prefValue = enabled
+                ? BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED
+                : BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED;
+        mServiceWrapper.setOptionalCodecsEnabled(device, prefValue);
+        if (getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) {
+            return;
+        }
+        if (enabled) {
+            mService.enableOptionalCodecs();
+        } else {
+            mService.disableOptionalCodecs();
+        }
+    }
+
+    public String getHighQualityAudioOptionLabel(BluetoothDevice device) {
+        int unknownCodecId = R.string.bluetooth_profile_a2dp_high_quality_unknown_codec;
+        if (!supportsHighQualityAudio(device) ||
+                getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) {
+            return mContext.getString(unknownCodecId);
+        }
+        // We want to get the highest priority codec, since that's the one that will be used with
+        // this device, and see if it is high-quality (ie non-mandatory).
+        BluetoothCodecConfig[] selectable = null;
+        if (mServiceWrapper.getCodecStatus() != null) {
+            selectable = mServiceWrapper.getCodecStatus().getCodecsSelectableCapabilities();
+            // To get the highest priority, we sort in reverse.
+            Arrays.sort(selectable,
+                    (a, b) -> {
+                        return b.getCodecPriority() - a.getCodecPriority();
+                    });
+        }
+        if (selectable == null || selectable.length < 1 || selectable[0].isMandatoryCodec()) {
+            return mContext.getString(unknownCodecId);
+        }
+        return mContext.getString(R.string.bluetooth_profile_a2dp_high_quality,
+                selectable[0].getCodecName());
+    }
+
     public String toString() {
         return NAME;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapper.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapper.java
new file mode 100644
index 0000000..aa3e835
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapper.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothCodecStatus;
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * This interface replicates some methods of android.bluetooth.BluetoothA2dp that are new and not
+ * yet available in our current version of  Robolectric. It provides a thin wrapper to call the real
+ * methods in production and a mock in tests.
+ */
+public interface BluetoothA2dpWrapper {
+
+    static interface Factory {
+        BluetoothA2dpWrapper getInstance(BluetoothA2dp service);
+    }
+
+    /**
+     * @return the real {@code BluetoothA2dp} object
+     */
+    BluetoothA2dp getService();
+
+    /**
+     * Wraps {@code BluetoothA2dp.getCodecStatus}
+     */
+    public BluetoothCodecStatus getCodecStatus();
+
+    /**
+     * Wraps {@code BluetoothA2dp.supportsOptionalCodecs}
+     */
+    int supportsOptionalCodecs(BluetoothDevice device);
+
+    /**
+     * Wraps {@code BluetoothA2dp.getOptionalCodecsEnabled}
+     */
+    int getOptionalCodecsEnabled(BluetoothDevice device);
+
+    /**
+     * Wraps {@code BluetoothA2dp.setOptionalCodecsEnabled}
+     */
+    void setOptionalCodecsEnabled(BluetoothDevice device, int value);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapperImpl.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapperImpl.java
new file mode 100644
index 0000000..14fa796
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapperImpl.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothCodecStatus;
+import android.bluetooth.BluetoothDevice;
+
+public class BluetoothA2dpWrapperImpl implements BluetoothA2dpWrapper {
+
+    public static class Factory implements BluetoothA2dpWrapper.Factory {
+        @Override
+        public BluetoothA2dpWrapper getInstance(BluetoothA2dp service) {
+            return new BluetoothA2dpWrapperImpl(service);
+        }
+    }
+
+    private BluetoothA2dp mService;
+
+    public BluetoothA2dpWrapperImpl(BluetoothA2dp service) {
+        mService = service;
+    }
+
+    @Override
+    public BluetoothA2dp getService() {
+        return mService;
+    }
+
+    @Override
+    public BluetoothCodecStatus getCodecStatus() {
+        return mService.getCodecStatus();
+    }
+
+    @Override
+    public int supportsOptionalCodecs(BluetoothDevice device) {
+        return mService.supportsOptionalCodecs(device);
+    }
+
+    @Override
+    public int getOptionalCodecsEnabled(BluetoothDevice device) {
+        return mService.getOptionalCodecsEnabled(device);
+    }
+
+    @Override
+    public void setOptionalCodecsEnabled(BluetoothDevice device, int value) {
+        mService.setOptionalCodecsEnabled(device, value);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 5a9a749..0750dc7 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -42,7 +42,7 @@
  * LocalBluetoothProfileManager provides access to the LocalBluetoothProfile
  * objects for the available Bluetooth profiles.
  */
-public final class LocalBluetoothProfileManager {
+public class LocalBluetoothProfileManager {
     private static final String TAG = "LocalBluetoothProfileManager";
     private static final boolean DEBUG = Utils.D;
     /** Singleton instance. */
diff --git a/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java b/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java
new file mode 100644
index 0000000..656ab86
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+/**
+ * A placeholder class to prevent ClassNotFound exceptions caused by lack of visibility.
+ */
+public class BluetoothCodecConfig {
+    public boolean isMandatoryCodec() { return true; }
+    public String getCodecName() { return null;}
+}
diff --git a/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecStatus.java b/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecStatus.java
new file mode 100644
index 0000000..919ec3f
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecStatus.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+/**
+ * A placeholder class to prevent ClassNotFound exceptions caused by lack of visibility.
+ */
+public class BluetoothCodecStatus {
+    public BluetoothCodecConfig getCodecConfig() { return null; }
+    public BluetoothCodecConfig[] getCodecsSelectableCapabilities() { return null; }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
new file mode 100644
index 0000000..07a0e11
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothCodecStatus;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import com.android.settingslib.R;
+import com.android.settingslib.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class A2dpProfileTest {
+
+    @Mock Context mContext;
+    @Mock LocalBluetoothAdapter mAdapter;
+    @Mock CachedBluetoothDeviceManager mDeviceManager;
+    @Mock LocalBluetoothProfileManager mProfileManager;
+    @Mock BluetoothDevice mDevice;
+    @Mock BluetoothA2dp mBluetoothA2dp;
+    @Mock BluetoothA2dpWrapper mBluetoothA2dpWrapper;
+    BluetoothProfile.ServiceListener mServiceListener;
+
+    A2dpProfile mProfile;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        // Capture the A2dpServiceListener our A2dpProfile will pass during its constructor, so that
+        // we can call its onServiceConnected method and get it to use our mock BluetoothA2dp
+        // object.
+        doAnswer((invocation) -> {
+            mServiceListener = (BluetoothProfile.ServiceListener) invocation.getArguments()[1];
+            return null;
+        }).when(mAdapter).getProfileProxy(any(Context.class), any(), eq(BluetoothProfile.A2DP));
+
+        mProfile = new A2dpProfile(mContext, mAdapter, mDeviceManager, mProfileManager);
+        mProfile.setWrapperFactory((service) -> { return mBluetoothA2dpWrapper; });
+        mServiceListener.onServiceConnected(BluetoothProfile.A2DP, mBluetoothA2dp);
+    }
+
+    @Test
+    public void supportsHighQualityAudio() {
+        when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
+        assertThat(mProfile.supportsHighQualityAudio(mDevice)).isTrue();
+
+        when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
+        assertThat(mProfile.supportsHighQualityAudio(mDevice)).isFalse();
+
+        when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN);
+        assertThat(mProfile.supportsHighQualityAudio(mDevice)).isFalse();
+    }
+
+    @Test
+    public void isHighQualityAudioEnabled() {
+        when(mBluetoothA2dpWrapper.getOptionalCodecsEnabled(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED);
+        assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue();
+
+        when(mBluetoothA2dpWrapper.getOptionalCodecsEnabled(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED);
+        assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse();
+
+        // If we don't have a stored pref for whether optional codecs should be enabled or not,
+        // then isHighQualityAudioEnabled() should return true or false based on whether optional
+        // codecs are supported. If the device is connected then we should ask it directly, but if
+        // the device isn't connected then rely on the stored pref about such support.
+        when(mBluetoothA2dpWrapper.getOptionalCodecsEnabled(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN);
+        when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+                BluetoothProfile.STATE_DISCONNECTED);
+
+        when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
+        assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse();
+
+        when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
+        assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue();
+
+        when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+                BluetoothProfile.STATE_CONNECTED);
+        BluetoothCodecStatus status = mock(BluetoothCodecStatus.class);
+        when(mBluetoothA2dpWrapper.getCodecStatus()).thenReturn(status);
+        BluetoothCodecConfig config = mock(BluetoothCodecConfig.class);
+        when(status.getCodecConfig()).thenReturn(config);
+        when(config.isMandatoryCodec()).thenReturn(false);
+        assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue();
+        when(config.isMandatoryCodec()).thenReturn(true);
+        assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse();
+    }
+
+    // Strings to use in fake resource lookups.
+    private static String KNOWN_CODEC_LABEL = "Use high quality audio: %1$s";
+    private static String UNKNOWN_CODEC_LABEL = "Use high quality audio";
+
+    /**
+     * Helper for setting up several tests of getHighQualityAudioOptionLabel
+     */
+    private void setupLabelTest() {
+        // SettingsLib doesn't have string resource lookup working for robotests, so fake our own
+        // string loading.
+        when(mContext.getString(eq(R.string.bluetooth_profile_a2dp_high_quality),
+                any(String.class))).thenAnswer((invocation) -> {
+            return String.format(KNOWN_CODEC_LABEL, invocation.getArguments()[1]);
+        });
+        when(mContext.getString(eq(R.string.bluetooth_profile_a2dp_high_quality_unknown_codec)))
+                .thenReturn(UNKNOWN_CODEC_LABEL);
+
+        // Most tests want to simulate optional codecs being supported by the device, so do that
+        // by default here.
+        when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
+    }
+
+    @Test
+    public void getLableCodecsNotSupported() {
+        setupLabelTest();
+        when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
+        assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(UNKNOWN_CODEC_LABEL);
+    }
+
+    @Test
+    public void getLabelDeviceDisconnected() {
+        setupLabelTest();
+        when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+                BluetoothProfile.STATE_DISCONNECTED);
+        assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(UNKNOWN_CODEC_LABEL);
+    }
+
+    @Test
+    public void getLabelDeviceConnectedButNotHighQualityCodec() {
+        setupLabelTest();
+        when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+                BluetoothProfile.STATE_CONNECTED);
+        BluetoothCodecStatus status = mock(BluetoothCodecStatus.class);
+        BluetoothCodecConfig config = mock(BluetoothCodecConfig.class);
+        BluetoothCodecConfig[] configs = {config};
+        when(mBluetoothA2dpWrapper.getCodecStatus()).thenReturn(status);
+        when(status.getCodecsSelectableCapabilities()).thenReturn(configs);
+
+        when(config.isMandatoryCodec()).thenReturn(true);
+        assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(UNKNOWN_CODEC_LABEL);
+    }
+
+    @Test
+    public void getLabelDeviceConnectedWithHighQualityCodec() {
+        setupLabelTest();
+        when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+                BluetoothProfile.STATE_CONNECTED);
+        BluetoothCodecStatus status = mock(BluetoothCodecStatus.class);
+        BluetoothCodecConfig config = mock(BluetoothCodecConfig.class);
+        BluetoothCodecConfig[] configs = {config};
+        when(mBluetoothA2dpWrapper.getCodecStatus()).thenReturn(status);
+        when(status.getCodecsSelectableCapabilities()).thenReturn(configs);
+
+        when(config.isMandatoryCodec()).thenReturn(false);
+        when(config.getCodecName()).thenReturn("PiedPiper");
+        assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(
+                String.format(KNOWN_CODEC_LABEL, config.getCodecName()));
+    }
+}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 5460304..79b02a5 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -187,6 +187,9 @@
     <!-- to access ResolverRankerServices -->
     <uses-permission android:name="android.permission.BIND_RESOLVER_RANKER_SERVICE" />
 
+    <!-- to access instant apps -->
+    <uses-permission android:name="android.permission.ACCESS_INSTANT_APPS" />
+
     <application
         android:name=".SystemUIApplication"
         android:persistent="true"
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 6fe00c0..bbd315e 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -71,51 +71,51 @@
         android:layout_height="wrap_content"
         android:layout_marginBottom="20dp"
         android:layout_marginEnd="@*android:dimen/notification_content_margin_end"
-        android:orientation="horizontal">
+        android:orientation="vertical">
         <!-- Channel Text -->
         <LinearLayout
-            android:layout_width="0dp"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:orientation="vertical">
+            android:orientation="horizontal">
             <!-- Channel Name -->
             <TextView
                 android:id="@+id/channel_name"
-                android:layout_width="wrap_content"
+                android:layout_width="0dp"
                 android:layout_height="wrap_content"
+                android:layout_weight="1"
                 android:layout_marginBottom="6dp"
                 style="@style/TextAppearance.NotificationInfo.Primary" />
-            <!-- Secondary Text - only one shows at a time -->
-            <TextView
-                android:id="@+id/channel_disabled"
+            <!-- Ban Channel Switch -->
+            <Switch
+                android:id="@+id/channel_enabled_switch"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:text="@string/notification_channel_disabled"
-                style="@style/TextAppearance.NotificationInfo.Secondary.Warning" />
-            <TextView
-                android:id="@+id/num_channels_desc"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/notification_channel_disabled"
-                style="@style/TextAppearance.NotificationInfo.Secondary" />
-            <!-- Optional link to app. Only appears if the channel is not disabled -->
-            <TextView
-                android:id="@+id/app_settings"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:visibility="gone"
-                android:ellipsize="end"
-                android:maxLines="1"
-                style="@style/TextAppearance.NotificationInfo.Secondary.Link"/>
+                android:layout_gravity="end|center_vertical"
+                android:contentDescription="@string/notification_channel_switch_accessibility"
+                android:background="@null" />
         </LinearLayout>
-        <!-- Ban Channel Switch -->
-        <Switch
-            android:id="@+id/channel_enabled_switch"
+        <!-- Secondary Text - only one shows at a time -->
+        <TextView
+            android:id="@+id/channel_disabled"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_gravity="end|center_vertical"
-            android:contentDescription="@string/notification_channel_switch_accessibility"
-            android:background="@null" />
+            android:text="@string/notification_channel_disabled"
+            style="@style/TextAppearance.NotificationInfo.Secondary.Warning" />
+        <TextView
+            android:id="@+id/num_channels_desc"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/notification_channel_disabled"
+            style="@style/TextAppearance.NotificationInfo.Secondary" />
+        <!-- Optional link to app. Only appears if the channel is not disabled -->
+        <TextView
+            android:id="@+id/app_settings"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+            android:ellipsize="end"
+            android:maxLines="1"
+            style="@style/TextAppearance.NotificationInfo.Secondary.Link"/>
     </LinearLayout>
 
     <!-- Settings and Done buttons -->
diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml
index 7367a10..629e306 100644
--- a/packages/SystemUI/res/values-it/strings_tv.xml
+++ b/packages/SystemUI/res/values-it/strings_tv.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-picture"</string>
+    <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-Picture"</string>
     <string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Programma senza titolo)"</string>
     <string name="pip_close" msgid="3480680679023423574">"Chiudi PIP"</string>
     <string name="pip_fullscreen" msgid="8604643018538487816">"Schermo intero"</string>
diff --git a/packages/SystemUI/res/values-pa/strings_tv.xml b/packages/SystemUI/res/values-pa/strings_tv.xml
index bdd8bee..245fc44 100644
--- a/packages/SystemUI/res/values-pa/strings_tv.xml
+++ b/packages/SystemUI/res/values-pa/strings_tv.xml
@@ -20,7 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="notification_channel_tv_pip" msgid="134047986446577723">"ਤਸਵੀਰ-ਵਿੱਚ-ਤਸਵੀਰ"</string>
-    <string name="pip_notification_unknown_title" msgid="6289156118095849438">"(ਕੋਈ ਸਿਰਲੇਖ ਪ੍ਰੋਗਰਾਮ ਨਹੀਂ)"</string>
+    <string name="pip_notification_unknown_title" msgid="6289156118095849438">"(ਸਿਰਲੇਖ-ਰਹਿਤ ਪ੍ਰੋਗਰਾਮ)"</string>
     <string name="pip_close" msgid="3480680679023423574">"PIP ਬੰਦ ਕਰੋ"</string>
     <string name="pip_fullscreen" msgid="8604643018538487816">"ਪੂਰੀ ਸਕ੍ਰੀਨ"</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 2d30476..ad82840 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -164,7 +164,7 @@
     private int mRingMode;
     private int mPhoneState;
     private boolean mKeyguardIsVisible;
-
+    private boolean mKeyguardGoingAway;
     private boolean mGoingToSleep;
     private boolean mBouncer;
     private boolean mBootCompleted;
@@ -406,6 +406,14 @@
         }
     }
 
+    /**
+     * Updates KeyguardUpdateMonitor's internal state to know if keyguard is goingAway
+     * @param goingAway
+     */
+    public void setKeyguardGoingAway(boolean goingAway) {
+        mKeyguardGoingAway = goingAway;
+    }
+
     private void onFingerprintAuthenticated(int userId) {
         Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
         mUserFingerprintAuthenticated.put(userId, true);
@@ -1113,7 +1121,8 @@
     }
 
     private boolean shouldListenForFingerprint() {
-        return (mKeyguardIsVisible || !mDeviceInteractive || mBouncer || mGoingToSleep)
+        return (mKeyguardIsVisible || !mDeviceInteractive ||
+                    (mBouncer && !mKeyguardGoingAway) || mGoingToSleep)
                 && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser());
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index f4d4a9f..0cf8ff0 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -264,6 +264,8 @@
         mProviders.put(AccessibilityManagerWrapper.class,
                 () -> new AccessibilityManagerWrapper(mContext));
 
+        mProviders.put(UiOffloadThread.class, UiOffloadThread::new);
+
         // Put all dependencies above here so the factory can override them if it wants.
         SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java b/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java
new file mode 100644
index 0000000..82fd9b3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+/**
+ * Thread that offloads work from the UI thread but that is still perceptible to the user, so the
+ * priority is the same as the main thread.
+ */
+public class UiOffloadThread {
+
+    private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
+
+    public Future<?> submit(Runnable runnable) {
+        return mExecutorService.submit(runnable);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 1abea37..a129ace 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -30,7 +30,10 @@
 import android.view.MotionEvent;
 import android.view.accessibility.AccessibilityManager;
 
+import com.android.systemui.Dependency;
+import com.android.systemui.UiOffloadThread;
 import com.android.systemui.analytics.DataCollector;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.statusbar.StatusBarState;
 
 import java.io.PrintWriter;
@@ -63,6 +66,7 @@
     private final DataCollector mDataCollector;
     private final HumanInteractionClassifier mHumanInteractionClassifier;
     private final AccessibilityManager mAccessibilityManager;
+    private final UiOffloadThread mUiOffloadThread;
 
     private static FalsingManager sInstance = null;
 
@@ -86,6 +90,7 @@
         mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
         mDataCollector = DataCollector.getInstance(mContext);
         mHumanInteractionClassifier = HumanInteractionClassifier.getInstance(mContext);
+        mUiOffloadThread = Dependency.get(UiOffloadThread.class);
         mScreenOn = context.getSystemService(PowerManager.class).isInteractive();
 
         mContext.getContentResolver().registerContentObserver(
@@ -130,7 +135,11 @@
     private void sessionExitpoint(boolean force) {
         if (mSessionActive && (force || !shouldSessionBeActive())) {
             mSessionActive = false;
-            mSensorManager.unregisterListener(this);
+
+            // This can be expensive, and doesn't need to happen on the main thread.
+            mUiOffloadThread.submit(() -> {
+                mSensorManager.unregisterListener(this);
+            });
         }
     }
 
@@ -154,7 +163,11 @@
         for (int sensorType : sensors) {
             Sensor s = mSensorManager.getDefaultSensor(sensorType);
             if (s != null) {
-                mSensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);
+
+                // This can be expensive, and doesn't need to happen on the main thread.
+                mUiOffloadThread.submit(() -> {
+                    mSensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);
+                });
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
index 262d29d..745f312 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
@@ -17,6 +17,10 @@
 package com.android.systemui.keyguard;
 
 import com.android.internal.policy.IKeyguardDismissCallback;
+import com.android.systemui.Dependency;
+import com.android.systemui.UiOffloadThread;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 
 import java.util.ArrayList;
 
@@ -26,6 +30,7 @@
 public class DismissCallbackRegistry {
 
     private final ArrayList<DismissCallbackWrapper> mDismissCallbacks = new ArrayList<>();
+    private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
 
     public void addCallback(IKeyguardDismissCallback callback) {
         mDismissCallbacks.add(new DismissCallbackWrapper(callback));
@@ -33,14 +38,16 @@
 
     public void notifyDismissCancelled() {
         for (int i = mDismissCallbacks.size() - 1; i >= 0; i--) {
-            mDismissCallbacks.get(i).notifyDismissCancelled();
+            DismissCallbackWrapper callback = mDismissCallbacks.get(i);
+            mUiOffloadThread.submit(callback::notifyDismissCancelled);
         }
         mDismissCallbacks.clear();
     }
 
     public void notifyDismissSucceeded() {
         for (int i = mDismissCallbacks.size() - 1; i >= 0; i--) {
-            mDismissCallbacks.get(i).notifyDismissSucceeded();
+            DismissCallbackWrapper callback = mDismissCallbacks.get(i);
+            mUiOffloadThread.submit(callback::notifyDismissSucceeded);
         }
         mDismissCallbacks.clear();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 2504e36..b977dd4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -51,6 +51,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.provider.Settings.System;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.EventLog;
@@ -76,9 +77,13 @@
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.LatencyTracker;
 import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.Dependency;
 import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUIFactory;
+import com.android.systemui.UiOffloadThread;
 import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.statusbar.phone.FingerprintUnlockController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.ScrimController;
@@ -162,6 +167,7 @@
     private static final int NOTIFY_SCREEN_TURNED_ON = 15;
     private static final int NOTIFY_SCREEN_TURNED_OFF = 16;
     private static final int NOTIFY_STARTED_GOING_TO_SLEEP = 17;
+    private static final int SET_SWITCHING_USER = 18;
 
     /**
      * The default amount of time we stay awake (used for all key input)
@@ -194,6 +200,7 @@
     private AlarmManager mAlarmManager;
     private AudioManager mAudioManager;
     private StatusBarManager mStatusBarManager;
+    private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
 
     private boolean mSystemReady;
     private boolean mBootCompleted;
@@ -1198,18 +1205,20 @@
             updateInputRestrictedLocked();
         }
     }
+
     private void updateInputRestrictedLocked() {
         boolean inputRestricted = isInputRestricted();
         if (mInputRestricted != inputRestricted) {
             mInputRestricted = inputRestricted;
             int size = mKeyguardStateCallbacks.size();
             for (int i = size - 1; i >= 0; i--) {
+                final IKeyguardStateCallback callback = mKeyguardStateCallbacks.get(i);
                 try {
-                    mKeyguardStateCallbacks.get(i).onInputRestrictedStateChanged(inputRestricted);
+                    callback.onInputRestrictedStateChanged(inputRestricted);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Failed to call onDeviceProvisioned", e);
                     if (e instanceof DeadObjectException) {
-                        mKeyguardStateCallbacks.remove(i);
+                        mKeyguardStateCallbacks.remove(callback);
                     }
                 }
             }
@@ -1398,7 +1407,11 @@
     }
 
     public void setSwitchingUser(boolean switching) {
-        KeyguardUpdateMonitor.getInstance(mContext).setSwitchingUser(switching);
+        Trace.beginSection("KeyguardViewMediator#setSwitchingUser");
+        mHandler.removeMessages(SET_SWITCHING_USER);
+        Message msg = mHandler.obtainMessage(SET_SWITCHING_USER, switching ? 1 : 0, 0);
+        mHandler.sendMessage(msg);
+        Trace.endSection();
     }
 
     /**
@@ -1538,6 +1551,11 @@
                     Log.w(TAG, "Timeout while waiting for activity drawn!");
                     Trace.endSection();
                     break;
+                case SET_SWITCHING_USER:
+                    Trace.beginSection("KeyguardViewMediator#handleMessage SET_SWITCHING_USER");
+                    KeyguardUpdateMonitor.getInstance(mContext).setSwitchingUser(msg.arg1 != 0);
+                    Trace.endSection();
+                    break;
             }
         }
     };
@@ -1559,9 +1577,11 @@
     private void handleKeyguardDone() {
         Trace.beginSection("KeyguardViewMediator#handleKeyguardDone");
         final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
-        if (mLockPatternUtils.isSecure(currentUser)) {
-            mLockPatternUtils.getDevicePolicyManager().reportKeyguardDismissed(currentUser);
-        }
+        mUiOffloadThread.submit(() -> {
+            if (mLockPatternUtils.isSecure(currentUser)) {
+                mLockPatternUtils.getDevicePolicyManager().reportKeyguardDismissed(currentUser);
+            }
+        });
         if (DEBUG) Log.d(TAG, "handleKeyguardDone");
         synchronized (this) {
             resetKeyguardDonePendingLocked();
@@ -1601,10 +1621,12 @@
                 final UserHandle currentUser = new UserHandle(currentUserId);
                 final UserManager um = (UserManager) mContext.getSystemService(
                         Context.USER_SERVICE);
-                for (int profileId : um.getProfileIdsWithDisabled(currentUser.getIdentifier())) {
-                    mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId));
-                }
-                getLockPatternUtils().userPresent(currentUserId);
+                mUiOffloadThread.submit(() -> {
+                    for (int profileId : um.getProfileIdsWithDisabled(currentUser.getIdentifier())) {
+                        mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId));
+                    }
+                    getLockPatternUtils().userPresent(currentUserId);
+                });
             } else {
                 mBootSendUserPresent = true;
             }
@@ -1649,11 +1671,18 @@
                 if (mAudioManager == null) return;
                 mUiSoundsStreamType = mAudioManager.getUiSoundsStreamType();
             }
-            // If the stream is muted, don't play the sound
-            if (mAudioManager.isStreamMute(mUiSoundsStreamType)) return;
 
-            mLockSoundStreamId = mLockSounds.play(soundId,
-                    mLockSoundVolume, mLockSoundVolume, 1/*priortiy*/, 0/*loop*/, 1.0f/*rate*/);
+            mUiOffloadThread.submit(() -> {
+                // If the stream is muted, don't play the sound
+                if (mAudioManager.isStreamMute(mUiSoundsStreamType)) return;
+
+                int id = mLockSounds.play(soundId,
+                        mLockSoundVolume, mLockSoundVolume, 1/*priortiy*/, 0/*loop*/, 1.0f/*rate*/);
+                synchronized (this) {
+                    mLockSoundStreamId = id;
+                }
+            });
+
         }
     }
 
@@ -1661,13 +1690,13 @@
         playSound(mTrustedSoundId);
     }
 
-    private void updateActivityLockScreenState() {
-        Trace.beginSection("KeyguardViewMediator#updateActivityLockScreenState");
-        try {
-            ActivityManager.getService().setLockScreenShown(mShowing);
-        } catch (RemoteException e) {
-        }
-        Trace.endSection();
+    private void updateActivityLockScreenState(boolean showing) {
+        mUiOffloadThread.submit(() -> {
+            try {
+                ActivityManager.getService().setLockScreenShown(showing);
+            } catch (RemoteException e) {
+            }
+        });
     }
 
     /**
@@ -1696,7 +1725,6 @@
             mHideAnimationRun = false;
             adjustStatusBarLocked();
             userActivity();
-
             mShowKeyguardWakeLock.release();
         }
         mKeyguardDisplayManager.show();
@@ -1723,6 +1751,7 @@
                     flags |= WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
                 }
 
+                mUpdateMonitor.setKeyguardGoingAway(true /* goingAway */);
                 // Don't actually hide the Keyguard at the moment, wait for window
                 // manager until it tells us it's safe to do so with
                 // startKeyguardExitAnimation.
@@ -1798,12 +1827,13 @@
 
             mWakeAndUnlocking = false;
             setShowingLocked(false);
+            mDismissCallbackRegistry.notifyDismissSucceeded();
             mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration);
             resetKeyguardDonePendingLocked();
             mHideAnimationRun = false;
             adjustStatusBarLocked();
-            mDismissCallbackRegistry.notifyDismissSucceeded();
             sendUserPresentBroadcast();
+            mUpdateMonitor.setKeyguardGoingAway(false /* goingAway */);
         }
         Trace.endSection();
     }
@@ -1835,7 +1865,10 @@
             }
 
             if (!(mContext instanceof Activity)) {
-                mStatusBarManager.disable(flags);
+                final int finalFlags = flags;
+                mUiOffloadThread.submit(() -> {
+                    mStatusBarManager.disable(finalFlags);
+                });
             }
         }
     }
@@ -2033,18 +2066,21 @@
             mShowing = showing;
             int size = mKeyguardStateCallbacks.size();
             for (int i = size - 1; i >= 0; i--) {
+                IKeyguardStateCallback callback = mKeyguardStateCallbacks.get(i);
                 try {
-                    mKeyguardStateCallbacks.get(i).onShowingStateChanged(showing);
+                    callback.onShowingStateChanged(showing);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Failed to call onShowingStateChanged", e);
                     if (e instanceof DeadObjectException) {
-                        mKeyguardStateCallbacks.remove(i);
+                        mKeyguardStateCallbacks.remove(callback);
                     }
                 }
             }
             updateInputRestrictedLocked();
-            mTrustManager.reportKeyguardShowingChanged();
-            updateActivityLockScreenState();
+            mUiOffloadThread.submit(() -> {
+                mTrustManager.reportKeyguardShowingChanged();
+            });
+            updateActivityLockScreenState(showing);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index da2d38f..0da4681 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -16,9 +16,11 @@
 
 package com.android.systemui.pip.phone;
 
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import android.app.ActivityManager;
+import android.app.ActivityManager.StackInfo;
 import android.app.IActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -33,6 +35,8 @@
 import android.view.WindowManagerGlobal;
 
 import com.android.systemui.pip.BasePipManager;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.component.ExpandPipEvent;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
 import com.android.systemui.statusbar.CommandQueue;
@@ -65,7 +69,7 @@
      */
     TaskStackListener mTaskStackListener = new TaskStackListener() {
         @Override
-        public void onActivityPinned(String packageName) {
+        public void onActivityPinned(String packageName, int taskId) {
             if (!checkCurrentUserId(false /* debug */)) {
                 return;
             }
@@ -186,6 +190,7 @@
                 mInputConsumerController);
         mNotificationController = new PipNotificationController(context, mActivityManager,
                 mTouchHandler.getMotionHelper());
+        EventBus.getDefault().register(this);
     }
 
     /**
@@ -196,6 +201,26 @@
     }
 
     /**
+     * Expands the PIP.
+     */
+    public final void onBusEvent(ExpandPipEvent event) {
+        if (event.clearThumbnailWindows) {
+            try {
+                StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
+                if (stackInfo != null && stackInfo.taskIds != null) {
+                    SystemServicesProxy ssp = SystemServicesProxy.getInstance(mContext);
+                    for (int taskId : stackInfo.taskIds) {
+                        ssp.cancelThumbnailTransition(taskId);
+                    }
+                }
+            } catch (RemoteException e) {
+                // Do nothing
+            }
+        }
+        mTouchHandler.getMotionHelper().expandPip(false /* skipAnimation */);
+    }
+
+    /**
      * Sent from KEYCODE_WINDOW handler in PhoneWindowManager, to request the menu to be shown.
      */
     public void showPictureInPictureMenu() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 766914c..013b9ac 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -63,6 +63,8 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.component.HidePipMenuEvent;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -221,9 +223,9 @@
     protected void onUserLeaveHint() {
         super.onUserLeaveHint();
 
-        // If another task is starting on top of the menu, then finish it so that it can be
+        // If another task is starting on top of the menu, then hide and finish it so that it can be
         // recreated on the top next time it starts
-        finish();
+        hideMenu();
     }
 
     @Override
@@ -231,6 +233,7 @@
         super.onStop();
 
         cancelDelayedFinish();
+        EventBus.getDefault().unregister(this);
     }
 
     @Override
@@ -290,6 +293,19 @@
         // Do nothing
     }
 
+    public final void onBusEvent(HidePipMenuEvent event) {
+        if (mMenuState != MENU_STATE_NONE) {
+            // If the menu is visible in either the closed or full state, then hide the menu and
+            // trigger the animation trigger afterwards
+            event.getAnimationTrigger().increment();
+            hideMenu(() -> {
+                mHandler.post(() -> {
+                    event.getAnimationTrigger().decrement();
+                });
+            }, true /* notifyMenuVisibility */);
+        }
+    }
+
     private void showMenu(int menuState, Rect stackBounds, Rect movementBounds,
             boolean allowMenuTimeout) {
         mAllowMenuTimeout = allowMenuTimeout;
@@ -373,11 +389,16 @@
     private void updateFromIntent(Intent intent) {
         mToControllerMessenger = intent.getParcelableExtra(EXTRA_CONTROLLER_MESSENGER);
         notifyActivityCallback(mMessenger);
+
+        // Register for HidePipMenuEvents once we notify the controller of this activity
+        EventBus.getDefault().register(this);
+
         ParceledListSlice actions = intent.getParcelableExtra(EXTRA_ACTIONS);
         if (actions != null) {
             mActions.clear();
             mActions.addAll(actions.getList());
         }
+
         final int menuState = intent.getIntExtra(EXTRA_MENU_STATE, MENU_STATE_NONE);
         if (menuState != MENU_STATE_NONE) {
             Rect stackBounds = intent.getParcelableExtra(EXTRA_STACK_BOUNDS);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 5afa53f..e310847 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -27,6 +27,7 @@
 import android.content.pm.ParceledListSlice;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Messenger;
@@ -36,6 +37,9 @@
 import android.view.IWindowManager;
 
 import com.android.systemui.pip.phone.PipMediaController.ActionListener;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.component.HidePipMenuEvent;
+import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -119,6 +123,7 @@
     // The dismiss fraction update is sent frequently, so use a temporary bundle for the message
     private Bundle mTmpDismissFractionData = new Bundle();
 
+    private ReferenceCountedTrigger mOnAttachDecrementTrigger;
     private boolean mStartActivityRequested;
     private Messenger mToActivityMessenger;
     private Messenger mMessenger = new Messenger(new Handler() {
@@ -157,6 +162,10 @@
                 case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
                     mToActivityMessenger = msg.replyTo;
                     mStartActivityRequested = false;
+                    if (mOnAttachDecrementTrigger != null) {
+                        mOnAttachDecrementTrigger.decrement();
+                        mOnAttachDecrementTrigger = null;
+                    }
                     // Mark the menu as invisible once the activity finishes as well
                     if (mToActivityMessenger == null) {
                         onMenuStateChanged(MENU_STATE_NONE, true /* resize */);
@@ -181,6 +190,8 @@
         mActivityManager = activityManager;
         mMediaController = mediaController;
         mInputConsumerController = inputConsumerController;
+
+        EventBus.getDefault().register(this);
     }
 
     public void onActivityPinned() {
@@ -244,7 +255,9 @@
     public void showMenu(int menuState, Rect stackBounds, Rect movementBounds,
             boolean allowMenuTimeout) {
         if (DEBUG) {
-            Log.d(TAG, "showMenu() hasActivity=" + (mToActivityMessenger != null));
+            Log.d(TAG, "showMenu() state=" + menuState
+                    + " hasActivity=" + (mToActivityMessenger != null)
+                    + " callers=\n" + Debug.getCallers(5, "    "));
         }
         if (mToActivityMessenger != null) {
             Bundle data = new Bundle();
@@ -288,7 +301,9 @@
      */
     public void hideMenu() {
         if (DEBUG) {
-            Log.d(TAG, "hideMenu() hasActivity=" + (mToActivityMessenger != null));
+            Log.d(TAG, "hideMenu() state=" + mMenuState
+                    + " hasActivity=" + (mToActivityMessenger != null)
+                    + " callers=\n" + Debug.getCallers(5, "    "));
         }
         if (mToActivityMessenger != null) {
             Message m = Message.obtain();
@@ -311,13 +326,6 @@
     }
 
     /**
-     * @return the current menu state.
-     */
-    public int getMenuState() {
-        return mMenuState;
-    }
-
-    /**
      * Sets the menu actions to the actions provided by the current PiP activity.
      */
     public void setAppActions(ParceledListSlice appActions) {
@@ -435,6 +443,15 @@
         mMenuState = menuState;
     }
 
+    public final void onBusEvent(HidePipMenuEvent event) {
+        if (mStartActivityRequested) {
+            // If the menu has been start-requested, but not actually started, then we defer the
+            // trigger callback until the menu has started and called back to the controller
+            mOnAttachDecrementTrigger = event.getAnimationTrigger();
+            mOnAttachDecrementTrigger.increment();
+        }
+    }
+
     public void dump(PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
         pw.println(prefix + TAG);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 590e3c6..9fa7ff6 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -34,6 +34,7 @@
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
+import android.os.Debug;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.util.Log;
@@ -54,6 +55,7 @@
 public class PipMotionHelper {
 
     private static final String TAG = "PipMotionHelper";
+    private static final boolean DEBUG = false;
 
     private static final RectEvaluator RECT_EVALUATOR = new RectEvaluator(new Rect());
 
@@ -150,6 +152,10 @@
      * Resizes the pinned stack back to fullscreen.
      */
     void expandPip(boolean skipAnimation) {
+        if (DEBUG) {
+            Log.d(TAG, "expandPip: skipAnimation=" + skipAnimation
+                    + " callers=\n" + Debug.getCallers(5, "    "));
+        }
         cancelAnimations();
         mMenuController.hideMenuWithoutResize();
         mHandler.post(() -> {
@@ -171,6 +177,9 @@
      * Dismisses the pinned stack.
      */
     void dismissPip() {
+        if (DEBUG) {
+            Log.d(TAG, "dismissPip: callers=\n" + Debug.getCallers(5, "    "));
+        }
         cancelAnimations();
         mMenuController.hideMenuWithoutResize();
         mHandler.post(() -> {
@@ -419,6 +428,10 @@
      * Directly resizes the PiP to the given {@param bounds}.
      */
     private void resizePipUnchecked(Rect toBounds) {
+        if (DEBUG) {
+            Log.d(TAG, "resizePipUnchecked: toBounds=" + toBounds
+                    + " callers=\n" + Debug.getCallers(5, "    "));
+        }
         if (!toBounds.equals(mBounds)) {
             mVsyncChoreographer.scheduleAtSfVsync(() -> {
                 try {
@@ -435,6 +448,10 @@
      * Directly resizes the PiP to the given {@param bounds}.
      */
     private void resizeAndAnimatePipUnchecked(Rect toBounds, int duration) {
+        if (DEBUG) {
+            Log.d(TAG, "resizeAndAnimatePipUnchecked: toBounds=" + toBounds
+                    + " duration=" + duration + " callers=\n" + Debug.getCallers(5, "    "));
+        }
         if (!toBounds.equals(mBounds)) {
             mHandler.post(() -> {
                 try {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 199b027..c35fdd5 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -484,14 +484,15 @@
             // Try and restore the PiP to the closest edge, using the saved snap fraction
             // if possible
             if (resize) {
-                // This is a very special case: when the menu is expanded and visible, navigating to
-                // another activity can trigger auto-enter PiP, and if the revealed activity has a
-                // forced rotation set, then the controller will get updated with the new rotation
-                // of the display. However, at the same time, SystemUI will try to hide the menu by
-                // creating an animation to the normal bounds which are now stale.  In such a case
-                // we defer the animation to the normal bounds until after the next
-                // onMovementBoundsChanged() call to get the bounds in the new orientation
                 if (mDeferResizeToNormalBoundsUntilRotation == -1) {
+                    // This is a very special case: when the menu is expanded and visible,
+                    // navigating to another activity can trigger auto-enter PiP, and if the
+                    // revealed activity has a forced rotation set, then the controller will get
+                    // updated with the new rotation of the display. However, at the same time,
+                    // SystemUI will try to hide the menu by creating an animation to the normal
+                    // bounds which are now stale.  In such a case we defer the animation to the
+                    // normal bounds until after the next onMovementBoundsChanged() call to get the
+                    // bounds in the new orientation
                     try {
                         int displayRotation = mPinnedStackController.getDisplayRotation();
                         if (mDisplayRotation != displayRotation) {
@@ -510,6 +511,9 @@
                     mSavedSnapFraction = -1f;
                 }
             } else {
+                // If resizing is not allowed, then the PiP should be frozen until the transition
+                // ends as well
+                setTouchEnabled(false);
                 mSavedSnapFraction = -1f;
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 6667b71..1c5da4d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -34,7 +34,6 @@
 import android.os.Debug;
 import android.os.Handler;
 import android.os.RemoteException;
-import android.os.SystemProperties;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
@@ -43,7 +42,6 @@
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
 
-import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.pip.BasePipManager;
 import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -109,7 +107,7 @@
     private IWindowManager mWindowManager;
     private MediaSessionManager mMediaSessionManager;
     private int mState = STATE_NO_PIP;
-    private int mResumeResizePinnedStackRunnable = STATE_NO_PIP;
+    private int mResumeResizePinnedStackRunnableState = STATE_NO_PIP;
     private final Handler mHandler = new Handler();
     private List<Listener> mListeners = new ArrayList<>();
     private List<MediaListener> mMediaListeners = new ArrayList<>();
@@ -130,7 +128,7 @@
     private final Runnable mResizePinnedStackRunnable = new Runnable() {
         @Override
         public void run() {
-            resizePinnedStack(mResumeResizePinnedStackRunnable);
+            resizePinnedStack(mResumeResizePinnedStackRunnableState);
         }
     };
     private final Runnable mClosePipRunnable = new Runnable() {
@@ -278,7 +276,7 @@
      * Shows the picture-in-picture menu if an activity is in picture-in-picture mode.
      */
     public void showPictureInPictureMenu() {
-        if (mState == STATE_PIP) {
+        if (getState() == STATE_PIP) {
             resizePinnedStack(STATE_PIP_MENU);
         }
     }
@@ -352,14 +350,15 @@
     void resizePinnedStack(int state) {
         if (DEBUG) Log.d(TAG, "resizePinnedStack() state=" + state, new Exception());
         boolean wasStateNoPip = (mState == STATE_NO_PIP);
-        mResumeResizePinnedStackRunnable = state;
         for (int i = mListeners.size() - 1; i >= 0; --i) {
             mListeners.get(i).onPipResizeAboutToStart();
         }
         if (mSuspendPipResizingReason != 0) {
+            mResumeResizePinnedStackRunnableState = state;
             if (DEBUG) Log.d(TAG, "resizePinnedStack() deferring"
                     + " mSuspendPipResizingReason=" + mSuspendPipResizingReason
-                    + " mResumeResizePinnedStackRunnable=" + mResumeResizePinnedStackRunnable);
+                    + " mResumeResizePinnedStackRunnableState="
+                    + mResumeResizePinnedStackRunnableState);
             return;
         }
         mState = state;
@@ -392,6 +391,16 @@
     }
 
     /**
+     * @return the current state, or the pending state if the state change was previously suspended.
+     */
+    private int getState() {
+        if (mSuspendPipResizingReason != 0) {
+            return mResumeResizePinnedStackRunnableState;
+        }
+        return mState;
+    }
+
+    /**
      * Returns the default PIP bound.
      */
     public Rect getPipBounds() {
@@ -459,7 +468,7 @@
     }
 
     private void handleMediaResourceGranted(String[] packageNames) {
-        if (mState == STATE_NO_PIP) {
+        if (getState() == STATE_NO_PIP) {
             mLastPackagesResourceGranted = packageNames;
         } else {
             boolean requestedFromLastPackages = false;
@@ -482,7 +491,7 @@
 
     private void updateMediaController(List<MediaController> controllers) {
         MediaController mediaController = null;
-        if (controllers != null && mState != STATE_NO_PIP && mPipComponentName != null) {
+        if (controllers != null && getState() != STATE_NO_PIP && mPipComponentName != null) {
             for (int i = controllers.size() - 1; i >= 0; i--) {
                 MediaController controller = controllers.get(i);
                 // We assumes that an app with PIPable activity
@@ -571,7 +580,7 @@
             if (!checkCurrentUserId(DEBUG)) {
                 return;
             }
-            if (mState != STATE_NO_PIP) {
+            if (getState() != STATE_NO_PIP) {
                 boolean hasPip = false;
 
                 StackInfo stackInfo = getPinnedStackInfo();
@@ -593,7 +602,7 @@
                     return;
                 }
             }
-            if (mState == STATE_PIP) {
+            if (getState() == STATE_PIP) {
                 Rect bounds = isSettingsShown() ? mSettingsPipBounds : mDefaultPipBounds;
                 if (mPipBounds != bounds) {
                     mPipBounds = bounds;
@@ -603,7 +612,7 @@
         }
 
         @Override
-        public void onActivityPinned(String packageName) {
+        public void onActivityPinned(String packageName, int taskId) {
             if (DEBUG) Log.d(TAG, "onActivityPinned()");
             if (!checkCurrentUserId(DEBUG)) {
                 return;
@@ -645,7 +654,7 @@
             if (!checkCurrentUserId(DEBUG)) {
                 return;
             }
-            switch (mState) {
+            switch (getState()) {
                 case STATE_PIP_MENU:
                     showPipMenu();
                     break;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index c0e4b99..dbf0724 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -62,6 +62,7 @@
 import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
 import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
 import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
+import com.android.systemui.recents.events.component.ActivityUnpinnedEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
 import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
@@ -203,8 +204,12 @@
                                 Recents.getSystemServices().removeTask(task.persistentId);
                             }
                         }
-                        Settings.Secure.putLongForUser(RecentsActivity.this.getContentResolver(),
-                                Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, currentTime, currentUser);
+                        Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync(
+                                currentTime, currentUser);
+
+                        // Clear the last PiP task time, it's an edge case and we'd rather it
+                        // not relaunch the PiP task if the user double taps
+                        RecentsImpl.clearLastPipTime();
                     }
                 }
             }
@@ -395,6 +400,7 @@
      * Reloads the stack views upon launching Recents.
      */
     private void reloadStackView() {
+
         // If the Recents component has preloaded a load plan, then use that to prevent
         // reconstructing the task stack
         RecentsTaskLoader loader = Recents.getTaskLoader();
@@ -501,28 +507,7 @@
     public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
         super.onMultiWindowModeChanged(isInMultiWindowMode);
 
-        // Reload the task stack completely
-        RecentsConfiguration config = Recents.getConfiguration();
-        RecentsActivityLaunchState launchState = config.getLaunchState();
-        RecentsTaskLoader loader = Recents.getTaskLoader();
-        RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
-        loader.preloadTasks(loadPlan, -1 /* runningTaskId */,
-                false /* includeFrontMostExcludedTask */);
-
-        RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
-        loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
-        loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
-        loader.loadTasks(this, loadPlan, loadOpts);
-
-        TaskStack stack = loadPlan.getTaskStack();
-        int numStackTasks = stack.getStackTaskCount();
-        boolean showDeferredAnimation = numStackTasks > 0;
-
-        EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */,
-                false /* fromDeviceOrientationChange */, false /* fromDisplayDensityChange */,
-                numStackTasks > 0));
-        EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode,
-                showDeferredAnimation, stack));
+        reloadTaskStack(isInMultiWindowMode, true /* sendConfigChangedEvent */);
     }
 
     @Override
@@ -821,6 +806,41 @@
         mRecentsView.invalidate();
     }
 
+    public final void onBusEvent(final ActivityUnpinnedEvent event) {
+        if (mIsVisible) {
+            // Skip the configuration change event as the PiP activity does not actually affect the
+            // config of recents
+            reloadTaskStack(isInMultiWindowMode(), false /* sendConfigChangedEvent */);
+        }
+    }
+
+    private void reloadTaskStack(boolean isInMultiWindowMode, boolean sendConfigChangedEvent) {
+        // Reload the task stack completely
+        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsActivityLaunchState launchState = config.getLaunchState();
+        RecentsTaskLoader loader = Recents.getTaskLoader();
+        RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
+        loader.preloadTasks(loadPlan, -1 /* runningTaskId */,
+                false /* includeFrontMostExcludedTask */);
+
+        RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
+        loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
+        loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
+        loader.loadTasks(this, loadPlan, loadOpts);
+
+        TaskStack stack = loadPlan.getTaskStack();
+        int numStackTasks = stack.getStackTaskCount();
+        boolean showDeferredAnimation = numStackTasks > 0;
+
+        if (sendConfigChangedEvent) {
+            EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */,
+                    false /* fromDeviceOrientationChange */, false /* fromDisplayDensityChange */,
+                    numStackTasks > 0));
+        }
+        EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode,
+                showDeferredAnimation, stack));
+    }
+
     @Override
     public boolean onPreDraw() {
         mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index a7f6b70..5b8ed94 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -29,6 +29,10 @@
 
     public boolean launchedWithAltTab;
     public boolean launchedFromApp;
+    // Set if the activity that we launched from entered PiP during the transition into Recents
+    public boolean launchedFromPipApp;
+    // Set if the next activity that quick-switch will launch is the PiP activity
+    public boolean launchedWithNextPipApp;
     public boolean launchedFromBlacklistedApp;
     public boolean launchedFromHome;
     public boolean launchedViaDragGesture;
@@ -41,6 +45,8 @@
         launchedFromHome = false;
         launchedFromApp = false;
         launchedFromBlacklistedApp = false;
+        launchedFromPipApp = false;
+        launchedWithNextPipApp = false;
         launchedToTaskId = -1;
         launchedWithAltTab = false;
         launchedViaDragGesture = false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 2b812a5..e229c90 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -35,15 +35,18 @@
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.SystemClock;
-import android.os.UserHandle;
 import android.util.Log;
 import android.util.MutableBoolean;
+import android.util.Pair;
 import android.view.AppTransitionAnimationSpec;
 import android.view.LayoutInflater;
 import android.view.ViewConfiguration;
 import android.view.WindowManager;
 
 import android.widget.Toast;
+
+import com.google.android.collect.Lists;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.policy.DockedDividerUtils;
 import com.android.systemui.R;
@@ -57,6 +60,9 @@
 import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
 import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
 import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
+import com.android.systemui.recents.events.component.ActivityPinnedEvent;
+import com.android.systemui.recents.events.component.ActivityUnpinnedEvent;
+import com.android.systemui.recents.events.component.HidePipMenuEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
 import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
@@ -71,6 +77,8 @@
 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.views.RecentsTransitionHelper;
+import com.android.systemui.recents.views.RecentsTransitionHelper.AppTransitionAnimationSpecsFuture;
 import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
 import com.android.systemui.recents.views.TaskStackLayoutAlgorithm.VisibilityReport;
 import com.android.systemui.recents.views.TaskStackView;
@@ -127,6 +135,7 @@
                 // previous one.
                 VisibilityReport visibilityReport;
                 synchronized (mDummyStackView) {
+                    mDummyStackView.getStack().removeAllTasks(false /* notifyStackChanges */);
                     mDummyStackView.setTasks(plan.getTaskStack(), false /* allowNotify */);
                     updateDummyStackViewLayout(plan.getTaskStack(),
                             getWindowRect(null /* windowRectOverride */));
@@ -151,12 +160,31 @@
         }
 
         @Override
+        public void onActivityPinned(String packageName, int taskId) {
+            // This time needs to be fetched the same way the last active time is fetched in
+            // {@link TaskRecord#touchActiveTime}
+            Recents.getConfiguration().getLaunchState().launchedFromPipApp = true;
+            Recents.getConfiguration().getLaunchState().launchedWithNextPipApp = false;
+            EventBus.getDefault().send(new ActivityPinnedEvent(taskId));
+            consumeInstanceLoadPlan();
+            sLastPipTime = System.currentTimeMillis();
+        }
+
+        @Override
+        public void onActivityUnpinned() {
+            EventBus.getDefault().send(new ActivityUnpinnedEvent());
+            sLastPipTime = -1;
+        }
+
+        @Override
         public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) {
             EventBus.getDefault().send(new TaskSnapshotChangedEvent(taskId, snapshot));
         }
     }
 
     protected static RecentsTaskLoadPlan sInstanceLoadPlan;
+    // Stores the last pinned task time
+    protected static long sLastPipTime = -1;
 
     protected Context mContext;
     protected Handler mHandler;
@@ -477,7 +505,8 @@
 
         // Launch the task
         ssp.startActivityFromRecents(
-                mContext, toTask.key, toTask.title, launchOpts, INVALID_STACK_ID);
+                mContext, toTask.key, toTask.title, launchOpts, INVALID_STACK_ID,
+                null /* resultListener */);
     }
 
     /**
@@ -550,7 +579,8 @@
 
         // Launch the task
         ssp.startActivityFromRecents(
-                mContext, toTask.key, toTask.title, launchOpts, INVALID_STACK_ID);
+                mContext, toTask.key, toTask.title, launchOpts, INVALID_STACK_ID,
+                null /* resultListener */);
     }
 
     public void showNextAffiliatedTask() {
@@ -593,6 +623,20 @@
     }
 
     /**
+     * @return the time at which a task last entered picture-in-picture.
+     */
+    public static long getLastPipTime() {
+        return sLastPipTime;
+    }
+
+    /**
+     * Clears the time at which a task last entered picture-in-picture.
+     */
+    public static void clearLastPipTime() {
+        sLastPipTime = -1;
+    }
+
+    /**
      * Reloads all the resources for the current configuration.
      */
     private void reloadResources() {
@@ -632,7 +676,7 @@
             windowRect.bottom -= systemInsets.bottom;
             systemInsets.bottom = 0;
         }
-        calculateWindowStableInsets(systemInsets, windowRect);
+        calculateWindowStableInsets(systemInsets, windowRect, displayRect);
         windowRect.offsetTo(0, 0);
 
         synchronized (mDummyStackView) {
@@ -674,6 +718,7 @@
             updateDummyStackViewLayout(stack, windowRect);
             if (stack != null) {
                 TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
+                mDummyStackView.getStack().removeAllTasks(false /* notifyStackChanges */);
                 mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */);
                 // Get the width of a task view so that we know how wide to draw the header bar.
                 if (useGridLayout) {
@@ -721,8 +766,7 @@
      * Given the stable insets and the rect for our window, calculates the insets that affect our
      * window.
      */
-    private void calculateWindowStableInsets(Rect inOutInsets, Rect windowRect) {
-        Rect displayRect = Recents.getSystemServices().getDisplayRect();
+    private void calculateWindowStableInsets(Rect inOutInsets, Rect windowRect, Rect displayRect) {
 
         // Display rect without insets - available app space
         Rect appRect = new Rect(displayRect);
@@ -772,8 +816,9 @@
     /**
      * Creates the activity options for an app->recents transition.
      */
-    private ActivityOptions getThumbnailTransitionActivityOptions(
-            ActivityManager.RunningTaskInfo runningTask, Rect windowOverrideRect) {
+    private Pair<ActivityOptions, AppTransitionAnimationSpecsFuture>
+            getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo runningTask,
+                    Rect windowOverrideRect) {
         if (runningTask != null && runningTask.stackId == FREEFORM_WORKSPACE_STACK_ID) {
             ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>();
             ArrayList<Task> tasks;
@@ -804,23 +849,27 @@
             }
             AppTransitionAnimationSpec[] specsArray = new AppTransitionAnimationSpec[specs.size()];
             specs.toArray(specsArray);
-            return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
-                    specsArray, mHandler, null, this);
+            return new Pair<>(ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
+                    specsArray, mHandler, null, this), null);
         } else {
             // Update the destination rect
             Task toTask = new Task();
             TaskViewTransform toTransform = getThumbnailTransitionTransform(mDummyStackView, toTask,
                     windowOverrideRect);
-            Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform,
-                            mThumbTransitionBitmapCache);
-            if (thumbnail != null) {
-                RectF toTaskRect = toTransform.rect;
-                return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
-                        thumbnail, (int) toTaskRect.left, (int) toTaskRect.top,
-                        (int) toTaskRect.width(), (int) toTaskRect.height(), mHandler, null);
-            }
-            // If both the screenshot and thumbnail fails, then just fall back to the default transition
-            return getUnknownTransitionActivityOptions();
+
+            RectF toTaskRect = toTransform.rect;
+            AppTransitionAnimationSpecsFuture future =
+                    new RecentsTransitionHelper(mContext).getAppTransitionFuture(
+                            () -> {
+                        Rect rect = new Rect();
+                        toTaskRect.round(rect);
+                        Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform,
+                                mThumbTransitionBitmapCache);
+                        return Lists.newArrayList(new AppTransitionAnimationSpec(
+                                toTask.key.id, thumbnail, rect));
+                    });
+            return new Pair<>(ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(mContext,
+                    mHandler, future.getFuture(), null, false /* scaleUp */), future);
         }
     }
 
@@ -919,6 +968,9 @@
         launchState.launchedFromHome = !useThumbnailTransition && !mLaunchedWhileDocking;
         launchState.launchedFromApp = useThumbnailTransition || mLaunchedWhileDocking;
         launchState.launchedFromBlacklistedApp = launchState.launchedFromApp && isBlacklisted;
+        launchState.launchedFromPipApp = false;
+        launchState.launchedWithNextPipApp =
+                stack.isNextLaunchTargetPip(RecentsImpl.getLastPipTime());
         launchState.launchedViaDockGesture = mLaunchedWhileDocking;
         launchState.launchedViaDragGesture = mDraggingInRecents;
         launchState.launchedToTaskId = runningTaskId;
@@ -943,30 +995,31 @@
         launchState.launchedNumVisibleThumbnails = stackVr.numVisibleThumbnails;
 
         if (!animate) {
-            startRecentsActivity(ActivityOptions.makeCustomAnimation(mContext, -1, -1));
+            startRecentsActivity(ActivityOptions.makeCustomAnimation(mContext, -1, -1),
+                    null /* future */);
             return;
         }
 
-        ActivityOptions opts;
+        Pair<ActivityOptions, AppTransitionAnimationSpecsFuture> pair;
         if (isBlacklisted) {
-            opts = getUnknownTransitionActivityOptions();
+            pair = new Pair<>(getUnknownTransitionActivityOptions(), null);
         } else if (useThumbnailTransition) {
             // Try starting with a thumbnail transition
-            opts = getThumbnailTransitionActivityOptions(runningTask, windowOverrideRect);
+            pair = getThumbnailTransitionActivityOptions(runningTask, windowOverrideRect);
         } else {
             // If there is no thumbnail transition, but is launching from home into recents, then
             // use a quick home transition
-            opts = hasRecentTasks
-                ? getHomeTransitionActivityOptions()
-                : getUnknownTransitionActivityOptions();
+            pair = new Pair<>(hasRecentTasks
+                    ? getHomeTransitionActivityOptions()
+                    : getUnknownTransitionActivityOptions(), null);
         }
-        startRecentsActivity(opts);
+        startRecentsActivity(pair.first, pair.second);
         mLastToggleTime = SystemClock.elapsedRealtime();
     }
 
     private Rect getWindowRectOverride(int growTarget) {
         if (growTarget == DividerView.INVALID_RECENTS_GROW_TARGET) {
-            return null;
+            return SystemServicesProxy.getInstance(mContext).getWindowRect();
         }
         Rect result = new Rect();
         Rect displayRect = Recents.getSystemServices().getDisplayRect();
@@ -979,19 +1032,23 @@
     /**
      * Starts the recents activity.
      */
-    private void startRecentsActivity(ActivityOptions opts) {
+    private void startRecentsActivity(ActivityOptions opts,
+            final AppTransitionAnimationSpecsFuture future) {
         Intent intent = new Intent();
         intent.setClassName(RECENTS_PACKAGE, RECENTS_ACTIVITY);
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
                 | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
-
-        if (opts != null) {
-            mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
-        } else {
-            mContext.startActivityAsUser(intent, UserHandle.CURRENT);
-        }
-        EventBus.getDefault().send(new RecentsActivityStartingEvent());
+        Recents.getSystemServices().startActivityAsUserAsync(intent, opts);
+        HidePipMenuEvent hideMenuEvent = new HidePipMenuEvent();
+        hideMenuEvent.addPostAnimationCallback(() -> {
+            Recents.getSystemServices().startActivityAsUserAsync(intent, opts);
+            EventBus.getDefault().send(new RecentsActivityStartingEvent());
+            if (future != null) {
+                future.precacheSpecs();
+            }
+        });
+        EventBus.getDefault().send(hideMenuEvent);
     }
 
     /**** OnAnimationFinishedListener Implementation ****/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
index a737505..d7abb38 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
@@ -810,6 +810,11 @@
     private void queueEvent(final Event event) {
         ArrayList<EventHandler> eventHandlers = mEventTypeMap.get(event.getClass());
         if (eventHandlers == null) {
+            // This is just an optimization to return early if there are no handlers. However, we
+            // should still ensure that we call pre/post dispatch callbacks so that AnimatedEvents
+            // are still cleaned up correctly if a listener has not been registered to handle them
+            event.onPreDispatch();
+            event.onPostDispatch();
             return;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java
new file mode 100644
index 0000000..75bfd7b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.recents.events.activity;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * Sent when the stack should be hidden and the empty view shown.
+ */
+public class ShowEmptyViewEvent extends EventBus.Event {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java
new file mode 100644
index 0000000..f4d2fcf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.component;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when an activity is pinned.
+ */
+public class ActivityPinnedEvent extends EventBus.Event {
+
+    public final int taskId;
+
+    public ActivityPinnedEvent(int taskId) {
+        this.taskId = taskId;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java
new file mode 100644
index 0000000..48c5f0b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.component;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when an activity is unpinned.
+ */
+public class ActivityUnpinnedEvent extends EventBus.Event {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ExpandPipEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ExpandPipEvent.java
new file mode 100644
index 0000000..8fe4975
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/ExpandPipEvent.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.component;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when the PiP should be expanded due to being relaunched.
+ */
+public class ExpandPipEvent extends EventBus.Event {
+    public final boolean clearThumbnailWindows = true;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java
new file mode 100644
index 0000000..ce4f207
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.component;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when the PiP menu should be hidden.
+ */
+public class HidePipMenuEvent extends EventBus.AnimatedEvent {
+    // Simple event
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 8594ec62..a155a71 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -26,6 +26,7 @@
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManager.StackInfo;
 import android.app.ActivityManager.TaskSnapshot;
@@ -57,15 +58,18 @@
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.IRemoteCallback;
-import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
 import android.util.ArraySet;
 import android.util.IconDrawableFactory;
 import android.util.Log;
@@ -82,7 +86,9 @@
 import com.android.internal.app.AssistUtils;
 import com.android.internal.os.BackgroundThread;
 import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.UiOffloadThread;
 import com.android.systemui.pip.tv.PipMenuActivity;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsDebugFlags;
@@ -127,6 +133,8 @@
     PackageManager mPm;
     IconDrawableFactory mDrawableFactory;
     IPackageManager mIpm;
+    private final IDreamManager mDreamManager;
+    private final Context mContext;
     AssistUtils mAssistUtils;
     WindowManager mWm;
     IWindowManager mIwm;
@@ -146,7 +154,8 @@
     Canvas mBgProtectionCanvas;
 
     private final Handler mHandler = new H();
-    private final ExecutorService mOnewayExecutor = Executors.newSingleThreadExecutor();
+
+    private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
 
     /**
      * An abstract class to track task stack changes.
@@ -160,7 +169,7 @@
         public void onTaskStackChangedBackground() { }
         public void onTaskStackChanged() { }
         public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
-        public void onActivityPinned(String packageName) { }
+        public void onActivityPinned(String packageName, int taskId) { }
         public void onActivityUnpinned() { }
         public void onPinnedActivityRestartAttempt(boolean clearedTask) { }
         public void onPinnedStackAnimationStarted() { }
@@ -215,9 +224,9 @@
         }
 
         @Override
-        public void onActivityPinned(String packageName) throws RemoteException {
+        public void onActivityPinned(String packageName, int taskId) throws RemoteException {
             mHandler.removeMessages(H.ON_ACTIVITY_PINNED);
-            mHandler.obtainMessage(H.ON_ACTIVITY_PINNED, packageName).sendToTarget();
+            mHandler.obtainMessage(H.ON_ACTIVITY_PINNED, taskId, 0, packageName).sendToTarget();
         }
 
         @Override
@@ -282,6 +291,7 @@
 
     /** Private constructor */
     private SystemServicesProxy(Context context) {
+        mContext = context.getApplicationContext();
         mAccm = AccessibilityManager.getInstance(context);
         mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
         mIam = ActivityManager.getService();
@@ -293,6 +303,8 @@
         mIwm = WindowManagerGlobal.getWindowManagerService();
         mKgm = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
         mUm = UserManager.get(context);
+        mDreamManager = IDreamManager.Stub.asInterface(
+                ServiceManager.checkService(DreamService.DREAM_SERVICE));
         mDisplay = mWm.getDefaultDisplay();
         mRecentsPackage = context.getPackageName();
         mHasFreeformWorkspaceSupport =
@@ -446,9 +458,18 @@
      * Returns the top running task.
      */
     public ActivityManager.RunningTaskInfo getRunningTask() {
-        List<ActivityManager.RunningTaskInfo> tasks = mAm.getRunningTasks(1);
+        // Note: The set of running tasks from the system is ordered by recency
+        List<ActivityManager.RunningTaskInfo> tasks = mAm.getRunningTasks(10);
         if (tasks != null && !tasks.isEmpty()) {
-            return tasks.get(0);
+            // Find the first task in a valid stack, we ignore everything from the Recents and PiP
+            // stacks
+            for (int i = 0; i < tasks.size(); i++) {
+                ActivityManager.RunningTaskInfo task = tasks.get(i);
+                int stackId = task.stackId;
+                if (stackId != RECENTS_STACK_ID && stackId != PINNED_STACK_ID) {
+                    return task;
+                }
+            }
         }
         return null;
     }
@@ -766,7 +787,7 @@
      * Sends a message to close other system windows.
      */
     public void sendCloseSystemWindows(String reason) {
-        mOnewayExecutor.submit(() -> {
+        mUiOffloadThread.submit(() -> {
             try {
                 mIam.closeSystemDialogs(reason);
             } catch (RemoteException e) {
@@ -1011,7 +1032,12 @@
      * Returns the current user id.
      */
     public int getCurrentUser() {
-        return KeyguardUpdateMonitor.getCurrentUser();
+        if (mAm == null) return 0;
+
+        // This must call through ActivityManager, as the SystemServicesProxy can be called in a
+        // secondary user's SystemUI process, and KeyguardUpdateMonitor is only updated in the
+        // primary user's SystemUI process
+        return mAm.getCurrentUser();
     }
 
     /**
@@ -1115,32 +1141,50 @@
         }
     }
 
+    public void startActivityAsUserAsync(Intent intent, ActivityOptions opts) {
+        mUiOffloadThread.submit(() -> mContext.startActivityAsUser(intent,
+                opts != null ? opts.toBundle() : null, UserHandle.CURRENT));
+    }
+
     /** Starts an activity from recents. */
-    public boolean startActivityFromRecents(Context context, Task.TaskKey taskKey, String taskName,
-            ActivityOptions options, int stackId) {
-        if (mIam != null) {
-            try {
-                if (taskKey.stackId == DOCKED_STACK_ID) {
-                    // We show non-visible docked tasks in Recents, but we always want to launch
-                    // them in the fullscreen stack.
-                    if (options == null) {
-                        options = ActivityOptions.makeBasic();
-                    }
-                    options.setLaunchStackId(FULLSCREEN_WORKSPACE_STACK_ID);
-                } else if (stackId != INVALID_STACK_ID){
-                    if (options == null) {
-                        options = ActivityOptions.makeBasic();
-                    }
-                    options.setLaunchStackId(stackId);
-                }
-                mIam.startActivityFromRecents(
-                        taskKey.id, options == null ? null : options.toBundle());
-                return true;
-            } catch (Exception e) {
-                Log.e(TAG, context.getString(R.string.recents_launch_error_message, taskName), e);
-            }
+    public void startActivityFromRecents(Context context, Task.TaskKey taskKey, String taskName,
+            ActivityOptions options, int stackId,
+            @Nullable final StartActivityFromRecentsResultListener resultListener) {
+        if (mIam == null) {
+            return;
         }
-        return false;
+        if (taskKey.stackId == DOCKED_STACK_ID) {
+            // We show non-visible docked tasks in Recents, but we always want to launch
+            // them in the fullscreen stack.
+            if (options == null) {
+                options = ActivityOptions.makeBasic();
+            }
+            options.setLaunchStackId(FULLSCREEN_WORKSPACE_STACK_ID);
+        } else if (stackId != INVALID_STACK_ID) {
+            if (options == null) {
+                options = ActivityOptions.makeBasic();
+            }
+            options.setLaunchStackId(stackId);
+        }
+        final ActivityOptions finalOptions = options;
+
+        // Execute this from another thread such that we can do other things (like caching the
+        // bitmap for the thumbnail) while AM is busy starting our activity.
+        mUiOffloadThread.submit(() -> {
+            try {
+                mIam.startActivityFromRecents(
+                        taskKey.id, finalOptions == null ? null : finalOptions.toBundle());
+                if (resultListener != null) {
+                    mHandler.post(() -> resultListener.onStartActivityResult(true));
+                }
+            } catch (Exception e) {
+                Log.e(TAG, context.getString(
+                        R.string.recents_launch_error_message, taskName), e);
+                if (resultListener != null) {
+                    mHandler.post(() -> resultListener.onStartActivityResult(false));
+                }
+            }
+        });
     }
 
     /** Starts an in-place animation on the front most application windows. */
@@ -1258,6 +1302,37 @@
         }
     }
 
+    public boolean isDreaming() {
+        try {
+            return mDreamManager.isDreaming();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to query dream manager.", e);
+        }
+        return false;
+    }
+
+    public void awakenDreamsAsync() {
+        mUiOffloadThread.submit(() -> {
+            try {
+                mDreamManager.awaken();
+            } catch (RemoteException e) {
+                e.printStackTrace();
+            }
+        });
+    }
+
+    public void updateOverviewLastStackActiveTimeAsync(long newLastStackActiveTime,
+            int currentUserId) {
+        mUiOffloadThread.submit(() -> {
+            Settings.Secure.putLongForUser(mContext.getContentResolver(),
+                    Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, newLastStackActiveTime, currentUserId);
+        });
+    }
+
+    public interface StartActivityFromRecentsResultListener {
+        void onStartActivityResult(boolean succeeded);
+    }
+
     private final class H extends Handler {
         private static final int ON_TASK_STACK_CHANGED = 1;
         private static final int ON_TASK_SNAPSHOT_CHANGED = 2;
@@ -1294,7 +1369,7 @@
                     }
                     case ON_ACTIVITY_PINNED: {
                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                            mTaskStackListeners.get(i).onActivityPinned((String) msg.obj);
+                            mTaskStackListeners.get(i).onActivityPinned((String) msg.obj, msg.arg1);
                         }
                         break;
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 7ee0906..ed09640 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -87,7 +87,7 @@
         mCurrentQuietProfiles.clear();
 
         if (currentUserId == UserHandle.USER_CURRENT) {
-            currentUserId = KeyguardUpdateMonitor.getCurrentUser();
+            currentUserId = SystemServicesProxy.getInstance(mContext).getCurrentUser();
         }
         UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         List<UserInfo> profiles = userManager.getProfiles(currentUserId);
@@ -218,8 +218,8 @@
             affiliatedTasks.put(taskKey.id, taskKey);
         }
         if (newLastStackActiveTime != -1) {
-            Settings.Secure.putLongForUser(mContext.getContentResolver(),
-                    Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, newLastStackActiveTime, currentUserId);
+            Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync(
+                    newLastStackActiveTime, currentUserId);
         }
 
         // Initialize the stacks
@@ -316,9 +316,8 @@
             for (int i = 0; i < users.size(); i++) {
                 int userId = users.get(i).id;
                 if (userId != currentUserId) {
-                    Settings.Secure.putLongForUser(mContext.getContentResolver(),
-                            Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, legacyLastStackActiveTime,
-                            userId);
+                    Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync(
+                            legacyLastStackActiveTime, userId);
                 }
             }
             return legacyLastStackActiveTime;
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 97a9659..15e1739 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -28,6 +28,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.Trace;
 import android.util.Log;
 import android.util.LruCache;
 
@@ -102,6 +103,7 @@
     Bitmap mDefaultThumbnail;
     BitmapDrawable mDefaultIcon;
 
+    boolean mStarted;
     boolean mCancelled;
     boolean mWaitingOnLoadQueue;
 
@@ -121,16 +123,21 @@
                 android.os.Process.THREAD_PRIORITY_BACKGROUND);
         mLoadThread.start();
         mLoadThreadHandler = new Handler(mLoadThread.getLooper());
-        mLoadThreadHandler.post(this);
     }
 
     /** Restarts the loader thread */
     void start(Context context) {
         mContext = context;
         mCancelled = false;
-        // Notify the load thread to start loading
-        synchronized(mLoadThread) {
-            mLoadThread.notifyAll();
+        if (!mStarted) {
+            // Start loading on the load thread
+            mStarted = true;
+            mLoadThreadHandler.post(this);
+        } else {
+            // Notify the load thread to start loading again
+            synchronized (mLoadThread) {
+                mLoadThread.notifyAll();
+            }
         }
     }
 
@@ -351,7 +358,12 @@
     /** Preloads recents tasks using the specified plan to store the output. */
     public synchronized void preloadTasks(RecentsTaskLoadPlan plan, int runningTaskId,
             boolean includeFrontMostExcludedTask) {
-        plan.preloadPlan(this, runningTaskId, includeFrontMostExcludedTask);
+        try {
+            Trace.beginSection("preloadPlan");
+            plan.preloadPlan(this, runningTaskId, includeFrontMostExcludedTask);
+        } finally {
+            Trace.endSection();
+        }
     }
 
     /** Begins loading the heavy task data according to the specified options. */
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 9b25ef8..6e3be09 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -229,7 +229,8 @@
          * Notifies when a task has been removed from the stack.
          */
         void onStackTaskRemoved(TaskStack stack, Task removedTask, Task newFrontMostTask,
-                AnimationProps animation, boolean fromDockGesture);
+                AnimationProps animation, boolean fromDockGesture,
+                boolean dismissRecentsIfAllRemoved);
 
         /**
          * Notifies when all tasks have been removed from the stack.
@@ -631,13 +632,22 @@
      * how they should update themselves.
      */
     public void removeTask(Task t, AnimationProps animation, boolean fromDockGesture) {
+        removeTask(t, animation, fromDockGesture, true /* dismissRecentsIfAllRemoved */);
+    }
+
+    /**
+     * 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, boolean fromDockGesture,
+            boolean dismissRecentsIfAllRemoved) {
         if (mStackTaskList.contains(t)) {
             removeTaskImpl(mStackTaskList, t);
             Task newFrontMostTask = getStackFrontMostTask(false  /* includeFreeform */);
             if (mCb != null) {
                 // Notify that a task has been removed
                 mCb.onStackTaskRemoved(this, t, newFrontMostTask, animation,
-                        fromDockGesture);
+                        fromDockGesture, dismissRecentsIfAllRemoved);
             }
         }
         mRawTaskList.remove(t);
@@ -646,19 +656,27 @@
     /**
      * Removes all tasks from the stack.
      */
-    public void removeAllTasks() {
+    public void removeAllTasks(boolean notifyStackChanges) {
         ArrayList<Task> tasks = mStackTaskList.getTasks();
         for (int i = tasks.size() - 1; i >= 0; i--) {
             Task t = tasks.get(i);
             removeTaskImpl(mStackTaskList, t);
             mRawTaskList.remove(t);
         }
-        if (mCb != null) {
+        if (mCb != null && notifyStackChanges) {
             // Notify that all tasks have been removed
             mCb.onStackTasksRemoved(this);
         }
     }
 
+
+    /**
+     * @see #setTasks(Context, List, boolean, boolean)
+     */
+    public void setTasks(Context context, TaskStack stack, boolean notifyStackChanges) {
+        setTasks(context, stack.mRawTaskList, notifyStackChanges);
+    }
+
     /**
      * Sets a few tasks in one go, without calling any callbacks.
      *
@@ -723,7 +741,8 @@
         Task newFrontMostTask = getStackFrontMostTask(false);
         for (int i = 0; i < removedTaskCount; i++) {
             mCb.onStackTaskRemoved(this, removedTasks.get(i), newFrontMostTask,
-                    AnimationProps.IMMEDIATE, false /* fromDockGesture */);
+                    AnimationProps.IMMEDIATE, false /* fromDockGesture */,
+                    true /* dismissRecentsIfAllRemoved */);
         }
 
         // Only callback for the newly added tasks after this stack has been updated
@@ -854,21 +873,46 @@
     }
 
     /**
+     * Returns whether the next launch target should actually be the PiP task.
+     */
+    public boolean isNextLaunchTargetPip(long lastPipTime) {
+        Task launchTarget = getLaunchTarget();
+        Task nextLaunchTarget = getNextLaunchTargetRaw();
+        if (nextLaunchTarget != null && lastPipTime > 0) {
+            // If the PiP time is more recent than the next launch target, then launch the PiP task
+            return lastPipTime > nextLaunchTarget.key.lastActiveTime;
+        } else if (launchTarget != null && lastPipTime > 0 && getTaskCount() == 1) {
+            // Otherwise, if there is no next launch target, but there is a PiP, then launch
+            // the PiP task
+            return true;
+        }
+        return false;
+    }
+
+    /**
      * Returns the task in stack tasks which should be launched next if Recents are toggled
-     * again, or null if there is no task to be launched.
+     * again, or null if there is no task to be launched. Callers should check
+     * {@link #isNextLaunchTargetPip(long)} before fetching the next raw launch target from the
+     * stack.
      */
     public Task getNextLaunchTarget() {
+        Task nextLaunchTarget = getNextLaunchTargetRaw();
+        if (nextLaunchTarget != null) {
+            return nextLaunchTarget;
+        }
+        return getStackTasks().get(getTaskCount() - 1);
+    }
+
+    private Task getNextLaunchTargetRaw() {
         int taskCount = getTaskCount();
         if (taskCount == 0) {
             return null;
         }
         int launchTaskIndex = indexOfStackTask(getLaunchTarget());
-        if (launchTaskIndex != -1) {
-            launchTaskIndex = Math.max(0, launchTaskIndex - 1);
-        } else {
-            launchTaskIndex = getTaskCount() - 1;
+        if (launchTaskIndex != -1 && launchTaskIndex > 0) {
+            return getStackTasks().get(launchTaskIndex - 1);
         }
-        return getStackTasks().get(launchTaskIndex);
+        return null;
     }
 
     /** Returns the index of this task in this current task stack */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 8882cab..d7d264e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -101,57 +101,49 @@
      */
     public void launchTaskFromRecents(final TaskStack stack, @Nullable final Task task,
             final TaskStackView stackView, final TaskView taskView,
-            final boolean screenPinningRequested, final Rect bounds, final int destinationStack) {
-        final ActivityOptions opts = ActivityOptions.makeBasic();
-        if (bounds != null) {
-            opts.setLaunchBounds(bounds.isEmpty() ? null : bounds);
-        }
+            final boolean screenPinningRequested, final int destinationStack) {
 
         final ActivityOptions.OnAnimationStartedListener animStartedListener;
-        final IAppTransitionAnimationSpecsFuture transitionFuture;
+        final AppTransitionAnimationSpecsFuture transitionFuture;
         if (taskView != null) {
-            transitionFuture = getAppTransitionFuture(new AnimationSpecComposer() {
-                @Override
-                public List<AppTransitionAnimationSpec> composeSpecs() {
-                    return composeAnimationSpecs(task, stackView, destinationStack);
-                }
-            });
-            animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
-                @Override
-                public void onAnimationStarted() {
-                    // If we are launching into another task, cancel the previous task's
-                    // window transition
-                    EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
-                    EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
-                    stackView.cancelAllTaskViewAnimations();
 
-                    if (screenPinningRequested) {
-                        // Request screen pinning after the animation runs
-                        mStartScreenPinningRunnable.taskId = task.key.id;
-                        mHandler.postDelayed(mStartScreenPinningRunnable, 350);
-                    }
+            // Fetch window rect here already in order not to be blocked on lock contention in WM
+            // when the future calls it.
+            final Rect windowRect = Recents.getSystemServices().getWindowRect();
+            transitionFuture = getAppTransitionFuture(
+                    () -> composeAnimationSpecs(task, stackView, destinationStack, windowRect));
+            animStartedListener = () -> {
+                // If we are launching into another task, cancel the previous task's
+                // window transition
+                EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
+                EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
+                stackView.cancelAllTaskViewAnimations();
+
+                if (screenPinningRequested) {
+                    // Request screen pinning after the animation runs
+                    mStartScreenPinningRunnable.taskId = task.key.id;
+                    mHandler.postDelayed(mStartScreenPinningRunnable, 350);
                 }
             };
         } else {
             // This is only the case if the task is not on screen (scrolled offscreen for example)
             transitionFuture = null;
-            animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
-                @Override
-                public void onAnimationStarted() {
-                    // If we are launching into another task, cancel the previous task's
-                    // window transition
-                    EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
-                    EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
-                    stackView.cancelAllTaskViewAnimations();
-                }
+            animStartedListener = () -> {
+                // If we are launching into another task, cancel the previous task's
+                // window transition
+                EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
+                EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
+                stackView.cancelAllTaskViewAnimations();
             };
         }
 
+        final ActivityOptions opts = ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(mContext,
+                mHandler, transitionFuture != null ? transitionFuture.future : null,
+                animStartedListener, true /* scaleUp */);
         if (taskView == null) {
             // If there is no task view, then we do not need to worry about animating out occluding
             // task views, and we can launch immediately
-            startTaskActivity(stack, task, taskView, opts, transitionFuture, animStartedListener,
-                    destinationStack);
+            startTaskActivity(stack, task, taskView, opts, transitionFuture, destinationStack);
         } else {
             LaunchTaskStartedEvent launchStartedEvent = new LaunchTaskStartedEvent(taskView,
                     screenPinningRequested);
@@ -160,14 +152,13 @@
                     @Override
                     public void run() {
                         startTaskActivity(stack, task, taskView, opts, transitionFuture,
-                                animStartedListener, destinationStack);
+                                destinationStack);
                     }
                 });
                 EventBus.getDefault().send(launchStartedEvent);
             } else {
                 EventBus.getDefault().send(launchStartedEvent);
-                startTaskActivity(stack, task, taskView, opts, transitionFuture,
-                        animStartedListener, destinationStack);
+                startTaskActivity(stack, task, taskView, opts, transitionFuture, destinationStack);
             }
         }
         Recents.getSystemServices().sendCloseSystemWindows(
@@ -199,30 +190,31 @@
      * @param destinationStack id of the stack to put the task into.
      */
     private void startTaskActivity(TaskStack stack, Task task, @Nullable TaskView taskView,
-            ActivityOptions opts, IAppTransitionAnimationSpecsFuture transitionFuture,
-            final OnAnimationStartedListener animStartedListener, int destinationStack) {
+            ActivityOptions opts, AppTransitionAnimationSpecsFuture transitionFuture,
+            int destinationStack) {
         SystemServicesProxy ssp = Recents.getSystemServices();
-        if (ssp.startActivityFromRecents(mContext, task.key, task.title, opts, destinationStack)) {
-            // Keep track of the index of the task launch
-            int taskIndexFromFront = 0;
-            int taskIndex = stack.indexOfStackTask(task);
-            if (taskIndex > -1) {
-                taskIndexFromFront = stack.getTaskCount() - taskIndex - 1;
-            }
-            EventBus.getDefault().send(new LaunchTaskSucceededEvent(taskIndexFromFront));
-        } else {
-            // Dismiss the task if we fail to launch it
-            if (taskView != null) {
-                taskView.dismissTask();
-            }
+        ssp.startActivityFromRecents(mContext, task.key, task.title, opts, destinationStack,
+                succeeded -> {
+            if (succeeded) {
+                // Keep track of the index of the task launch
+                int taskIndexFromFront = 0;
+                int taskIndex = stack.indexOfStackTask(task);
+                if (taskIndex > -1) {
+                    taskIndexFromFront = stack.getTaskCount() - taskIndex - 1;
+                }
+                EventBus.getDefault().send(new LaunchTaskSucceededEvent(taskIndexFromFront));
+            } else {
+                // Dismiss the task if we fail to launch it
+                if (taskView != null) {
+                    taskView.dismissTask();
+                }
 
-            // Keep track of failed launches
-            EventBus.getDefault().send(new LaunchTaskFailedEvent());
-        }
-
+                // Keep track of failed launches
+                EventBus.getDefault().send(new LaunchTaskFailedEvent());
+            }
+        });
         if (transitionFuture != null) {
-            ssp.overridePendingAppTransitionMultiThumbFuture(transitionFuture,
-                    wrapStartedListener(animStartedListener), true /* scaleUp */);
+            mHandler.post(transitionFuture::precacheSpecs);
         }
     }
 
@@ -231,21 +223,18 @@
      *
      * @param composer The implementation that composes the specs on the UI thread.
      */
-    public IAppTransitionAnimationSpecsFuture getAppTransitionFuture(
+    public AppTransitionAnimationSpecsFuture getAppTransitionFuture(
             final AnimationSpecComposer composer) {
         synchronized (this) {
             mAppTransitionAnimationSpecs = SPECS_WAITING;
         }
-        return new IAppTransitionAnimationSpecsFuture.Stub() {
+        IAppTransitionAnimationSpecsFuture future = new IAppTransitionAnimationSpecsFuture.Stub() {
             @Override
             public AppTransitionAnimationSpec[] get() throws RemoteException {
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        synchronized (RecentsTransitionHelper.this) {
-                            mAppTransitionAnimationSpecs = composer.composeSpecs();
-                            RecentsTransitionHelper.this.notifyAll();
-                        }
+                mHandler.post(() -> {
+                    synchronized (RecentsTransitionHelper.this) {
+                        mAppTransitionAnimationSpecs = composer.composeSpecs();
+                        RecentsTransitionHelper.this.notifyAll();
                     }
                 });
                 synchronized (RecentsTransitionHelper.this) {
@@ -265,6 +254,7 @@
                 }
             }
         };
+        return new AppTransitionAnimationSpecsFuture(composer, future);
     }
 
     /**
@@ -283,7 +273,7 @@
      * Composes the animation specs for all the tasks in the target stack.
      */
     private List<AppTransitionAnimationSpec> composeAnimationSpecs(final Task task,
-            final TaskStackView stackView, final int destinationStack) {
+            final TaskStackView stackView, final int destinationStack, Rect windowRect) {
         // Ensure we have a valid target stack id
         final int targetStackId = destinationStack != INVALID_STACK_ID ?
                 destinationStack : task.key.stackId;
@@ -309,8 +299,7 @@
                 specs.add(composeOffscreenAnimationSpec(task, offscreenTaskRect));
             } else {
                 mTmpTransform.fillIn(taskView);
-                stackLayout.transformToScreenCoordinates(mTmpTransform,
-                        null /* windowOverrideRect */);
+                stackLayout.transformToScreenCoordinates(mTmpTransform, windowRect);
                 AppTransitionAnimationSpec spec = composeAnimationSpec(stackView, taskView,
                         mTmpTransform, true /* addHeaderBitmap */);
                 if (spec != null) {
@@ -430,4 +419,34 @@
     public interface AnimationSpecComposer {
         List<AppTransitionAnimationSpec> composeSpecs();
     }
+
+    /**
+     * Class to be returned from {@link #composeAnimationSpec} that gives access to both the future
+     * and the anonymous class used for composing.
+     */
+    public class AppTransitionAnimationSpecsFuture {
+
+        private final AnimationSpecComposer composer;
+        private final IAppTransitionAnimationSpecsFuture future;
+
+        private AppTransitionAnimationSpecsFuture(AnimationSpecComposer composer,
+                IAppTransitionAnimationSpecsFuture future) {
+            this.composer = composer;
+            this.future = future;
+        }
+
+        public IAppTransitionAnimationSpecsFuture getFuture() {
+            return future;
+        }
+
+        /**
+         * Manually generates and caches the spec such that they are already available when the
+         * future needs.
+         */
+        public void precacheSpecs() {
+            synchronized (RecentsTransitionHelper.this) {
+                mAppTransitionAnimationSpecs = composer.composeSpecs();
+            }
+        }
+    }
 }
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 8f9c457..a0ad782 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -24,19 +24,16 @@
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.Outline;
 import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.util.ArraySet;
 import android.util.AttributeSet;
 import android.view.AppTransitionAnimationSpec;
-import android.view.IAppTransitionAnimationSpecsFuture;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewDebug;
-import android.view.ViewOutlineProvider;
 import android.view.ViewPropertyAnimator;
 import android.view.WindowInsets;
 import android.widget.FrameLayout;
@@ -58,7 +55,9 @@
 import com.android.systemui.recents.events.activity.HideStackActionButtonEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskEvent;
 import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
+import com.android.systemui.recents.events.activity.ShowEmptyViewEvent;
 import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent;
+import com.android.systemui.recents.events.component.ExpandPipEvent;
 import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
 import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
 import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
@@ -73,10 +72,10 @@
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.RecentsTransitionHelper.AnimationSpecComposer;
+import com.android.systemui.recents.views.RecentsTransitionHelper.AppTransitionAnimationSpecsFuture;
 import com.android.systemui.stackdivider.WindowManagerProxy;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 
-import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
@@ -253,6 +252,12 @@
 
     /** Launches the task that recents was launched from if possible */
     public boolean launchPreviousTask() {
+        if (Recents.getConfiguration().getLaunchState().launchedFromPipApp) {
+            // If the app auto-entered PiP on the way to Recents, then just re-expand it
+            EventBus.getDefault().send(new ExpandPipEvent());
+            return true;
+        }
+
         if (mTaskStackView != null) {
             Task task = getStack().getLaunchTarget();
             if (task != null) {
@@ -440,8 +445,7 @@
     public final void onBusEvent(LaunchTaskEvent event) {
         mLastTaskLaunchedWasFreeform = event.task.isFreeformTask();
         mTransitionHelper.launchTaskFromRecents(getStack(), event.task, mTaskStackView,
-                event.taskView, event.screenPinningRequested, event.targetTaskBounds,
-                event.targetTaskStack);
+                event.taskView, event.screenPinningRequested, event.targetTaskStack);
     }
 
     public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
@@ -523,7 +527,7 @@
                 };
 
                 final Rect taskRect = getTaskRect(event.taskView);
-                IAppTransitionAnimationSpecsFuture future =
+                AppTransitionAnimationSpecsFuture future =
                         mTransitionHelper.getAppTransitionFuture(
                                 new AnimationSpecComposer() {
                                     @Override
@@ -532,7 +536,7 @@
                                                 event.taskView, taskRect);
                                     }
                                 });
-                ssp.overridePendingAppTransitionMultiThumbFuture(future,
+                ssp.overridePendingAppTransitionMultiThumbFuture(future.getFuture(),
                         mTransitionHelper.wrapStartedListener(startedListener),
                         true /* scaleUp */);
 
@@ -639,6 +643,10 @@
         updateStack(event.stack, false /* setStackViewTasks */);
     }
 
+    public final void onBusEvent(ShowEmptyViewEvent event) {
+        showEmptyView(R.string.recents_empty_message);
+    }
+
     /**
      * Shows the stack action button.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 7ba705e..8135034 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -562,7 +562,8 @@
             mMinScrollP = 0;
             mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
                     Math.max(0, mFocusedRange.getAbsoluteX(maxBottomNormX)));
-            if (launchState.launchedFromHome) {
+            if (launchState.launchedFromHome || launchState.launchedFromPipApp
+                    || launchState.launchedWithNextPipApp) {
                 mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
             } else {
                 mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
@@ -581,8 +582,8 @@
             mMinScrollP = 0;
             mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
                     Math.max(0, mUnfocusedRange.getAbsoluteX(maxBottomNormX)));
-            boolean scrollToFront = launchState.launchedFromHome ||
-                    launchState.launchedViaDockGesture;
+            boolean scrollToFront = launchState.launchedFromHome || launchState.launchedFromPipApp
+                    || launchState.launchedWithNextPipApp || launchState.launchedViaDockGesture;
             if (launchState.launchedFromBlacklistedApp) {
                 mInitialScrollP = mMaxScrollP;
             } else if (launchState.launchedWithAltTab) {
@@ -608,6 +609,8 @@
         mTaskIndexOverrideMap.clear();
 
         boolean scrollToFront = launchState.launchedFromHome ||
+                launchState.launchedFromPipApp ||
+                launchState.launchedWithNextPipApp ||
                 launchState.launchedFromBlacklistedApp ||
                 launchState.launchedViaDockGesture;
         if (getInitialFocusState() == STATE_UNFOCUSED && mNumStackTasks > 1) {
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 18a9bab..5f9a8f5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -57,6 +57,7 @@
 import com.android.systemui.recents.RecentsActivityLaunchState;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.RecentsDebugFlags;
+import com.android.systemui.recents.RecentsImpl;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
 import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
@@ -72,7 +73,11 @@
 import com.android.systemui.recents.events.activity.LaunchTaskStartedEvent;
 import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
 import com.android.systemui.recents.events.activity.PackagesChangedEvent;
+import com.android.systemui.recents.events.activity.ShowEmptyViewEvent;
 import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent;
+import com.android.systemui.recents.events.component.ActivityPinnedEvent;
+import com.android.systemui.recents.events.component.ExpandPipEvent;
+import com.android.systemui.recents.events.component.HidePipMenuEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
 import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
@@ -379,8 +384,7 @@
 
         // Only notify if we are already initialized, otherwise, everything will pick up all the
         // new and old tasks when we next layout
-        mStack.setTasks(getContext(), stack.computeAllTasksList(),
-                allowNotifyStackChanges && isInitialized);
+        mStack.setTasks(getContext(), stack, allowNotifyStackChanges && isInitialized);
     }
 
     /** Returns the task stack. */
@@ -1496,7 +1500,7 @@
      */
     @Override
     public void onStackTaskRemoved(TaskStack stack, Task removedTask, Task newFrontMostTask,
-            AnimationProps animation, boolean fromDockGesture) {
+            AnimationProps animation, boolean fromDockGesture, boolean dismissRecentsIfAllRemoved) {
         if (mFocusedTask == removedTask) {
             resetFocusedTask(removedTask);
         }
@@ -1527,9 +1531,13 @@
 
         // If there are no remaining tasks, then just close recents
         if (mStack.getTaskCount() == 0) {
-            EventBus.getDefault().send(new AllTaskViewsDismissedEvent(fromDockGesture
-                    ? R.string.recents_empty_message
-                    : R.string.recents_empty_message_dismissed_all));
+            if (dismissRecentsIfAllRemoved) {
+                EventBus.getDefault().send(new AllTaskViewsDismissedEvent(fromDockGesture
+                        ? R.string.recents_empty_message
+                        : R.string.recents_empty_message_dismissed_all));
+            } else {
+                EventBus.getDefault().send(new ShowEmptyViewEvent());
+            }
         }
     }
 
@@ -1802,14 +1810,36 @@
             return;
         }
 
-        final Task launchTask = mStack.getNextLaunchTarget();
-        if (launchTask != null) {
-            launchTask(launchTask);
-            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));
+        if (mStack.getTaskCount() == 0) {
+            if (RecentsImpl.getLastPipTime() != -1) {
+                EventBus.getDefault().send(new ExpandPipEvent());
+                MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
+                        "pip");
+            } else {
+                // If there are no tasks, then just hide recents back to home.
+                EventBus.getDefault().send(new HideRecentsEvent(false, true));
+            }
+            return;
+        }
+
+        if (!Recents.getConfiguration().getLaunchState().launchedFromPipApp
+                && mStack.isNextLaunchTargetPip(RecentsImpl.getLastPipTime())) {
+            // If the launch task is in the pinned stack, then expand the PiP now
+            EventBus.getDefault().send(new ExpandPipEvent());
+            MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK, "pip");
+        } else {
+            final Task launchTask = mStack.getNextLaunchTarget();
+            if (launchTask != null) {
+                // Defer launching the task until the PiP menu has been dismissed (if it is
+                // showing at all)
+                HidePipMenuEvent hideMenuEvent = new HidePipMenuEvent();
+                hideMenuEvent.addPostAnimationCallback(() -> {
+                    launchTask(launchTask);
+                });
+                EventBus.getDefault().send(hideMenuEvent);
+                MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
+                        launchTask.key.getComponent().toString());
+            }
         }
     }
 
@@ -1871,7 +1901,7 @@
                         R.string.accessibility_recents_all_items_dismissed));
 
                 // Remove all tasks and delete the task data for all tasks
-                mStack.removeAllTasks();
+                mStack.removeAllTasks(true /* notifyStackChanges */);
                 for (int i = tasks.size() - 1; i >= 0; i--) {
                     EventBus.getDefault().send(new DeleteTaskDataEvent(tasks.get(i)));
                 }
@@ -2217,11 +2247,23 @@
         }
     }
 
+    public final void onBusEvent(ActivityPinnedEvent event) {
+        // If an activity enters PiP while Recents is open, remove the stack task associated with
+        // the new PiP task
+        Task removeTask = mStack.findTaskWithId(event.taskId);
+        if (removeTask != null) {
+            // In this case, we remove the task, but if the last task is removed, don't dismiss
+            // Recents to home
+            mStack.removeTask(removeTask, AnimationProps.IMMEDIATE, false /* fromDockGesture */,
+                    false /* dismissRecentsIfAllRemoved */);
+        }
+        updateLayoutAlgorithm(false /* boundScroll */);
+        updateToInitialState();
+    }
+
     public void reloadOnConfigurationChange() {
         mStableLayoutAlgorithm.reloadOnConfigurationChange(getContext());
         mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
-
-        boolean hasDockedTask = Recents.getSystemServices().hasDockedTask();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 24a2927..0c77036 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -1169,7 +1169,7 @@
     }
 
     public final void onBusEvent(RecentsActivityStartingEvent recentsActivityStartingEvent) {
-        if (mGrowRecents && getWindowManagerProxy().getDockSide() == WindowManager.DOCKED_TOP
+        if (mGrowRecents && mDockSide == WindowManager.DOCKED_TOP
                 && getSnapAlgorithm().getMiddleTarget() != getSnapAlgorithm().getLastSplitTarget()
                 && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position) {
             mState.growAfterRecentsDrawn = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index be221bb..bf89b01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -279,7 +279,9 @@
     public void toggleRecentApps() {
         synchronized (mLock) {
             mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS);
-            mHandler.obtainMessage(MSG_TOGGLE_RECENT_APPS, 0, 0, null).sendToTarget();
+            Message msg = mHandler.obtainMessage(MSG_TOGGLE_RECENT_APPS, 0, 0, null);
+            msg.setAsynchronous(true);
+            msg.sendToTarget();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 0924089..1691e135 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -270,7 +270,7 @@
                 return;
             }
 
-            if (!mUserManager.isUserUnlocked(ActivityManager.getCurrentUser())) {
+            if (!mUserManager.isUserUnlocked(KeyguardUpdateMonitor.getCurrentUser())) {
                 mTextView.switchIndication(com.android.internal.R.string.lockscreen_storage_locked);
                 mTextView.setTextColor(Color.WHITE);
 
@@ -365,6 +365,9 @@
     };
 
     public void setDozing(boolean dozing) {
+        if (mDozing == dozing) {
+            return;
+        }
         mDozing = dozing;
         updateIndication();
         updateDisclosure();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
index 9a3de61..80854ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
@@ -24,7 +24,6 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.support.annotation.VisibleForTesting;
-import android.support.v4.graphics.ColorUtils;
 import android.support.v7.graphics.Palette;
 import android.util.LayoutDirection;
 
@@ -41,10 +40,31 @@
     /**
      * The fraction below which we select the vibrant instead of the light/dark vibrant color
      */
-    private static final float POPULATION_FRACTION_FOR_MORE_VIBRANT = 0.75f;
+    private static final float POPULATION_FRACTION_FOR_MORE_VIBRANT = 1.0f;
+
+    /**
+     * Minimum saturation that a muted color must have if there exists if deciding between two
+     * colors
+     */
+    private static final float MIN_SATURATION_WHEN_DECIDING = 0.19f;
+
+    /**
+     * Minimum fraction that any color must have to be picked up as a text color
+     */
+    private static final double MINIMUM_IMAGE_FRACTION = 0.002;
+
+    /**
+     * The population fraction to select the dominant color as the text color over a the colored
+     * ones.
+     */
+    private static final float POPULATION_FRACTION_FOR_DOMINANT = 0.01f;
+
+    /**
+     * The population fraction to select a white or black color as the background over a color.
+     */
     private static final float POPULATION_FRACTION_FOR_WHITE_OR_BLACK = 2.5f;
     private static final float BLACK_MAX_LIGHTNESS = 0.08f;
-    private static final float WHITE_MIN_LIGHTNESS = 0.92f;
+    private static final float WHITE_MIN_LIGHTNESS = 0.90f;
     private static final int RESIZE_BITMAP_AREA = 150 * 150;
     private final ImageGradientColorizer mColorizer;
     private final Context mContext;
@@ -109,8 +129,11 @@
                         .resizeBitmapArea(RESIZE_BITMAP_AREA);
                 Palette palette = paletteBuilder.generate();
                 backgroundColor = findBackgroundColorAndFilter(palette);
-                // we want the full region again
-                paletteBuilder.setRegion(0, 0, bitmap.getWidth(), bitmap.getHeight());
+                // we want most of the full region again, slightly shifted to the right
+                float textColorStartWidthFraction = 0.4f;
+                paletteBuilder.setRegion((int) (bitmap.getWidth() * textColorStartWidthFraction), 0,
+                        bitmap.getWidth(),
+                        bitmap.getHeight());
                 if (mFilteredBackgroundHsl != null) {
                     paletteBuilder.addFilter((rgb, hsl) -> {
                         // at least 10 degrees hue difference
@@ -120,78 +143,7 @@
                 }
                 paletteBuilder.addFilter(mBlackWhiteFilter);
                 palette = paletteBuilder.generate();
-                int foregroundColor;
-                if (NotificationColorUtil.isColorLight(backgroundColor)) {
-                    Palette.Swatch first = palette.getDarkVibrantSwatch();
-                    Palette.Swatch second = palette.getVibrantSwatch();
-                    if (first != null && second != null) {
-                        int firstPopulation = first.getPopulation();
-                        int secondPopulation = second.getPopulation();
-                        if (firstPopulation / secondPopulation
-                                < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
-                            foregroundColor = second.getRgb();
-                        } else {
-                            foregroundColor = first.getRgb();
-                        }
-                    } else if (first != null) {
-                        foregroundColor = first.getRgb();
-                    } else if (second != null) {
-                        foregroundColor = second.getRgb();
-                    } else {
-                        first = palette.getMutedSwatch();
-                        second = palette.getDarkMutedSwatch();
-                        if (first != null && second != null) {
-                            float firstSaturation = first.getHsl()[1];
-                            float secondSaturation = second.getHsl()[1];
-                            if (firstSaturation > secondSaturation) {
-                                foregroundColor = first.getRgb();
-                            } else {
-                                foregroundColor = second.getRgb();
-                            }
-                        } else if (first != null) {
-                            foregroundColor = first.getRgb();
-                        } else if (second != null) {
-                            foregroundColor = second.getRgb();
-                        } else {
-                            foregroundColor = Color.BLACK;
-                        }
-                    }
-                } else {
-                    Palette.Swatch first = palette.getLightVibrantSwatch();
-                    Palette.Swatch second = palette.getVibrantSwatch();
-                    if (first != null && second != null) {
-                        int firstPopulation = first.getPopulation();
-                        int secondPopulation = second.getPopulation();
-                        if (firstPopulation / secondPopulation
-                                < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
-                            foregroundColor = second.getRgb();
-                        } else {
-                            foregroundColor = first.getRgb();
-                        }
-                    } else if (first != null) {
-                        foregroundColor = first.getRgb();
-                    } else if (second != null) {
-                        foregroundColor = second.getRgb();
-                    } else {
-                        first = palette.getMutedSwatch();
-                        second = palette.getLightMutedSwatch();
-                        if (first != null && second != null) {
-                            float firstSaturation = first.getHsl()[1];
-                            float secondSaturation = second.getHsl()[1];
-                            if (firstSaturation > secondSaturation) {
-                                foregroundColor = first.getRgb();
-                            } else {
-                                foregroundColor = second.getRgb();
-                            }
-                        } else if (first != null) {
-                            foregroundColor = first.getRgb();
-                        } else if (second != null) {
-                            foregroundColor = second.getRgb();
-                        } else {
-                            foregroundColor = Color.WHITE;
-                        }
-                    }
-                }
+                int foregroundColor = selectForegroundColor(backgroundColor, palette);
                 builder.setColorPalette(backgroundColor, foregroundColor);
             } else {
                 int id = mIsLowPriority
@@ -206,6 +158,95 @@
         }
     }
 
+    private int selectForegroundColor(int backgroundColor, Palette palette) {
+        if (NotificationColorUtil.isColorLight(backgroundColor)) {
+            return selectForegroundColorForSwatches(palette.getDarkVibrantSwatch(),
+                    palette.getVibrantSwatch(),
+                    palette.getDarkMutedSwatch(),
+                    palette.getMutedSwatch(),
+                    palette.getDominantSwatch(),
+                    Color.BLACK);
+        } else {
+            return selectForegroundColorForSwatches(palette.getLightVibrantSwatch(),
+                    palette.getVibrantSwatch(),
+                    palette.getLightMutedSwatch(),
+                    palette.getMutedSwatch(),
+                    palette.getDominantSwatch(),
+                    Color.WHITE);
+        }
+    }
+
+    private int selectForegroundColorForSwatches(Palette.Swatch moreVibrant,
+            Palette.Swatch vibrant, Palette.Swatch moreMutedSwatch, Palette.Swatch mutedSwatch,
+            Palette.Swatch dominantSwatch, int fallbackColor) {
+        Palette.Swatch coloredCandidate = selectVibrantCandidate(moreVibrant, vibrant);
+        if (coloredCandidate == null) {
+            coloredCandidate = selectMutedCandidate(mutedSwatch, moreMutedSwatch);
+        }
+        if (coloredCandidate != null) {
+            if (dominantSwatch == coloredCandidate) {
+                return coloredCandidate.getRgb();
+            } else if ((float) coloredCandidate.getPopulation() / dominantSwatch.getPopulation()
+                    < POPULATION_FRACTION_FOR_DOMINANT
+                    && dominantSwatch.getHsl()[1] > MIN_SATURATION_WHEN_DECIDING) {
+                return dominantSwatch.getRgb();
+            } else {
+                return coloredCandidate.getRgb();
+            }
+        } else if (hasEnoughPopulation(dominantSwatch)) {
+            return dominantSwatch.getRgb();
+        } else {
+            return fallbackColor;
+        }
+    }
+
+    private Palette.Swatch selectMutedCandidate(Palette.Swatch first,
+            Palette.Swatch second) {
+        boolean firstValid = hasEnoughPopulation(first);
+        boolean secondValid = hasEnoughPopulation(second);
+        if (firstValid && secondValid) {
+            float firstSaturation = first.getHsl()[1];
+            float secondSaturation = second.getHsl()[1];
+            float populationFraction = first.getPopulation() / (float) second.getPopulation();
+            if (firstSaturation * populationFraction > secondSaturation) {
+                return first;
+            } else {
+                return second;
+            }
+        } else if (firstValid) {
+            return first;
+        } else if (secondValid) {
+            return second;
+        }
+        return null;
+    }
+
+    private Palette.Swatch selectVibrantCandidate(Palette.Swatch first, Palette.Swatch second) {
+        boolean firstValid = hasEnoughPopulation(first);
+        boolean secondValid = hasEnoughPopulation(second);
+        if (firstValid && secondValid) {
+            int firstPopulation = first.getPopulation();
+            int secondPopulation = second.getPopulation();
+            if (firstPopulation / (float) secondPopulation
+                    < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
+                return second;
+            } else {
+                return first;
+            }
+        } else if (firstValid) {
+            return first;
+        } else if (secondValid) {
+            return second;
+        }
+        return null;
+    }
+
+    private boolean hasEnoughPopulation(Palette.Swatch swatch) {
+        // We want a fraction that is at least 1% of the image
+        return swatch != null
+                && (swatch.getPopulation() / (float) RESIZE_BITMAP_AREA > MINIMUM_IMAGE_FRACTION);
+    }
+
     private int findBackgroundColorAndFilter(Palette palette) {
         // by default we use the dominant palette
         Palette.Swatch dominantSwatch = palette.getDominantSwatch();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 2124011..95f32bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -18,6 +18,7 @@
 
 import android.app.ActivityManager;
 import android.content.Context;
+import android.os.Handler;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Slog;
@@ -55,6 +56,7 @@
     protected final ViewGroup mContainer;
     private final FalsingManager mFalsingManager;
     private final DismissCallbackRegistry mDismissCallbackRegistry;
+    private final Handler mHandler;
     protected KeyguardHostView mKeyguardView;
     protected ViewGroup mRoot;
     private boolean mShowingSoon;
@@ -66,6 +68,7 @@
                     mBouncerPromptReason = mCallback.getBouncerPromptReason();
                 }
             };
+    private final Runnable mRemoveViewRunnable = this::removeView;
 
     public KeyguardBouncer(Context context, ViewMediatorCallback callback,
             LockPatternUtils lockPatternUtils, ViewGroup container,
@@ -77,6 +80,7 @@
         KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
         mFalsingManager = FalsingManager.getInstance(mContext);
         mDismissCallbackRegistry = dismissCallbackRegistry;
+        mHandler = new Handler();
     }
 
     public void show(boolean resetSecuritySelection) {
@@ -179,10 +183,14 @@
             mKeyguardView.cancelDismissAction();
             mKeyguardView.cleanUp();
         }
-        if (destroyView) {
-            removeView();
-        } else if (mRoot != null) {
+        if (mRoot != null) {
             mRoot.setVisibility(View.INVISIBLE);
+            if (destroyView) {
+
+                // We have a ViewFlipper that unregisters a broadcast when being detached, which may
+                // be slow because of AM lock contention during unlocking. We can delay it a bit.
+                mHandler.postDelayed(mRemoveViewRunnable, 50);
+            }
         }
     }
 
@@ -226,6 +234,7 @@
     }
 
     protected void ensureView() {
+        mHandler.removeCallbacks(mRemoveViewRunnable);
         if (mRoot == null) {
             inflateView();
         }
@@ -233,6 +242,7 @@
 
     protected void inflateView() {
         removeView();
+        mHandler.removeCallbacks(mRemoveViewRunnable);
         mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
         mKeyguardView = (KeyguardHostView) mRoot.findViewById(R.id.keyguard_host_view);
         mKeyguardView.setLockPatternUtils(mLockPatternUtils);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 4581204..52838b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -128,8 +128,7 @@
 
     protected boolean shouldShowNotificationIcon(NotificationData.Entry entry,
             NotificationData notificationData, boolean showAmbient) {
-        if (notificationData.isAmbient(entry.key) && !showAmbient
-                && !NotificationData.showNotificationEvenIfUnprovisioned(entry.notification)) {
+        if (notificationData.isAmbient(entry.key) && !showAmbient) {
             return false;
         }
         if (!StatusBar.isTopLevelChild(entry)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 41fb5f7..f3ba5aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -58,6 +58,7 @@
 import com.android.systemui.DockedStackExistsListener;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.UiOffloadThread;
 import com.android.systemui.qs.tiles.DndTile;
 import com.android.systemui.qs.tiles.RotationLockTile;
 import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -128,6 +129,7 @@
     private final KeyguardMonitor mKeyguardMonitor;
     private final LocationController mLocationController;
     private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
+    private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
 
     // Assume it's all good unless we hear otherwise.  We don't always seem
     // to get broadcasts that it *is* there.
@@ -472,30 +474,38 @@
     }
 
     private void updateManagedProfile() {
-        try {
-            final boolean showIcon;
-            final int userId = ActivityManager.getService().getLastResumedActivityUserId();
-            if (mUserManager.isManagedProfile(userId) && !mKeyguardMonitor.isShowing()) {
-                showIcon = true;
-                mIconController.setIcon(mSlotManagedProfile,
-                        R.drawable.stat_sys_managed_profile_status,
-                        mContext.getString(R.string.accessibility_managed_profile));
-            } else if (mManagedProfileInQuietMode) {
-                showIcon = true;
-                mIconController.setIcon(mSlotManagedProfile,
-                        R.drawable.stat_sys_managed_profile_status_off,
-                        mContext.getString(R.string.accessibility_managed_profile));
-            } else {
-                showIcon = false;
+        // getLastResumedActivityUserId needds to acquire the AM lock, which may be contended in
+        // some cases. Since it doesn't really matter here whether it's updated in this frame
+        // or in the next one, we call this method from our UI offload thread.
+        mUiOffloadThread.submit(() -> {
+            final int userId;
+            try {
+                userId = ActivityManager.getService().getLastResumedActivityUserId();
+                boolean isManagedProfile = mUserManager.isManagedProfile(userId);
+                mHandler.post(() -> {
+                    final boolean showIcon;
+                    if (isManagedProfile && !mKeyguardMonitor.isShowing()) {
+                        showIcon = true;
+                        mIconController.setIcon(mSlotManagedProfile,
+                                R.drawable.stat_sys_managed_profile_status,
+                                mContext.getString(R.string.accessibility_managed_profile));
+                    } else if (mManagedProfileInQuietMode) {
+                        showIcon = true;
+                        mIconController.setIcon(mSlotManagedProfile,
+                                R.drawable.stat_sys_managed_profile_status_off,
+                                mContext.getString(R.string.accessibility_managed_profile));
+                    } else {
+                        showIcon = false;
+                    }
+                    if (mManagedProfileIconVisible != showIcon) {
+                        mIconController.setIconVisibility(mSlotManagedProfile, showIcon);
+                        mManagedProfileIconVisible = showIcon;
+                    }
+                });
+            } catch (RemoteException e) {
+                Log.w(TAG, "updateManagedProfile: ", e);
             }
-            if (mManagedProfileIconVisible != showIcon) {
-                mIconController.setIconVisibility(mSlotManagedProfile, showIcon);
-                mManagedProfileIconVisible = showIcon;
-            }
-        } catch (RemoteException ex) {
-            Log.w(TAG, "updateManagedProfile: ", ex);
-            // ignore
-        }
+        });
     }
 
     private void updateForegroundInstantApps() {
@@ -503,26 +513,22 @@
         ArraySet<Pair<String, Integer>> notifs = new ArraySet<>(mCurrentNotifs);
         IPackageManager pm = AppGlobals.getPackageManager();
         mCurrentNotifs.clear();
-        try {
-            ArraySet<Integer> stacksToCheck = new ArraySet<>();
-            int[] STACKS_TO_CHECK = new int[]{
-                    StackId.FULLSCREEN_WORKSPACE_STACK_ID,
-                    StackId.DOCKED_STACK_ID,
-            };
-            int focusedId = ActivityManager.getService().getFocusedStackId();
-            if (focusedId == StackId.FULLSCREEN_WORKSPACE_STACK_ID
-                    || focusedId == StackId.FULLSCREEN_WORKSPACE_STACK_ID) {
-                checkStack(StackId.FULLSCREEN_WORKSPACE_STACK_ID, notifs, noMan, pm);
+        mUiOffloadThread.submit(() -> {
+            try {
+                int focusedId = ActivityManager.getService().getFocusedStackId();
+                if (focusedId == StackId.FULLSCREEN_WORKSPACE_STACK_ID) {
+                    checkStack(StackId.FULLSCREEN_WORKSPACE_STACK_ID, notifs, noMan, pm);
+                }
+                if (mDockedStackExists) {
+                    checkStack(StackId.DOCKED_STACK_ID, notifs, noMan, pm);
+                }
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
             }
-            if (mDockedStackExists) {
-                checkStack(StackId.DOCKED_STACK_ID, notifs, noMan, pm);
-            }
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-        // Cancel all the leftover notifications that don't have a foreground process anymore.
-        notifs.forEach(v -> noMan.cancelAsUser(v.first, SystemMessage.NOTE_INSTANT_APPS,
-                new UserHandle(v.second)));
+            // Cancel all the leftover notifications that don't have a foreground process anymore.
+            notifs.forEach(v -> noMan.cancelAsUser(v.first, SystemMessage.NOTE_INSTANT_APPS,
+                    new UserHandle(v.second)));
+        });
     }
 
     private void checkStack(int stackId, ArraySet<Pair<String, Integer>> notifs,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index fc73c0f..d798fbf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -83,6 +83,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.SystemService;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -131,6 +132,7 @@
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.SystemUIFactory;
+import com.android.systemui.UiOffloadThread;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.classifier.FalsingLog;
 import com.android.systemui.classifier.FalsingManager;
@@ -149,6 +151,7 @@
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
 import com.android.systemui.recents.events.activity.UndockingTaskEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.stackdivider.WindowManagerProxy;
 import com.android.systemui.statusbar.ActivatableNotificationView;
@@ -220,8 +223,6 @@
 import android.content.pm.UserInfo;
 import android.os.Build;
 import android.os.Handler;
-import android.service.dreams.DreamService;
-import android.service.dreams.IDreamManager;
 import android.service.notification.NotificationListenerService;
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
@@ -538,6 +539,7 @@
     private ViewMediatorCallback mKeyguardViewMediatorCallback;
     protected ScrimController mScrimController;
     protected DozeScrimController mDozeScrimController;
+    private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
 
     private final Runnable mAutohide = new Runnable() {
         @Override
@@ -778,8 +780,6 @@
         mAccessibilityManager = (AccessibilityManager)
                 mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
 
-        mDreamManager = IDreamManager.Stub.asInterface(
-                ServiceManager.checkService(DreamService.DREAM_SERVICE));
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
 
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
@@ -1532,13 +1532,7 @@
     }
 
     void awakenDreams() {
-        if (mDreamManager != null) {
-            try {
-                mDreamManager.awaken();
-            } catch (RemoteException e) {
-                // fine, stay asleep then
-            }
-        }
+        SystemServicesProxy.getInstance(mContext).awakenDreamsAsync();
     }
 
     public UserHandle getCurrentUserHandle() {
@@ -4348,7 +4342,7 @@
         checkBarModes();
         updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
         mKeyguardMonitor.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
-                mStatusBarKeyguardViewManager.isSecure(),
+                mUnlockMethodCache.isMethodSecure(),
                 mStatusBarKeyguardViewManager.isOccluded());
         Trace.endSection();
     }
@@ -5173,7 +5167,6 @@
     protected boolean mDisableNotificationAlerts = false;
 
     protected DevicePolicyManager mDevicePolicyManager;
-    protected IDreamManager mDreamManager;
     protected PowerManager mPowerManager;
     protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
@@ -6816,12 +6809,8 @@
             return false;
         }
 
-        boolean inUse = mPowerManager.isScreenOn();
-        try {
-            inUse = inUse && !mDreamManager.isDreaming();
-        } catch (RemoteException e) {
-            Log.d(TAG, "failed to query dream manager", e);
-        }
+        boolean inUse = mPowerManager.isScreenOn()
+                && !SystemServicesProxy.getInstance(mContext).isDreaming();
 
         if (!inUse && !isDozing()) {
             if (DEBUG) {
@@ -6898,11 +6887,13 @@
 
     @Override
     public void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
-        try {
-            mBarService.onNotificationExpansionChanged(key, userAction, expanded);
-        } catch (RemoteException e) {
-            // Ignore.
-        }
+        mUiOffloadThread.submit(() -> {
+            try {
+                mBarService.onNotificationExpansionChanged(key, userAction, expanded);
+            } catch (RemoteException e) {
+                // Ignore.
+            }
+        });
     }
 
     public boolean isKeyguardSecure() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index d6c080a..7bce33a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -124,13 +124,11 @@
         mKeyguardFadingAway = true;
         mKeyguardFadingAwayDelay = delay;
         mKeyguardFadingAwayDuration = fadeoutDuration;
-        notifyKeyguardChanged();
     }
 
     public void notifyKeyguardDoneFading() {
         mKeyguardFadingAway = false;
         mKeyguardGoingAway = false;
-        notifyKeyguardChanged();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 53671a1..e1acc9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -872,7 +872,14 @@
     private final KeyguardMonitor.Callback mCallback = new KeyguardMonitor.Callback() {
         @Override
         public void onKeyguardShowingChanged() {
-            notifyAdapters();
+
+            // When Keyguard is going away, we don't need to update our items immediately which
+            // helps making the transition faster.
+            if (!mKeyguardMonitor.isShowing()) {
+                mHandler.post(UserSwitcherController.this::notifyAdapters);
+            } else {
+                notifyAdapters();
+            }
         }
     };
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index aadae0f..0aac1c0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -21,15 +21,21 @@
 import android.os.MessageQueue;
 import android.support.test.InstrumentationRegistry;
 import android.testing.LeakCheck;
+import android.util.Log;
 
 import org.junit.Before;
 import org.junit.Rule;
 
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
 /**
  * Base class that does System UI specific setup.
  */
 public abstract class SysuiTestCase {
 
+    private static final String TAG = "SysuiTestCase";
+
     private Handler mHandler;
     @Rule
     public SysuiTestableContext mContext = new SysuiTestableContext(
@@ -57,6 +63,15 @@
         waitForIdleSync(mHandler);
     }
 
+    protected void waitForUiOffloadThread() {
+        Future<?> future = Dependency.get(UiOffloadThread.class).submit(() -> {});
+        try {
+            future.get();
+        } catch (InterruptedException | ExecutionException e) {
+            Log.e(TAG, "Failed to wait for ui offload thread.", e);
+        }
+    }
+
     public static void waitForIdleSync(Handler h) {
         validateThread(h.getLooper());
         Idler idler = new Idler(null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
index 131a70b..308670d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
@@ -23,6 +23,8 @@
 import android.support.test.runner.AndroidJUnit4;
 
 import com.android.internal.policy.IKeyguardDismissCallback;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.UiOffloadThread;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -35,7 +37,7 @@
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class DismissCallbackRegistryTest {
+public class DismissCallbackRegistryTest extends SysuiTestCase {
 
     private final DismissCallbackRegistry mDismissCallbackRegistry = new DismissCallbackRegistry();
     private @Mock IKeyguardDismissCallback mMockCallback;
@@ -50,6 +52,7 @@
     public void testCancelled() throws Exception {
         mDismissCallbackRegistry.addCallback(mMockCallback);
         mDismissCallbackRegistry.notifyDismissCancelled();
+        waitForUiOffloadThread();
         verify(mMockCallback).onDismissCancelled();
     }
 
@@ -58,6 +61,7 @@
         mDismissCallbackRegistry.addCallback(mMockCallback);
         mDismissCallbackRegistry.addCallback(mMockCallback2);
         mDismissCallbackRegistry.notifyDismissCancelled();
+        waitForUiOffloadThread();
         verify(mMockCallback).onDismissCancelled();
         verify(mMockCallback2).onDismissCancelled();
     }
@@ -66,6 +70,7 @@
     public void testSucceeded() throws Exception {
         mDismissCallbackRegistry.addCallback(mMockCallback);
         mDismissCallbackRegistry.notifyDismissSucceeded();
+        waitForUiOffloadThread();
         verify(mMockCallback).onDismissSucceeded();
     }
 
@@ -74,6 +79,7 @@
         mDismissCallbackRegistry.addCallback(mMockCallback);
         mDismissCallbackRegistry.addCallback(mMockCallback2);
         mDismissCallbackRegistry.notifyDismissSucceeded();
+        waitForUiOffloadThread();
         verify(mMockCallback).onDismissSucceeded();
         verify(mMockCallback2).onDismissSucceeded();
     }
@@ -83,6 +89,7 @@
         mDismissCallbackRegistry.addCallback(mMockCallback);
         mDismissCallbackRegistry.notifyDismissSucceeded();
         mDismissCallbackRegistry.notifyDismissSucceeded();
+        waitForUiOffloadThread();
         verify(mMockCallback, times(1)).onDismissSucceeded();
     }
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
index 0e30fb2..de8a518 100644
--- a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
+++ b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
@@ -26,6 +26,7 @@
 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
 import com.android.internal.annotations.GuardedBy;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -96,7 +97,7 @@
                 mNodeFromOriginalWindow = info;
             } else {
                 Slog.e(LOG_TAG, "Callback with unexpected interactionId");
-                throw new RuntimeException("Callback with unexpected interactionId"); // Remove
+                return;
             }
 
             mSingleNodeCallbackHappened = true;
@@ -119,7 +120,7 @@
                 mNodesWithReplacementActions = infos;
             } else {
                 Slog.e(LOG_TAG, "Callback with unexpected interactionId");
-                throw new RuntimeException("Callback with unexpected interactionId"); // Remove
+                return;
             }
             callbackForSingleNode = mSingleNodeCallbackHappened;
             callbackForMultipleNodes = mMultiNodeCallbackHappened;
@@ -147,7 +148,7 @@
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Extra callback");
                 }
-                throw new RuntimeException("Extra callback"); // Replace with return before submit
+                return;
             }
             if (mNodeFromOriginalWindow != null) {
                 replaceActionsOnInfoLocked(mNodeFromOriginalWindow);
@@ -172,7 +173,7 @@
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Extra callback");
                 }
-                throw new RuntimeException("Extra callback"); // Replace with return before submit
+                return;
             }
             if (mNodesFromOriginalWindow != null) {
                 for (int i = 0; i < mNodesFromOriginalWindow.size(); i++) {
@@ -180,7 +181,8 @@
                 }
             }
             recycleReplaceActionNodesLocked();
-            nodesToReturn = mNodesFromOriginalWindow;
+            nodesToReturn = (mNodesFromOriginalWindow == null)
+                    ? null : new ArrayList<>(mNodesFromOriginalWindow);
             mDone = true;
         }
         try {
@@ -195,6 +197,12 @@
     @GuardedBy("mLock")
     private void replaceActionsOnInfoLocked(AccessibilityNodeInfo info) {
         info.removeAllActions();
+        info.setClickable(false);
+        info.setFocusable(false);
+        info.setContextClickable(false);
+        info.setScrollable(false);
+        info.setLongClickable(false);
+        info.setDismissable(false);
         // We currently only replace actions for the root node
         if ((info.getSourceNodeId() == AccessibilityNodeInfo.ROOT_NODE_ID)
                 && mNodesWithReplacementActions != null) {
@@ -213,6 +221,12 @@
                         info.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
                         info.addAction(AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
                     }
+                    info.setClickable(nodeWithReplacementActions.isClickable());
+                    info.setFocusable(nodeWithReplacementActions.isFocusable());
+                    info.setContextClickable(nodeWithReplacementActions.isContextClickable());
+                    info.setScrollable(nodeWithReplacementActions.isScrollable());
+                    info.setLongClickable(nodeWithReplacementActions.isLongClickable());
+                    info.setDismissable(nodeWithReplacementActions.isDismissable());
                 }
             }
         }
@@ -220,6 +234,7 @@
 
     @GuardedBy("mLock")
     private void recycleReplaceActionNodesLocked() {
+        if (mNodesWithReplacementActions == null) return;
         for (int i = mNodesWithReplacementActions.size() - 1; i >= 0; i--) {
             AccessibilityNodeInfo nodeWithReplacementAction = mNodesWithReplacementActions.get(i);
             nodeWithReplacementAction.recycle();
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index 6e87f88..e380f2c 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -938,7 +938,12 @@
         if (pointerIdBits == ALL_POINTER_ID_BITS) {
             event = prototype;
         } else {
-            event = prototype.split(pointerIdBits);
+            try {
+                event = prototype.split(pointerIdBits);
+            } catch (IllegalArgumentException e) {
+                Slog.e(LOG_TAG, "sendMotionEvent: Failed to split motion event: " + e);
+                return;
+            }
         }
         if (action == MotionEvent.ACTION_DOWN) {
             event.setDownTime(event.getEventTime());
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index b65f54e..61057dd 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1697,7 +1697,7 @@
                     mHandler.removeMessages(MESSAGE_USER_SWITCHED);
 
                     /* disable and enable BT when detect a user switch */
-                    if (mEnable && mBluetooth != null) {
+                    if (mBluetooth != null && isEnabled()) {
                         try {
                             mBluetoothLock.readLock().lock();
                             if (mBluetooth != null) {
@@ -1766,6 +1766,8 @@
                         mState = BluetoothAdapter.STATE_OFF;
                         // enable
                         addActiveLog(REASON_USER_SWITCH, true);
+                        // mEnable flag could have been reset on disableBLE. Reenable it.
+                        mEnable = true;
                         handleEnable(mQuietEnable);
                     } else if (mBinding || mBluetooth != null) {
                         Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
index f5bae7c..fe9bfd0 100644
--- a/services/core/java/com/android/server/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -26,6 +26,7 @@
 import android.database.sqlite.SQLiteOpenHelper;
 import android.os.Environment;
 import android.os.UserManager;
+import android.os.storage.StorageManager;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Slog;
@@ -336,8 +337,11 @@
         synchronized (mFileWriteLock) {
             RandomAccessFile raf = null;
             try {
-                // Write the hash to file
-                raf = new RandomAccessFile(name, "rw");
+                // Write the hash to file, requiring each write to be synchronized to the
+                // underlying storage device immediately to avoid data loss in case of power loss.
+                // This also ensures future secdiscard operation on the file succeeds since the
+                // file would have been allocated on flash.
+                raf = new RandomAccessFile(name, "rws");
                 // Truncate the file if pattern is null, to clear the lock
                 if (hash == null || hash.length == 0) {
                     raf.setLength(0);
@@ -432,12 +436,17 @@
         return readFile(getSynthenticPasswordStateFilePathForUser(userId, handle, name));
     }
 
-    public void deleteSyntheticPasswordState(int userId, long handle, String name, boolean secure) {
+    public void deleteSyntheticPasswordState(int userId, long handle, String name) {
         String path = getSynthenticPasswordStateFilePathForUser(userId, handle, name);
         File file = new File(path);
         if (file.exists()) {
-            //TODO: (b/34600579) invoke secdiscardable
-            file.delete();
+            try {
+                mContext.getSystemService(StorageManager.class).secdiscard(file.getAbsolutePath());
+            } catch (Exception e) {
+                Slog.w(TAG, "Failed to secdiscard " + path, e);
+            } finally {
+                file.delete();
+            }
             mCache.putFile(path, null);
         }
     }
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 452fe1d..cffb158 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3009,6 +3009,18 @@
         }
     }
 
+    @Override
+    public void secdiscard(String path) {
+        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
+        waitForReady();
+
+        try {
+            mCryptConnector.execute("cryptfs", "secdiscard", escapeNull(path));
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
     class AppFuseMountScope extends AppFuseBridge.MountScope {
         boolean opened = false;
 
diff --git a/services/core/java/com/android/server/SyntheticPasswordManager.java b/services/core/java/com/android/server/SyntheticPasswordManager.java
index f797517..1d17ff7 100644
--- a/services/core/java/com/android/server/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/SyntheticPasswordManager.java
@@ -283,7 +283,7 @@
 
     // Nuke the SP handle (and as a result, its SID) for the given user.
     public void clearSidForUser(int userId) {
-        destroyState(SP_HANDLE_NAME, true, DEFAULT_HANDLE, userId);
+        destroyState(SP_HANDLE_NAME, DEFAULT_HANDLE, userId);
     }
 
     public boolean hasSidForUser(int userId) {
@@ -318,8 +318,8 @@
     }
 
     public void destroyEscrowData(int userId) {
-        destroyState(SP_E0_NAME, true, DEFAULT_HANDLE, userId);
-        destroyState(SP_P1_NAME, true, DEFAULT_HANDLE, userId);
+        destroyState(SP_E0_NAME, DEFAULT_HANDLE, userId);
+        destroyState(SP_P1_NAME, DEFAULT_HANDLE, userId);
     }
 
     /**
@@ -584,17 +584,17 @@
 
     public void destroyTokenBasedSyntheticPassword(long handle, int userId) {
         destroySyntheticPassword(handle, userId);
-        destroyState(SECDISCARDABLE_NAME, true, handle, userId);
+        destroyState(SECDISCARDABLE_NAME, handle, userId);
     }
 
     public void destroyPasswordBasedSyntheticPassword(long handle, int userId) {
         destroySyntheticPassword(handle, userId);
-        destroyState(SECDISCARDABLE_NAME, true, handle, userId);
-        destroyState(PASSWORD_DATA_NAME, true, handle, userId);
+        destroyState(SECDISCARDABLE_NAME, handle, userId);
+        destroyState(PASSWORD_DATA_NAME, handle, userId);
     }
 
     private void destroySyntheticPassword(long handle, int userId) {
-        destroyState(SP_BLOB_NAME, true, handle, userId);
+        destroyState(SP_BLOB_NAME, handle, userId);
         destroySPBlobKey(getHandleName(handle));
     }
 
@@ -629,8 +629,8 @@
         mStorage.writeSyntheticPasswordState(userId, handle, stateName, data);
     }
 
-    private void destroyState(String stateName, boolean secure, long handle, int userId) {
-        mStorage.deleteSyntheticPasswordState(userId, handle, stateName, secure);
+    private void destroyState(String stateName, long handle, int userId) {
+        mStorage.deleteSyntheticPasswordState(userId, handle, stateName);
     }
 
     protected byte[] decryptSPBlob(String blobKeyName, byte[] blob, byte[] applicationId) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 2bd55e2..36c3f7d 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -5922,6 +5922,13 @@
                 return;
             }
 
+            int visibility =
+                resolveAccountVisibility(account, packageName, getUserAccounts(userId));
+            if (visibility == AccountManager.VISIBILITY_NOT_VISIBLE) {
+                Slog.w(TAG, "requestAccountAccess: account is hidden");
+                return;
+            }
+
             if (AccountManagerService.this.hasAccountAccess(account, packageName,
                     new UserHandle(userId))) {
                 Bundle result = new Bundle();
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 5e03508..2680b425 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -780,7 +780,8 @@
                 smap.removeMessages(ServiceMap.MSG_UPDATE_FOREGROUND_APPS);
                 if (nextUpdateTime < Long.MAX_VALUE) {
                     Message msg = smap.obtainMessage();
-                    smap.sendMessageAtTime(msg, nextUpdateTime);
+                    smap.sendMessageAtTime(msg, nextUpdateTime
+                            + SystemClock.uptimeMillis() - SystemClock.elapsedRealtime());
                 }
             }
             if (!smap.mActiveForegroundAppsChanged) {
@@ -811,30 +812,35 @@
             Intent intent;
             String title;
             String msg;
+            String[] pkgs;
             if (active.size() == 1) {
                 intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                 intent.setData(Uri.fromParts("package", active.get(0).mPackageName, null));
                 title = context.getString(
                         R.string.foreground_service_app_in_background, active.get(0).mLabel);
                 msg = context.getString(R.string.foreground_service_tap_for_details);
+                pkgs = new String[] { active.get(0).mPackageName };
             } else {
                 intent = new Intent(Settings.ACTION_FOREGROUND_SERVICES_SETTINGS);
-                String[] pkgs = new String[active.size()];
+                pkgs = new String[active.size()];
                 for (int i = 0; i < active.size(); i++) {
                     pkgs[i] = active.get(i).mPackageName;
                 }
                 intent.putExtra("packages", pkgs);
                 title = context.getString(
                         R.string.foreground_service_apps_in_background, active.size());
-                msg =  active.get(0).mLabel.toString();
+                msg = active.get(0).mLabel.toString();
                 for (int i = 1; i < active.size(); i++) {
                     msg = context.getString(R.string.foreground_service_multiple_separator,
                             msg, active.get(i).mLabel);
                 }
             }
+            Bundle notificationBundle = new Bundle();
+            notificationBundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, pkgs);
             Notification.Builder n =
                     new Notification.Builder(context,
                             SystemNotificationChannels.FOREGROUND_SERVICE)
+                            .addExtras(notificationBundle)
                             .setSmallIcon(R.drawable.ic_check_circle_24px)
                             .setOngoing(true)
                             .setShowWhen(false)
@@ -854,10 +860,11 @@
         }
     }
 
-    private void requestUpdateActiveForegroundAppsLocked(ServiceMap smap, long time) {
+    private void requestUpdateActiveForegroundAppsLocked(ServiceMap smap, long timeElapsed) {
         Message msg = smap.obtainMessage(ServiceMap.MSG_UPDATE_FOREGROUND_APPS);
-        if (time != 0) {
-            smap.sendMessageAtTime(msg, time);
+        if (timeElapsed != 0) {
+            smap.sendMessageAtTime(msg,
+                    timeElapsed + SystemClock.uptimeMillis() - SystemClock.elapsedRealtime());
         } else {
             smap.mActiveForegroundAppsChanged = true;
             smap.sendMessage(msg);
@@ -909,6 +916,9 @@
                     if (changed) {
                         requestUpdateActiveForegroundAppsLocked(smap,
                                 nowElapsed + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME);
+                    } else if (smap.mActiveForegroundApps.size() > 0) {
+                        // Just being paranoid.
+                        requestUpdateActiveForegroundAppsLocked(smap, 0);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index df32089..54b28d1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7914,12 +7914,6 @@
                     final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
                     // Adjust the source bounds by the insets for the transition down
                     final Rect sourceBounds = new Rect(r.pictureInPictureArgs.getSourceRectHint());
-                    final Rect insets = r.pictureInPictureArgs.getSourceRectHintInsets();
-                    if (insets != null) {
-                        sourceBounds.offsetTo(Math.max(0, sourceBounds.left - insets.left),
-                                Math.max(0, sourceBounds.top - insets.top));
-                    }
-
                     mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, aspectRatio,
                             true /* moveHomeStackToFront */, "enterPictureInPictureMode");
                     final PinnedActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 4e00f2d..55ec3b0 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -149,6 +149,7 @@
 import android.util.Slog;
 import android.util.TimeUtils;
 import android.view.AppTransitionAnimationSpec;
+import android.view.IAppTransitionAnimationSpecsFuture;
 import android.view.IApplicationToken;
 import android.view.WindowManager.LayoutParams;
 
@@ -1437,7 +1438,13 @@
                 case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
                 case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
                     final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
-                    if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
+                    final IAppTransitionAnimationSpecsFuture specsFuture =
+                            pendingOptions.getSpecsFuture();
+                    if (specsFuture != null) {
+                        service.mWindowManager.overridePendingAppTransitionMultiThumbFuture(
+                                specsFuture, pendingOptions.getOnAnimationStartListener(),
+                                animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP);
+                    } else if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
                             && specs != null) {
                         service.mWindowManager.overridePendingAppTransitionMultiThumb(
                                 specs, pendingOptions.getOnAnimationStartListener(),
@@ -2165,7 +2172,8 @@
         final boolean shown = mWindowContainerController.addStartingWindow(packageName, theme,
                 compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
                 prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
-                allowTaskSnapshot());
+                allowTaskSnapshot(),
+                state.ordinal() >= RESUMED.ordinal() && state.ordinal() <= STOPPED.ordinal());
         if (shown) {
             mStartingWindowState = STARTING_WINDOW_SHOWN;
         }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 8210c07..79ea7ba 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2998,7 +2998,8 @@
 
         stack.animateResizePinnedStack(sourceHintBounds, destBounds, -1 /* animationDuration */,
                 true /* schedulePipModeChangedOnAnimationEnd */);
-        mService.mTaskChangeNotificationController.notifyActivityPinned(r.packageName);
+        mService.mTaskChangeNotificationController.notifyActivityPinned(r.packageName,
+                r.getTask().taskId);
     }
 
     /** Move activity with its stack to front and make the stack focused. */
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index a2eec5c..960351b 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -533,11 +533,12 @@
                     auxiliaryResponse, originalIntent, resolvedType, callingPackage,
                     verificationBundle, userId);
         }
-        return InstantAppResolver.buildEphemeralInstallerIntent(originalIntent,
-            auxiliaryResponse.failureIntent, callingPackage, verificationBundle,
-            resolvedType, userId, auxiliaryResponse.packageName,
-            auxiliaryResponse.splitName, auxiliaryResponse.versionCode,
-            auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
+        return InstantAppResolver.buildEphemeralInstallerIntent(
+                Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, originalIntent,
+                auxiliaryResponse.failureIntent, callingPackage, verificationBundle,
+                resolvedType, userId, auxiliaryResponse.packageName, auxiliaryResponse.splitName,
+                auxiliaryResponse.versionCode, auxiliaryResponse.token,
+                auxiliaryResponse.needsPhaseTwo);
     }
 
     void postStartActivityProcessing(
diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
index f5d7b68..ea9ff59 100644
--- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
@@ -96,7 +96,7 @@
     };
 
     private final TaskStackConsumer mNotifyActivityPinned = (l, m) -> {
-        l.onActivityPinned((String) m.obj);
+        l.onActivityPinned((String) m.obj, m.arg1);
     };
 
     private final TaskStackConsumer mNotifyActivityUnpinned = (l, m) -> {
@@ -279,10 +279,10 @@
     }
 
     /** Notifies all listeners when an Activity is pinned. */
-    void notifyActivityPinned(String packageName) {
+    void notifyActivityPinned(String packageName, int taskId) {
         mHandler.removeMessages(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG);
         final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG,
-                packageName);
+                taskId, 0, packageName);
         forAllLocalListeners(mNotifyActivityPinned, msg);
         msg.sendToTarget();
     }
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index dcd58e7..702cbbe 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -67,6 +67,10 @@
                     .createIfNeeded()
                     .build();
 
+    // like a PLAY_CREATE_IF_NEEDED operation but with a skip to the end of the ramp
+    private static final VolumeShaper.Operation PLAY_SKIP_RAMP =
+            new VolumeShaper.Operation.Builder(PLAY_CREATE_IF_NEEDED).setXOffset(1.0f).build();
+
     private final ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>();
     // a public client is one that needs an anonymized version of the playback configurations, we
     // keep track of whether there is at least one to know when we need to create the list of
@@ -487,17 +491,19 @@
     private static final class DuckingManager {
         private final HashMap<Integer, DuckedApp> mDuckers = new HashMap<Integer, DuckedApp>();
 
-        void duckUid(int uid, ArrayList<AudioPlaybackConfiguration> apcsToDuck) {
+        synchronized void duckUid(int uid, ArrayList<AudioPlaybackConfiguration> apcsToDuck) {
+            if (DEBUG) {  Log.v(TAG, "DuckingManager: duckUid() uid:"+ uid); }
             if (!mDuckers.containsKey(uid)) {
                 mDuckers.put(uid, new DuckedApp(uid));
             }
             final DuckedApp da = mDuckers.get(uid);
             for (AudioPlaybackConfiguration apc : apcsToDuck) {
-                da.addDuck(apc);
+                da.addDuck(apc, false /*skipRamp*/);
             }
         }
 
-        void unduckUid(int uid, HashMap<Integer, AudioPlaybackConfiguration> players) {
+        synchronized void unduckUid(int uid, HashMap<Integer, AudioPlaybackConfiguration> players) {
+            if (DEBUG) {  Log.v(TAG, "DuckingManager: unduckUid() uid:"+ uid); }
             final DuckedApp da = mDuckers.remove(uid);
             if (da == null) {
                 return;
@@ -506,25 +512,27 @@
         }
 
         // pre-condition: apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED
-        void checkDuck(@NonNull AudioPlaybackConfiguration apc) {
+        synchronized void checkDuck(@NonNull AudioPlaybackConfiguration apc) {
+            if (DEBUG) {  Log.v(TAG, "DuckingManager: checkDuck() player piid:"
+                    + apc.getPlayerInterfaceId()+ " uid:"+ apc.getClientUid()); }
             final DuckedApp da = mDuckers.get(apc.getClientUid());
             if (da == null) {
                 return;
             }
-            // FIXME here the player needs to be put in a state that is the same as if it
-            //   had been ducked as it starts. At the moment, this works already for linked
-            //   players, as is the case in gapless playback.
-            da.addDuck(apc);
+            da.addDuck(apc, true /*skipRamp*/);
         }
 
-        void dump(PrintWriter pw) {
+        synchronized void dump(PrintWriter pw) {
             for (DuckedApp da : mDuckers.values()) {
                 da.dump(pw);
             }
         }
 
-        void removeReleased(@NonNull AudioPlaybackConfiguration apc) {
-            final DuckedApp da = mDuckers.get(apc.getClientUid());
+        synchronized void removeReleased(@NonNull AudioPlaybackConfiguration apc) {
+            final int uid = apc.getClientUid();
+            if (DEBUG) {  Log.v(TAG, "DuckingManager: removedReleased() player piid: "
+                    + apc.getPlayerInterfaceId() + " uid:" + uid); }
+            final DuckedApp da = mDuckers.get(uid);
             if (da == null) {
                 return;
             }
@@ -550,20 +558,21 @@
             // pre-conditions:
             //  * apc != null
             //  * apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED
-            void addDuck(@NonNull AudioPlaybackConfiguration apc) {
+            void addDuck(@NonNull AudioPlaybackConfiguration apc, boolean skipRamp) {
                 final int piid = new Integer(apc.getPlayerInterfaceId());
                 if (mDuckedPlayers.contains(piid)) {
-                    if (DEBUG) { Log.v(TAG, "player " + piid + " already ducked"); }
+                    if (DEBUG) { Log.v(TAG, "player piid:" + piid + " already ducked"); }
                     return;
                 }
                 try {
-                    Log.v(TAG, "ducking player " + apc.getPlayerInterfaceId() + " uid:" + mUid);
+                    Log.v(TAG, "ducking (skipRamp=" + skipRamp + ") player piid:"
+                            + apc.getPlayerInterfaceId() + " uid:" + mUid);
                     apc.getPlayerProxy().applyVolumeShaper(
                             DUCK_VSHAPE,
-                            PLAY_CREATE_IF_NEEDED);
+                            skipRamp ? PLAY_SKIP_RAMP : PLAY_CREATE_IF_NEEDED);
                     mDuckedPlayers.add(piid);
                 } catch (Exception e) {
-                    Log.e(TAG, "Error ducking player " + piid + " uid:" + mUid, e);
+                    Log.e(TAG, "Error ducking player piid:" + piid + " uid:" + mUid, e);
                 }
             }
 
@@ -577,13 +586,13 @@
                                     DUCK_ID,
                                     VolumeShaper.Operation.REVERSE);
                         } catch (Exception e) {
-                            Log.e(TAG, "Error unducking player " + piid + " uid:" + mUid, e);
+                            Log.e(TAG, "Error unducking player piid:" + piid + " uid:" + mUid, e);
                         }
                     } else {
                         // this piid was in the list of ducked players, but wasn't found
                         if (DEBUG) {
-                            Log.v(TAG, "Error unducking player " + piid + ", player not found for"
-                                    + " uid " + mUid);
+                            Log.v(TAG, "Error unducking player piid:" + piid
+                                    + ", player not found for uid " + mUid);
                         }
                     }
                 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 96f6f2d..11296ab 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -960,14 +960,18 @@
                 return result;
             }
         }
-        // Otherwise wait until https probe completes and use its result.
+        // Otherwise wait until http and https probes completes and use their results.
         try {
+            httpProbe.join();
+            if (httpProbe.result().isPortal()) {
+                return httpProbe.result();
+            }
             httpsProbe.join();
+            return httpsProbe.result();
         } catch (InterruptedException e) {
-            validationLog("Error: https probe wait interrupted!");
+            validationLog("Error: http or https probe wait interrupted!");
             return CaptivePortalProbeResult.FAILED;
         }
-        return httpsProbe.result();
     }
 
     private URL makeURL(String url) {
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
index d38beb3..44c61f0 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -16,6 +16,7 @@
 
 package com.android.server.connectivity.tethering;
 
+import static android.content.Context.TELEPHONY_SERVICE;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
 import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
@@ -47,9 +48,9 @@
 public class TetheringConfiguration {
     private static final String TAG = TetheringConfiguration.class.getSimpleName();
 
-    private static final int DUN_NOT_REQUIRED = 0;
-    private static final int DUN_REQUIRED = 1;
-    private static final int DUN_UNSPECIFIED = 2;
+    public static final int DUN_NOT_REQUIRED = 0;
+    public static final int DUN_REQUIRED = 1;
+    public static final int DUN_UNSPECIFIED = 2;
 
     // USB is  192.168.42.1 and 255.255.255.0
     // Wifi is 192.168.43.1 and 255.255.255.0
@@ -81,8 +82,9 @@
         tetherableBluetoothRegexs = ctx.getResources().getStringArray(
                 com.android.internal.R.array.config_tether_bluetooth_regexs);
 
-        isDunRequired = checkDunRequired(ctx);
-        preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(ctx, isDunRequired);
+        final int dunCheck = checkDunRequired(ctx);
+        preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(ctx, dunCheck);
+        isDunRequired = preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN);
 
         dhcpRanges = getDhcpRanges(ctx);
         defaultIPv4DNS = copy(DEFAULT_IPV4_DNS);
@@ -138,14 +140,12 @@
         pw.println();
     }
 
-    private static boolean checkDunRequired(Context ctx) {
-        final TelephonyManager tm = ctx.getSystemService(TelephonyManager.class);
-        final int secureSetting =
-                (tm != null) ? tm.getTetherApnRequired() : DUN_UNSPECIFIED;
-        return (secureSetting == DUN_REQUIRED);
+    private static int checkDunRequired(Context ctx) {
+        final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE);
+        return (tm != null) ? tm.getTetherApnRequired() : DUN_UNSPECIFIED;
     }
 
-    private static Collection<Integer> getUpstreamIfaceTypes(Context ctx, boolean requiresDun) {
+    private static Collection<Integer> getUpstreamIfaceTypes(Context ctx, int dunCheck) {
         final int ifaceTypes[] = ctx.getResources().getIntArray(
                 com.android.internal.R.array.config_tether_upstream_types);
         final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length);
@@ -153,10 +153,10 @@
             switch (i) {
                 case TYPE_MOBILE:
                 case TYPE_MOBILE_HIPRI:
-                    if (requiresDun) continue;
+                    if (dunCheck == DUN_REQUIRED) continue;
                     break;
                 case TYPE_MOBILE_DUN:
-                    if (!requiresDun) continue;
+                    if (dunCheck == DUN_NOT_REQUIRED) continue;
                     break;
             }
             upstreamIfaceTypes.add(i);
@@ -166,7 +166,7 @@
         // of the value of |requiresDun|, cell data of one form or another is
         // *always* an upstream, regardless of the upstream interface types
         // specified by configuration resources.
-        if (requiresDun) {
+        if (dunCheck == DUN_REQUIRED) {
             if (!upstreamIfaceTypes.contains(TYPE_MOBILE_DUN)) {
                 upstreamIfaceTypes.add(TYPE_MOBILE_DUN);
             }
diff --git a/services/core/java/com/android/server/fingerprint/RemovalClient.java b/services/core/java/com/android/server/fingerprint/RemovalClient.java
index 88a6bdd..8646107 100644
--- a/services/core/java/com/android/server/fingerprint/RemovalClient.java
+++ b/services/core/java/com/android/server/fingerprint/RemovalClient.java
@@ -85,7 +85,6 @@
         IFingerprintServiceReceiver receiver = getReceiver();
         try {
             if (receiver != null) {
-                // TODO: plumb remaining
                 receiver.onRemoved(getHalDeviceId(), fingerId, groupId, remaining);
             }
         } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index c08f866..b0d76e8 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -63,6 +63,7 @@
 import android.os.ShellCallback;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.os.UserManagerInternal;
 import android.provider.Settings;
 import android.util.KeyValueListParser;
 import android.util.Slog;
@@ -751,6 +752,13 @@
         }
     }
 
+    private void cancelJobsForNonExistentUsers() {
+        UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
+        synchronized (mLock) {
+            mJobs.removeJobsOfNonUsers(umi.getUserIds());
+        }
+    }
+
     void cancelJobsForPackageAndUid(String pkgName, int uid) {
         synchronized (mLock) {
             final List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
@@ -941,6 +949,8 @@
             } catch (RemoteException e) {
                 // ignored; both services live in system_server
             }
+            // Remove any jobs that are not associated with any of the current users.
+            cancelJobsForNonExistentUsers();
         } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
             synchronized (mLock) {
                 // Let's go!
@@ -1270,6 +1280,17 @@
         }
     }
 
+    private void stopNonReadyActiveJobsLocked() {
+        for (int i=0; i<mActiveServices.size(); i++) {
+            JobServiceContext serviceContext = mActiveServices.get(i);
+            final JobStatus running = serviceContext.getRunningJobLocked();
+            if (running != null && !running.isReady()) {
+                serviceContext.cancelExecutingJobLocked(
+                        JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED);
+            }
+        }
+    }
+
     /**
      * Run through list of jobs and execute all possible - at least one is expired so we do
      * as many as we can.
@@ -1280,6 +1301,7 @@
         }
         noteJobsNonpending(mPendingJobs);
         mPendingJobs.clear();
+        stopNonReadyActiveJobsLocked();
         mJobs.forEachJob(mReadyQueueFunctor);
         mReadyQueueFunctor.postProcess();
 
@@ -1306,9 +1328,6 @@
                     newReadyJobs = new ArrayList<JobStatus>();
                 }
                 newReadyJobs.add(job);
-            } else if (areJobConstraintsNotSatisfiedLocked(job)) {
-                stopJobOnServiceContextLocked(job,
-                        JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED);
             }
         }
 
@@ -1387,9 +1406,6 @@
                     runnableJobs = new ArrayList<>();
                 }
                 runnableJobs.add(job);
-            } else if (areJobConstraintsNotSatisfiedLocked(job)) {
-                stopJobOnServiceContextLocked(job,
-                        JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED);
             }
         }
 
@@ -1439,6 +1455,7 @@
 
         noteJobsNonpending(mPendingJobs);
         mPendingJobs.clear();
+        stopNonReadyActiveJobsLocked();
         mJobs.forEachJob(mMaybeQueueFunctor);
         mMaybeQueueFunctor.postProcess();
     }
@@ -1516,15 +1533,6 @@
     }
 
     /**
-     * Criteria for cancelling an active job:
-     *      - It's not ready
-     *      - It's running on a JSC.
-     */
-    private boolean areJobConstraintsNotSatisfiedLocked(JobStatus job) {
-        return !job.isReady() && isCurrentlyActiveLocked(job);
-    }
-
-    /**
      * Reconcile jobs in the pending queue against available execution contexts.
      * A controller can force a job into the pending queue even if it's already running, but
      * here is where we decide whether to actually execute it.
@@ -2088,6 +2096,83 @@
         }
     }
 
+    int getJobState(PrintWriter pw, String pkgName, int userId, int jobId) {
+        try {
+            final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0,
+                    userId != UserHandle.USER_ALL ? userId : UserHandle.USER_SYSTEM);
+            if (uid < 0) {
+                pw.print("unknown("); pw.print(pkgName); pw.println(")");
+                return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE;
+            }
+
+            synchronized (mLock) {
+                final JobStatus js = mJobs.getJobByUidAndJobId(uid, jobId);
+                if (DEBUG) Slog.d(TAG, "get-job-state " + uid + "/" + jobId + ": " + js);
+                if (js == null) {
+                    pw.print("unknown("); UserHandle.formatUid(pw, uid);
+                    pw.print("/jid"); pw.print(jobId); pw.println(")");
+                    return JobSchedulerShellCommand.CMD_ERR_NO_JOB;
+                }
+
+                boolean printed = false;
+                if (mPendingJobs.contains(js)) {
+                    pw.print("pending");
+                    printed = true;
+                }
+                if (isCurrentlyActiveLocked(js)) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("active");
+                }
+                if (!ArrayUtils.contains(mStartedUsers, js.getUserId())) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("user-stopped");
+                }
+                if (mBackingUpUids.indexOfKey(js.getSourceUid()) >= 0) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("backing-up");
+                }
+                boolean componentPresent = false;
+                try {
+                    componentPresent = (AppGlobals.getPackageManager().getServiceInfo(
+                            js.getServiceComponent(),
+                            PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+                            js.getUserId()) != null);
+                } catch (RemoteException e) {
+                }
+                if (!componentPresent) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("no-component");
+                }
+                if (js.isReady()) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("ready");
+                }
+                if (!printed) {
+                    pw.print("waiting");
+                }
+                pw.println();
+            }
+        } catch (RemoteException e) {
+            // can't happen
+        }
+        return 0;
+    }
+
     private String printContextIdToJobMap(JobStatus[] map, String initial) {
         StringBuilder s = new StringBuilder(initial + ": ");
         for (int i=0; i<map.length; i++) {
@@ -2152,7 +2237,8 @@
         }
 
         final int filterUidFinal = UserHandle.getAppId(filterUid);
-        final long now = SystemClock.elapsedRealtime();
+        final long nowElapsed = SystemClock.elapsedRealtime();
+        final long nowUptime = SystemClock.uptimeMillis();
         synchronized (mLock) {
             mConstants.dump(pw);
             pw.println();
@@ -2184,7 +2270,7 @@
                         continue;
                     }
 
-                    job.dump(pw, "    ", true, now);
+                    job.dump(pw, "    ", true, nowElapsed);
                     pw.print("    Ready: ");
                     pw.print(isReadyToBeExecutedLocked(job));
                     pw.print(" (job=");
@@ -2254,14 +2340,14 @@
                 JobStatus job = mPendingJobs.get(i);
                 pw.print("  Pending #"); pw.print(i); pw.print(": ");
                 pw.println(job.toShortString());
-                job.dump(pw, "    ", false, now);
+                job.dump(pw, "    ", false, nowElapsed);
                 int priority = evaluateJobPriorityLocked(job);
                 if (priority != JobInfo.PRIORITY_DEFAULT) {
                     pw.print("    Evaluated priority: "); pw.println(priority);
                 }
                 pw.print("    Tag: "); pw.println(job.getTag());
                 pw.print("    Enq: ");
-                TimeUtils.formatDuration(job.madePending - now, pw);
+                TimeUtils.formatDuration(job.madePending - nowUptime, pw);
                 pw.println();
             }
             pw.println();
@@ -2276,17 +2362,17 @@
                 } else {
                     pw.println(job.toShortString());
                     pw.print("    Running for: ");
-                    TimeUtils.formatDuration(now - jsc.getExecutionStartTimeElapsed(), pw);
+                    TimeUtils.formatDuration(nowElapsed - jsc.getExecutionStartTimeElapsed(), pw);
                     pw.print(", timeout at: ");
-                    TimeUtils.formatDuration(jsc.getTimeoutElapsed() - now, pw);
+                    TimeUtils.formatDuration(jsc.getTimeoutElapsed() - nowElapsed, pw);
                     pw.println();
-                    job.dump(pw, "    ", false, now);
+                    job.dump(pw, "    ", false, nowElapsed);
                     int priority = evaluateJobPriorityLocked(jsc.getRunningJobLocked());
                     if (priority != JobInfo.PRIORITY_DEFAULT) {
                         pw.print("    Evaluated priority: "); pw.println(priority);
                     }
                     pw.print("    Active at ");
-                    TimeUtils.formatDuration(job.madeActive - now, pw);
+                    TimeUtils.formatDuration(job.madeActive - nowUptime, pw);
                     pw.print(", pending for ");
                     TimeUtils.formatDuration(job.madeActive - job.madePending, pw);
                     pw.println();
diff --git a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
index fdfb345..2d2f61f 100644
--- a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -60,6 +60,8 @@
                     return getStorageSeq(pw);
                 case "get-storage-not-low":
                     return getStorageNotLow(pw);
+                case "get-job-state":
+                    return getJobState(pw);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -83,6 +85,43 @@
         }
     }
 
+    private boolean printError(int errCode, String pkgName, int userId, int jobId) {
+        PrintWriter pw;
+        switch (errCode) {
+            case CMD_ERR_NO_PACKAGE:
+                pw = getErrPrintWriter();
+                pw.print("Package not found: ");
+                pw.print(pkgName);
+                pw.print(" / user ");
+                pw.println(userId);
+                return true;
+
+            case CMD_ERR_NO_JOB:
+                pw = getErrPrintWriter();
+                pw.print("Could not find job ");
+                pw.print(jobId);
+                pw.print(" in package ");
+                pw.print(pkgName);
+                pw.print(" / user ");
+                pw.println(userId);
+                return true;
+
+            case CMD_ERR_CONSTRAINTS:
+                pw = getErrPrintWriter();
+                pw.print("Job ");
+                pw.print(jobId);
+                pw.print(" in package ");
+                pw.print(pkgName);
+                pw.print(" / user ");
+                pw.print(userId);
+                pw.println(" has functional constraints but --force not specified");
+                return true;
+
+            default:
+                return false;
+        }
+    }
+
     private int runJob(PrintWriter pw) throws Exception {
         checkPermission("force scheduled jobs");
 
@@ -114,42 +153,17 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force);
-            switch (ret) {
-                case CMD_ERR_NO_PACKAGE:
-                    pw.print("Package not found: ");
-                    pw.print(pkgName);
-                    pw.print(" / user ");
-                    pw.println(userId);
-                    break;
-
-                case CMD_ERR_NO_JOB:
-                    pw.print("Could not find job ");
-                    pw.print(jobId);
-                    pw.print(" in package ");
-                    pw.print(pkgName);
-                    pw.print(" / user ");
-                    pw.println(userId);
-                    break;
-
-                case CMD_ERR_CONSTRAINTS:
-                    pw.print("Job ");
-                    pw.print(jobId);
-                    pw.print(" in package ");
-                    pw.print(pkgName);
-                    pw.print(" / user ");
-                    pw.print(userId);
-                    pw.println(" has functional constraints but --force not specified");
-                    break;
-
-                default:
-                    // success!
-                    pw.print("Running job");
-                    if (force) {
-                        pw.print(" [FORCED]");
-                    }
-                    pw.println();
-                    break;
+            if (printError(ret, pkgName, userId, jobId)) {
+                return ret;
             }
+
+            // success!
+            pw.print("Running job");
+            if (force) {
+                pw.print(" [FORCED]");
+            }
+            pw.println();
+
             return ret;
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -244,6 +258,43 @@
         return 0;
     }
 
+    private int getJobState(PrintWriter pw) throws Exception {
+        checkPermission("force timeout jobs");
+
+        int userId = UserHandle.USER_SYSTEM;
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-u":
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+
+                default:
+                    pw.println("Error: unknown option '" + opt + "'");
+                    return -1;
+            }
+        }
+
+        if (userId == UserHandle.USER_CURRENT) {
+            userId = ActivityManager.getCurrentUser();
+        }
+
+        final String pkgName = getNextArgRequired();
+        final String jobIdStr = getNextArgRequired();
+        final int jobId = Integer.parseInt(jobIdStr);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            int ret = mInternal.getJobState(pw, pkgName, userId, jobId);
+            printError(ret, pkgName, userId, jobId);
+            return ret;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
     @Override
     public void onHelp() {
         final PrintWriter pw = getOutPrintWriter();
@@ -277,6 +328,18 @@
         pw.println("    Return the last storage update sequence number that was received.");
         pw.println("  get-storage-not-low");
         pw.println("    Return whether storage is currently considered to not be low.");
+        pw.println("  get-job-state [-u | --user USER_ID] PACKAGE JOB_ID");
+        pw.println("    Return the current state of a job, may be any combination of:");
+        pw.println("      pending: currently on the pending list, waiting to be active");
+        pw.println("      active: job is actively running");
+        pw.println("      user-stopped: job can't run because its user is stopped");
+        pw.println("      backing-up: job can't run because app is currently backing up its data");
+        pw.println("      no-component: job can't run because its component is not available");
+        pw.println("      ready: job is ready to run (all constraints satisfied or bypassed)");
+        pw.println("      waiting: if nothing else above is printed, job not ready to run");
+        pw.println("    Options:");
+        pw.println("      -u or --user: specify which user's job is to be run; the default is");
+        pw.println("         the primary or system user");
         pw.println();
     }
 
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 497d36f..22eed3b 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -35,6 +35,7 @@
 import android.util.Xml;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.server.IoThread;
 import com.android.server.job.controllers.JobStatus;
@@ -171,6 +172,14 @@
         return removed;
     }
 
+    /**
+     * Remove the jobs of users not specified in the whitelist.
+     * @param whitelist Array of User IDs whose jobs are not to be removed.
+     */
+    public void removeJobsOfNonUsers(int[] whitelist) {
+        mJobSet.removeJobsOfNonUsers(whitelist);
+    }
+
     @VisibleForTesting
     public void clear() {
         mJobSet.clear();
@@ -839,6 +848,17 @@
             return didRemove;
         }
 
+        // Remove the jobs all users not specified by the whitelist of user ids
+        public void removeJobsOfNonUsers(int[] whitelist) {
+            for (int jobIndex = mJobs.size() - 1; jobIndex >= 0; jobIndex--) {
+                int jobUserId = UserHandle.getUserId(mJobs.keyAt(jobIndex));
+                // check if job's user id is not in the whitelist
+                if (!ArrayUtils.contains(whitelist, jobUserId)) {
+                    mJobs.removeAt(jobIndex);
+                }
+            }
+        }
+
         public boolean contains(JobStatus job) {
             final int uid = job.getUid();
             ArraySet<JobStatus> jobs = mJobs.get(uid);
diff --git a/services/core/java/com/android/server/job/controllers/BatteryController.java b/services/core/java/com/android/server/job/controllers/BatteryController.java
index b1f8f6b..d275bd9 100644
--- a/services/core/java/com/android/server/job/controllers/BatteryController.java
+++ b/services/core/java/com/android/server/job/controllers/BatteryController.java
@@ -93,34 +93,31 @@
         }
     }
 
-    private void maybeReportNewChargingState() {
+    private void maybeReportNewChargingStateLocked() {
         final boolean stablePower = mChargeTracker.isOnStablePower();
         final boolean batteryNotLow = mChargeTracker.isBatteryNotLow();
         if (DEBUG) {
-            Slog.d(TAG, "maybeReportNewChargingState: " + stablePower);
+            Slog.d(TAG, "maybeReportNewChargingStateLocked: " + stablePower);
         }
         boolean reportChange = false;
-        synchronized (mLock) {
-            for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
-                final JobStatus ts = mTrackedTasks.valueAt(i);
-                boolean previous = ts.setChargingConstraintSatisfied(stablePower);
-                if (previous != stablePower) {
-                    reportChange = true;
-                }
-                previous = ts.setBatteryNotLowConstraintSatisfied(batteryNotLow);
-                if (previous != batteryNotLow) {
-                    reportChange = true;
-                }
+        for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
+            final JobStatus ts = mTrackedTasks.valueAt(i);
+            boolean previous = ts.setChargingConstraintSatisfied(stablePower);
+            if (previous != stablePower) {
+                reportChange = true;
+            }
+            previous = ts.setBatteryNotLowConstraintSatisfied(batteryNotLow);
+            if (previous != batteryNotLow) {
+                reportChange = true;
             }
         }
-        // Let the scheduler know that state has changed. This may or may not result in an
-        // execution.
-        if (reportChange) {
-            mStateChangedListener.onControllerStateChanged();
-        }
-        // Also tell the scheduler that any ready jobs should be flushed.
         if (stablePower || batteryNotLow) {
+            // If one of our conditions has been satisfied, always schedule any newly ready jobs.
             mStateChangedListener.onRunJobNow(null);
+        } else if (reportChange) {
+            // Otherwise, just let the job scheduler know the state has changed and take care of it
+            // as it thinks is best.
+            mStateChangedListener.onControllerStateChanged();
         }
     }
 
@@ -201,38 +198,42 @@
 
         @VisibleForTesting
         public void onReceiveInternal(Intent intent) {
-            final String action = intent.getAction();
-            if (Intent.ACTION_BATTERY_LOW.equals(action)) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Battery life too low to do work. @ "
-                            + SystemClock.elapsedRealtime());
+            synchronized (mLock) {
+                final String action = intent.getAction();
+                if (Intent.ACTION_BATTERY_LOW.equals(action)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Battery life too low to do work. @ "
+                                + SystemClock.elapsedRealtime());
+                    }
+                    // If we get this action, the battery is discharging => it isn't plugged in so
+                    // there's no work to cancel. We track this variable for the case where it is
+                    // charging, but hasn't been for long enough to be healthy.
+                    mBatteryHealthy = false;
+                    maybeReportNewChargingStateLocked();
+                } else if (Intent.ACTION_BATTERY_OKAY.equals(action)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Battery life healthy enough to do work. @ "
+                                + SystemClock.elapsedRealtime());
+                    }
+                    mBatteryHealthy = true;
+                    maybeReportNewChargingStateLocked();
+                } else if (BatteryManager.ACTION_CHARGING.equals(action)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Received charging intent, fired @ "
+                                + SystemClock.elapsedRealtime());
+                    }
+                    mCharging = true;
+                    maybeReportNewChargingStateLocked();
+                } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Disconnected from power.");
+                    }
+                    mCharging = false;
+                    maybeReportNewChargingStateLocked();
                 }
-                // If we get this action, the battery is discharging => it isn't plugged in so
-                // there's no work to cancel. We track this variable for the case where it is
-                // charging, but hasn't been for long enough to be healthy.
-                mBatteryHealthy = false;
-            } else if (Intent.ACTION_BATTERY_OKAY.equals(action)) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Battery life healthy enough to do work. @ "
-                            + SystemClock.elapsedRealtime());
-                }
-                mBatteryHealthy = true;
-                maybeReportNewChargingState();
-            } else if (BatteryManager.ACTION_CHARGING.equals(action)) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Received charging intent, fired @ "
-                            + SystemClock.elapsedRealtime());
-                }
-                mCharging = true;
-                maybeReportNewChargingState();
-            } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Disconnected from power.");
-                }
-                mCharging = false;
-                maybeReportNewChargingState();
+                mLastBatterySeq = intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE,
+                        mLastBatterySeq);
             }
-            mLastBatterySeq = intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE, mLastBatterySeq);
         }
     }
 
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 51bebb09..85d8986 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -937,7 +937,7 @@
                     long time = mNtpTime.getCachedNtpTime();
                     long timeReference = mNtpTime.getCachedNtpTimeReference();
                     long certainty = mNtpTime.getCacheCertainty();
-                    long now = System.currentTimeMillis();
+                    long now = SystemClock.elapsedRealtime();
 
                     if (DEBUG) {
                         Log.d(TAG, "NTP server returned: "
@@ -1444,7 +1444,8 @@
 
             // reset SV count to zero
             updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
-            mFixRequestTime = System.currentTimeMillis();
+            mFixRequestTime = SystemClock.elapsedRealtime();
+
             if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
                 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
                 // and our fix interval is not short
@@ -1514,7 +1515,7 @@
             }
         }
 
-        mLastFixTime = System.currentTimeMillis();
+        mLastFixTime = SystemClock.elapsedRealtime();
         // report time to first fix
         if (mTimeToFirstFix == 0 && hasLatLong) {
             mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);
@@ -1629,7 +1630,7 @@
         updateStatus(mStatus, usedInFixCount);
 
         if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
-            System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
+            SystemClock.elapsedRealtime() - mLastFixTime > RECENT_FIX_TIMEOUT) {
             // send an intent to notify that the GPS is no longer receiving fixes.
             Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
             intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 5a5e658..803b0dc 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -153,7 +153,7 @@
                   final ApplicationInfo applicationInfo =
                         mContext.getPackageManager().getApplicationInfoAsUser(sbn.getPackageName(),
                                 0, UserHandle.getUserId(sbn.getUid()));
-                if (applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
+                if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) {
                     return true;
                 }
             }
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index e83d453..f00ef38 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -286,7 +286,7 @@
     private boolean shouldHaveDefaultChannel(Record r) throws NameNotFoundException {
         final int userId = UserHandle.getUserId(r.uid);
         final ApplicationInfo applicationInfo = mPm.getApplicationInfoAsUser(r.pkg, 0, userId);
-        if (applicationInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1) {
+        if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
             // O apps should not have the default channel.
             return false;
         }
@@ -1158,6 +1158,9 @@
 
     public boolean badgingEnabled(UserHandle userHandle) {
         int userId = userHandle.getIdentifier();
+        if (userId == UserHandle.USER_ALL) {
+            return false;
+        }
         if (mBadgingEnabled.indexOfKey(userId) < 0) {
             mBadgingEnabled.put(userId,
                     Secure.getIntForUser(mContext.getContentResolver(),
diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
index 1de3936..562ab33 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
@@ -96,7 +96,7 @@
                 return mGetEphemeralResolveInfoCaller
                         .getEphemeralResolveInfoList(target, hashPrefix, token);
             } catch (TimeoutException e) {
-                throw new ConnectionException(ConnectionException.FAILURE_BIND);
+                throw new ConnectionException(ConnectionException.FAILURE_CALL);
             } catch (RemoteException ignore) {
             }
         } finally {
diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java
index 85be4a2..34cc6e3 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolver.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolver.java
@@ -182,6 +182,7 @@
                     failureIntent = null;
                 }
                 final Intent installerIntent = buildEphemeralInstallerIntent(
+                        Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE,
                         requestObj.origIntent,
                         failureIntent,
                         requestObj.callingPackage,
@@ -226,6 +227,7 @@
      * Builds and returns an intent to launch the instant installer.
      */
     public static Intent buildEphemeralInstallerIntent(
+            @NonNull String action,
             @NonNull Intent origIntent,
             @NonNull Intent failureIntent,
             @NonNull String callingPackage,
@@ -239,7 +241,7 @@
             boolean needsPhaseTwo) {
         // Construct the intent that launches the instant installer
         int flags = origIntent.getFlags();
-        final Intent intent = new Intent();
+        final Intent intent = new Intent(action);
         intent.setFlags(flags
                 | Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_CLEAR_TASK
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 400ee0c..b1068ae 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2026,15 +2026,17 @@
             EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
                     getUnknownSourcesSettings());
 
-            // Force a gc to clear up things
-            Runtime.getRuntime().gc();
-
             // Remove the replaced package's older resources safely now
             // We delete after a gc for applications  on sdcard.
             if (res.removedInfo != null && res.removedInfo.args != null) {
+                Runtime.getRuntime().gc();
                 synchronized (mInstallLock) {
                     res.removedInfo.args.doPostDeleteLI(true);
                 }
+            } else {
+                // Force a gc to clear up things. Ask for a background one, it's fine to go on
+                // and not block here.
+                VMRuntime.getRuntime().requestConcurrentGC();
             }
 
             // Notify DexManager that the package was installed for new users.
@@ -3480,28 +3482,49 @@
         return cur;
     }
 
+    /**
+     * Returns whether or not a full application can see an instant application.
+     * <p>
+     * Currently, there are three cases in which this can occur:
+     * <ol>
+     * <li>The calling application is a "special" process. The special
+     *     processes are {@link Process#SYSTEM_UID}, {@link Process#SHELL_UID}
+     *     and {@code 0}</li>
+     * <li>The calling application has the permission
+     *     {@link android.Manifest.permission#ACCESS_INSTANT_APPS}</li>
+     * <li>[TODO] The calling application is the default launcher on the
+     *     system partition.</li>
+     * </ol>
+     */
+    private boolean canAccessInstantApps(int callingUid) {
+        final boolean isSpecialProcess =
+                callingUid == Process.SYSTEM_UID
+                        || callingUid == Process.SHELL_UID
+                        || callingUid == 0;
+        final boolean allowMatchInstant =
+                isSpecialProcess
+                        || mContext.checkCallingOrSelfPermission(
+                        android.Manifest.permission.ACCESS_INSTANT_APPS) == PERMISSION_GRANTED;
+        return allowMatchInstant;
+    }
     private PackageInfo generatePackageInfo(PackageSetting ps, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         if (ps == null) {
             return null;
         }
-        final PackageParser.Package p = ps.pkg;
+        PackageParser.Package p = ps.pkg;
         if (p == null) {
             return null;
         }
+        final int callingUid =  Binder.getCallingUid();
         // Filter out ephemeral app metadata:
         //   * The system/shell/root can see metadata for any app
         //   * An installed app can see metadata for 1) other installed apps
         //     and 2) ephemeral apps that have explicitly interacted with it
         //   * Ephemeral apps can only see their own data and exposed installed apps
         //   * Holding a signature permission allows seeing instant apps
-        final int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
-        if (callingAppId != Process.SYSTEM_UID
-                && callingAppId != Process.SHELL_UID
-                && callingAppId != Process.ROOT_UID
-                && checkUidPermission(Manifest.permission.ACCESS_INSTANT_APPS,
-                        Binder.getCallingUid()) != PackageManager.PERMISSION_GRANTED) {
-            final String instantAppPackageName = getInstantAppPackageName(Binder.getCallingUid());
+        if (!canAccessInstantApps(callingUid)) {
+            final String instantAppPackageName = getInstantAppPackageName(callingUid);
             if (instantAppPackageName != null) {
                 // ephemeral apps can only get information on themselves or
                 // installed apps that are exposed.
@@ -3512,6 +3535,7 @@
             } else {
                 if (ps.getInstantApp(userId)) {
                     // only get access to the ephemeral app if we've been granted access
+                    final int callingAppId = UserHandle.getAppId(callingUid);
                     if (!mInstantAppRegistry.isInstantAccessGranted(
                             userId, callingAppId, ps.appId)) {
                         return null;
@@ -3610,15 +3634,15 @@
     public PackageInfo getPackageInfoVersioned(VersionedPackage versionedPackage,
             int flags, int userId) {
         return getPackageInfoInternal(versionedPackage.getPackageName(),
-                // TODO: We will change version code to long, so in the new API it is long
-                (int) versionedPackage.getVersionCode(), flags, userId);
+                versionedPackage.getVersionCode(), flags, userId);
     }
 
     private PackageInfo getPackageInfoInternal(String packageName, int versionCode,
             int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForPackage(flags, userId, packageName);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get package info");
 
         // reader
@@ -3630,7 +3654,10 @@
             if (matchFactoryOnly) {
                 final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName);
                 if (ps != null) {
-                    if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+                    if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+                        return null;
+                    }
+                    if (filterAppAccessLPr(ps, callingUid, userId)) {
                         return null;
                     }
                     return generatePackageInfo(ps, flags, userId);
@@ -3644,15 +3671,22 @@
             if (DEBUG_PACKAGE_INFO)
                 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
             if (p != null) {
-                if (filterSharedLibPackageLPr((PackageSetting) p.mExtras,
-                        Binder.getCallingUid(), userId, flags)) {
+                final PackageSetting ps = (PackageSetting) p.mExtras;
+                if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+                    return null;
+                }
+                if (ps != null && filterAppAccessLPr(ps, callingUid, userId)) {
                     return null;
                 }
                 return generatePackageInfo((PackageSetting)p.mExtras, flags, userId);
             }
             if (!matchFactoryOnly && (flags & MATCH_KNOWN_PACKAGES) != 0) {
                 final PackageSetting ps = mSettings.mPackages.get(packageName);
-                if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+                if (ps == null) return null;
+                if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+                    return null;
+                }
+                if (filterAppAccessLPr(ps, callingUid, userId)) {
                     return null;
                 }
                 return generatePackageInfo(ps, flags, userId);
@@ -3661,6 +3695,57 @@
         return null;
     }
 
+    /**
+     * Returns whether or not access to the application should be filtered.
+     * <p>
+     * Access may be limited based upon whether the calling or target applications
+     * are instant applications.
+     *
+     * @see #canAccessInstantApps(int)
+     */
+    private boolean filterAppAccessLPr(@NonNull PackageSetting ps, int callingUid,
+            @Nullable ComponentName component, boolean componentVisibleToInstantApp, int userId) {
+        // if we're in an isolated process, get the real calling UID
+        if (Process.isIsolated(callingUid)) {
+            callingUid = mIsolatedOwners.get(callingUid);
+        }
+        // if the target and caller are the same application, don't filter
+        if (isCallerSameApp(ps.name, callingUid)) {
+            return false;
+        }
+        final String instantAppPkgName = getInstantAppPackageName(callingUid);
+        final boolean callerIsInstantApp = instantAppPkgName != null;
+        if (callerIsInstantApp) {
+            // request for a specific component; if it hasn't been explicitly exposed, filter
+            if (component != null) {
+                return !componentVisibleToInstantApp;
+            }
+            // request for application; if no components have been explicitly exposed, filter
+            return !ps.pkg.visibleToInstantApps;
+        }
+        if (ps.getInstantApp(userId)) {
+            // caller can see all components of all instant applications, don't filter
+            if (canAccessInstantApps(callingUid)) {
+                return false;
+            }
+            // request for a specific instant application component, filter
+            if (component != null) {
+                return true;
+            }
+            // request for an instant application; if the caller hasn't been granted access, filter
+            return !mInstantAppRegistry.isInstantAccessGranted(
+                    userId, UserHandle.getAppId(callingUid), ps.appId);
+        }
+        return false;
+    }
+
+    /**
+     * @see #filterAppAccessLPr(PackageSetting, int, ComponentName, boolean, int)
+     */
+    private boolean filterAppAccessLPr(@NonNull PackageSetting ps, int callingUid, int userId) {
+        return filterAppAccessLPr(ps, callingUid, null, false, userId);
+    }
+
     private boolean filterSharedLibPackageLPr(@Nullable PackageSetting ps, int uid, int userId,
             int flags) {
         // Callers can access only the libs they depend on, otherwise they need to explicitly
@@ -3869,6 +3954,9 @@
             if (filterSharedLibPackageLPr(ps, uid, userId, flags)) {
                 return null;
             }
+            if (filterAppAccessLPr(ps, uid, userId)) {
+                return null;
+            }
             if (ps.pkg == null) {
                 final PackageInfo pInfo = generatePackageInfo(ps, flags, userId);
                 if (pInfo != null) {
@@ -3910,6 +3998,9 @@
                 if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
                     return null;
                 }
+                if (filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) {
+                    return null;
+                }
                 // Note: isEnabledLP() does not apply here - always return info
                 ApplicationInfo ai = PackageParser.generateApplicationInfo(
                         p, flags, ps.readUserState(userId), userId);
@@ -4209,15 +4300,15 @@
      */
     int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid) {
         return updateFlagsForResolve(flags, userId, intent, callingUid,
-                false /*includeInstantApps*/, false /*onlyExposedExplicitly*/);
+                false /*wantInstantApps*/, false /*onlyExposedExplicitly*/);
     }
     int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid,
-            boolean includeInstantApps) {
+            boolean wantInstantApps) {
         return updateFlagsForResolve(flags, userId, intent, callingUid,
-                includeInstantApps, false /*onlyExposedExplicitly*/);
+                wantInstantApps, false /*onlyExposedExplicitly*/);
     }
     int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid,
-            boolean includeInstantApps, boolean onlyExposedExplicitly) {
+            boolean wantInstantApps, boolean onlyExposedExplicitly) {
         // Safe mode means we shouldn't match any third-party components
         if (mSafeMode) {
             flags |= PackageManager.MATCH_SYSTEM_ONLY;
@@ -4230,18 +4321,11 @@
             flags |= PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY;
             flags |= PackageManager.MATCH_INSTANT;
         } else {
-            // Otherwise, prevent leaking ephemeral components
-            final boolean isSpecialProcess =
-                    callingUid == Process.SYSTEM_UID
-                    || callingUid == Process.SHELL_UID
-                    || callingUid == 0;
             final boolean allowMatchInstant =
-                    (includeInstantApps
+                    (wantInstantApps
                             && Intent.ACTION_VIEW.equals(intent.getAction())
                             && hasWebURI(intent))
-                    || isSpecialProcess
-                    || mContext.checkCallingOrSelfPermission(
-                            android.Manifest.permission.ACCESS_INSTANT_APPS) == PERMISSION_GRANTED;
+                    || canAccessInstantApps(callingUid);
             flags &= ~(PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY
                     | PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY);
             if (!allowMatchInstant) {
@@ -4272,8 +4356,9 @@
     @Override
     public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForComponent(flags, userId, component);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get activity info");
         synchronized (mPackages) {
             PackageParser.Activity a = mActivities.mActivities.get(component);
@@ -4282,6 +4367,11 @@
             if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
+                final boolean visibleToInstantApp =
+                        (a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
+                if (filterAppAccessLPr(ps, callingUid, component, visibleToInstantApp, userId)) {
+                    return null;
+                }
                 return generateActivityInfo(a, flags, ps.readUserState(userId), userId);
             }
             if (mResolveComponentName.equals(component)) {
@@ -4334,7 +4424,8 @@
     }
 
     @Override
-    public ParceledListSlice<SharedLibraryInfo> getSharedLibraries(int flags, int userId) {
+    public ParceledListSlice<SharedLibraryInfo> getSharedLibraries(String packageName,
+            int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         Preconditions.checkArgumentNonnegative(userId, "userId must be >= 0");
 
@@ -4345,8 +4436,9 @@
                         == PERMISSION_GRANTED
                 || mContext.checkCallingOrSelfPermission(DELETE_PACKAGES)
                         == PERMISSION_GRANTED
-                || mContext.checkCallingOrSelfPermission(REQUEST_INSTALL_PACKAGES)
-                        == PERMISSION_GRANTED
+                || canRequestPackageInstallsInternal(packageName,
+                        PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId,
+                        false  /* throwIfPermNotDeclared*/)
                 || mContext.checkCallingOrSelfPermission(REQUEST_DELETE_PACKAGES)
                         == PERMISSION_GRANTED;
 
@@ -4369,7 +4461,8 @@
                     final long identity = Binder.clearCallingIdentity();
                     try {
                         PackageInfo packageInfo = getPackageInfoVersioned(
-                                libInfo.getDeclaringPackage(), flags, userId);
+                                libInfo.getDeclaringPackage(), flags
+                                        | PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId);
                         if (packageInfo == null) {
                             continue;
                         }
@@ -4443,8 +4536,9 @@
     @Override
     public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForComponent(flags, userId, component);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get service info");
         synchronized (mPackages) {
             PackageParser.Service s = mServices.mServices.get(component);
@@ -4453,6 +4547,11 @@
             if (s != null && mSettings.isEnabledAndMatchLPr(s.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
+                final boolean visibleToInstantApp =
+                        (s.info.flags & ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
+                if (filterAppAccessLPr(ps, callingUid, component, visibleToInstantApp, userId)) {
+                    return null;
+                }
                 ServiceInfo si = PackageParser.generateServiceInfo(s, flags,
                         ps.readUserState(userId), userId);
                 if (si != null) {
@@ -4467,8 +4566,9 @@
     @Override
     public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForComponent(flags, userId, component);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get provider info");
         synchronized (mPackages) {
             PackageParser.Provider p = mProviders.mProviders.get(component);
@@ -4477,6 +4577,11 @@
             if (p != null && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
+                final boolean visibleToInstantApp =
+                        (p.info.flags & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
+                if (filterAppAccessLPr(ps, callingUid, component, visibleToInstantApp, userId)) {
+                    return null;
+                }
                 ProviderInfo pi = PackageParser.generateProviderInfo(p, flags,
                         ps.readUserState(userId), userId);
                 if (pi != null) {
@@ -6489,18 +6594,22 @@
                 }
             } else {
                 final PackageParser.Package pkg = mPackages.get(pkgName);
+                result = null;
                 if (pkg != null) {
-                    return applyPostResolutionFilter(filterIfNotSystemUser(
+                    result = filterIfNotSystemUser(
                             mActivities.queryIntentForPackage(
                                     intent, resolvedType, flags, pkg.activities, userId),
-                            userId), instantAppPkgName);
-                } else {
+                            userId);
+                }
+                if (result == null || result.size() == 0) {
                     // the caller wants to resolve for a particular package; however, there
                     // were no installed results, so, try to find an ephemeral result
                     addEphemeral = !ephemeralDisabled
                             && isInstantAppAllowed(
                                     intent, null /*result*/, userId, true /*skipPackageCheck*/);
-                    result = new ArrayList<ResolveInfo>();
+                    if (result == null) {
+                        result = new ArrayList<>();
+                    }
                 }
             }
         }
@@ -9268,6 +9377,9 @@
         }
         if (p != null) {
             usesLibraryFiles.addAll(p.getAllCodePaths());
+            if (p.usesLibraryFiles != null) {
+                Collections.addAll(usesLibraryFiles, p.usesLibraryFiles);
+            }
         }
     }
 
@@ -17414,17 +17526,24 @@
                 }
             }
 
-            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
-            // Do not run PackageDexOptimizer through the local performDexOpt
-            // method because `pkg` may not be in `mPackages` yet.
-            //
-            // Also, don't fail application installs if the dexopt step fails.
-            mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
-                    null /* instructionSets */, false /* checkProfiles */,
-                    getCompilerFilterForReason(REASON_INSTALL),
-                    getOrCreateCompilerPackageStats(pkg),
-                    mDexManager.isUsedByOtherApps(pkg.packageName));
-            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+            // dexopt can take some time to complete, so, for instant apps, we skip this
+            // step during installation. Instead, we'll take extra time the first time the
+            // instant app starts. It's preferred to do it this way to provide continuous
+            // progress to the user instead of mysteriously blocking somewhere in the
+            // middle of running an instant app.
+            if (!instantApp) {
+                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+                // Do not run PackageDexOptimizer through the local performDexOpt
+                // method because `pkg` may not be in `mPackages` yet.
+                //
+                // Also, don't fail application installs if the dexopt step fails.
+                mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
+                        null /* instructionSets */, false /* checkProfiles */,
+                        getCompilerFilterForReason(REASON_INSTALL),
+                        getOrCreateCompilerPackageStats(pkg),
+                        mDexManager.isUsedByOtherApps(pkg.packageName));
+                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+            }
 
             // Notify BackgroundDexOptService that the package has been changed.
             // If this is an update of a package which used to fail to compile,
@@ -17714,14 +17833,12 @@
                 Integer.MAX_VALUE, "versionCode must be >= -1");
 
         final String packageName = versionedPackage.getPackageName();
-        // TODO: We will change version code to long, so in the new API it is long
-        final int versionCode = (int) versionedPackage.getVersionCode();
+        final int versionCode = versionedPackage.getVersionCode();
         final String internalPackageName;
         synchronized (mPackages) {
             // Normalize package name to handle renamed packages and static libs
             internalPackageName = resolveInternalPackageNameLPr(versionedPackage.getPackageName(),
-                    // TODO: We will change version code to long, so in the new API it is long
-                    (int) versionedPackage.getVersionCode());
+                    versionedPackage.getVersionCode());
         }
 
         final int uid = Binder.getCallingUid();
@@ -17863,8 +17980,7 @@
                     libEntry.info.getVersion()) < 0) {
                 continue;
             }
-            // TODO: We will change version code to long, so in the new API it is long
-            final int libVersionCode = (int) libEntry.info.getDeclaringPackage().getVersionCode();
+            final int libVersionCode = libEntry.info.getDeclaringPackage().getVersionCode();
             if (versionCode != PackageManager.VERSION_CODE_HIGHEST) {
                 if (libVersionCode == versionCode) {
                     return libEntry.apk;
@@ -23838,6 +23954,11 @@
                 return getUidTargetSdkVersionLockedLPr(uid);
             }
         }
+
+        @Override
+        public boolean canAccessInstantApps(int callingUid) {
+            return PackageManagerService.this.canAccessInstantApps(callingUid);
+        }
     }
 
     @Override
@@ -23944,6 +24065,12 @@
 
     @Override
     public boolean canRequestPackageInstalls(String packageName, int userId) {
+        return canRequestPackageInstallsInternal(packageName, 0, userId,
+                true /* throwIfPermNotDeclared*/);
+    }
+
+    private boolean canRequestPackageInstallsInternal(String packageName, int flags, int userId,
+            boolean throwIfPermNotDeclared) {
         int callingUid = Binder.getCallingUid();
         int uid = getPackageUid(packageName, 0, userId);
         if (callingUid != uid && callingUid != Process.ROOT_UID
@@ -23951,18 +24078,23 @@
             throw new SecurityException(
                     "Caller uid " + callingUid + " does not own package " + packageName);
         }
-        ApplicationInfo info = getApplicationInfo(packageName, 0, userId);
+        ApplicationInfo info = getApplicationInfo(packageName, flags, userId);
         if (info == null) {
             return false;
         }
         if (info.targetSdkVersion < Build.VERSION_CODES.O) {
-            throw new UnsupportedOperationException(
-                    "Operation only supported on apps targeting Android O or higher");
+            return false;
         }
         String appOpPermission = Manifest.permission.REQUEST_INSTALL_PACKAGES;
         String[] packagesDeclaringPermission = getAppOpPermissionPackages(appOpPermission);
         if (!ArrayUtils.contains(packagesDeclaringPermission, packageName)) {
-            throw new SecurityException("Need to declare " + appOpPermission + " to call this api");
+            if (throwIfPermNotDeclared) {
+                throw new SecurityException("Need to declare " + appOpPermission
+                        + " to call this api");
+            } else {
+                Slog.e(TAG, "Need to declare " + appOpPermission + " to call this api");
+                return false;
+            }
         }
         if (sUserManager.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, userId)) {
             return false;
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index feeee3f..6d48a05 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1374,7 +1374,7 @@
                     case Icon.TYPE_ADAPTIVE_BITMAP: {
                         bitmap = icon.getBitmap(); // Don't recycle in this case.
                         maxIconDimension *= (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
-
+                        break;
                     }
                     default:
                         // This shouldn't happen because we've already validated the icon, but
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 30c4009..b115422 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -3684,6 +3684,11 @@
         }
 
         @Override
+        public int[] getUserIds() {
+            return UserManagerService.this.getUserIds();
+        }
+
+        @Override
         public boolean isUserUnlockingOrUnlocked(int userId) {
             synchronized (mUserStates) {
                 int state = mUserStates.get(userId, -1);
diff --git a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
index 82dd9ac..7a35bf7 100644
--- a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
+++ b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
@@ -177,7 +177,7 @@
             UserInfo info = users.get(i);
             List<UsageStats> stats =
                     mUsageStats.queryUsageStatsForUser(info.id, UsageStatsManager.INTERVAL_BEST,
-                            oneYearAgo, timeNow);
+                            oneYearAgo, timeNow, /*obfuscateInstantApps=*/ false);
             if (stats == null) {
                 continue;
             }
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 8e06a51..e12dc1d 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -795,6 +795,10 @@
             // coalesce refresh messages.
             mHandler.removeMessages(MSG_KEYGUARD_SHOWING_CHANGED);
             mHandler.sendEmptyMessage(MSG_KEYGUARD_SHOWING_CHANGED);
+
+            // Make sure handler processes the message before returning, such that isDeviceLocked
+            // after this call will retrieve the correct value.
+            mHandler.runWithScissors(() -> {}, 0);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index fb7ccc7..4044fdb 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -368,7 +368,7 @@
 
             // There is an active service, update it if needed
             updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
-                    mCurrentVrService.getUserId(), null);
+                    mCurrentVrService.getUserId(), mCurrentVrModeComponent);
         }
     }
 
@@ -675,7 +675,7 @@
      * @param enabled new state for VR mode.
      * @param component new component to be bound as a VR listener.
      * @param userId user owning the component to be bound.
-     * @param calling the component currently using VR mode, or null to leave unchanged.
+     * @param calling the component currently using VR mode.
      *
      * @return {@code true} if the component/user combination specified is valid.
      */
diff --git a/services/core/java/com/android/server/wm/AlertWindowNotification.java b/services/core/java/com/android/server/wm/AlertWindowNotification.java
index 7ed3eac..50b1520 100644
--- a/services/core/java/com/android/server/wm/AlertWindowNotification.java
+++ b/services/core/java/com/android/server/wm/AlertWindowNotification.java
@@ -16,15 +16,14 @@
 
 package com.android.server.wm;
 
-import static android.app.NotificationManager.IMPORTANCE_MIN;
 import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
 import static android.content.Context.NOTIFICATION_SERVICE;
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.provider.Settings.ACTION_MANAGE_OVERLAY_PERMISSION;
+import static com.android.internal.notification.SystemNotificationChannels.ALERT_WINDOW;
 
 import android.app.Notification;
-import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -41,7 +40,7 @@
 
 /** Displays an ongoing notification for a process displaying an alert window */
 class AlertWindowNotification {
-    private static final String CHANNEL_PREFIX = "com.android.server.wm.AlertWindowNotification - ";
+    private static final String TAG_PREFIX = "com.android.server.wm.AlertWindowNotification: ";
     private static final int NOTIFICATION_ID = 0;
 
     private static int sNextRequestCode = 0;
@@ -58,7 +57,7 @@
         mPackageName = packageName;
         mNotificationManager =
                 (NotificationManager) mService.mContext.getSystemService(NOTIFICATION_SERVICE);
-        mNotificationTag = CHANNEL_PREFIX + mPackageName;
+        mNotificationTag = TAG_PREFIX + mPackageName;
         mRequestCode = sNextRequestCode++;
         mIconUtilities = new IconUtilities(mService.mContext);
     }
@@ -100,11 +99,9 @@
         final String appName = (aInfo != null)
                 ? pm.getApplicationLabel(aInfo).toString() : mPackageName;
 
-        createNotificationChannelIfNeeded(context, appName);
-
         final String message = context.getString(R.string.alert_windows_notification_message,
                 appName);
-        final Notification.Builder builder = new Notification.Builder(context, mNotificationTag)
+        final Notification.Builder builder = new Notification.Builder(context, ALERT_WINDOW)
                 .setOngoing(true)
                 .setContentTitle(
                         context.getString(R.string.alert_windows_notification_title, appName))
@@ -134,20 +131,6 @@
         return PendingIntent.getActivity(context, mRequestCode, intent, FLAG_CANCEL_CURRENT);
     }
 
-    private void createNotificationChannelIfNeeded(Context context, String appName) {
-        if (mNotificationManager.getNotificationChannel(mNotificationTag) != null) {
-            return;
-        }
-        final String nameChannel =
-                context.getString(R.string.alert_windows_notification_channel_name, appName);
-        final NotificationChannel channel =
-                new NotificationChannel(mNotificationTag, nameChannel, IMPORTANCE_MIN);
-        channel.enableLights(false);
-        channel.enableVibration(false);
-        mNotificationManager.createNotificationChannel(channel);
-    }
-
-
     private ApplicationInfo getApplicationInfo(PackageManager pm, String packageName) {
         try {
             return pm.getApplicationInfo(packageName, 0);
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 16edd35..65e3ec0 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -411,7 +411,9 @@
         }
 
         if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + mAppToken
-                + ": reportedVisible=" + mAppToken.reportedVisible);
+                + ": reportedVisible=" + mAppToken.reportedVisible
+                + " okToDisplay=" + mService.okToDisplay()
+                + " startingDisplayed=" + mAppToken.startingDisplayed);
 
         transformation.clear();
 
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index b5e194b..c982f08 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -19,6 +19,7 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -98,18 +99,27 @@
     private final Runnable mRemoveStartingWindow = () -> {
         StartingSurface surface = null;
         synchronized (mWindowMap) {
+            if (mContainer == null) {
+                if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "mContainer was null while trying to"
+                        + " remove starting window");
+                return;
+            }
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting " + mContainer
                     + ": startingWindow=" + mContainer.startingWindow
                     + " startingView=" + mContainer.startingSurface);
-            if (mContainer == null) {
-                return;
-            }
             if (mContainer.startingWindow != null) {
                 surface = mContainer.startingSurface;
                 mContainer.startingData = null;
                 mContainer.startingSurface = null;
                 mContainer.startingWindow = null;
                 mContainer.startingDisplayed = false;
+                if (surface == null && DEBUG_STARTING_WINDOW) {
+                    Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
+                            + "remove");
+                }
+            } else if (DEBUG_STARTING_WINDOW) {
+                Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
+                        + mContainer);
             }
         }
         if (surface != null) {
@@ -127,6 +137,8 @@
 
         synchronized (mWindowMap) {
             if (mContainer == null) {
+                if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "mContainer was null while trying to"
+                        + " add starting window");
                 return;
             }
             startingData = mContainer.startingData;
@@ -135,6 +147,8 @@
 
         if (startingData == null) {
             // Animation has been canceled... do nothing.
+            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "startingData was nulled out before handling"
+                    + " mAddStartingWindow: " + mContainer);
             return;
         }
 
@@ -174,6 +188,8 @@
             if (abort) {
                 surface.remove();
             }
+        } else if (DEBUG_STARTING_WINDOW) {
+            Slog.v(TAG_WM, "Surface returned was null: " + mContainer);
         }
     };
 
@@ -447,10 +463,12 @@
     public boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
             CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
             IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
-            boolean allowTaskSnapshot) {
+            boolean allowTaskSnapshot, boolean activityCreated) {
         synchronized(mWindowMap) {
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "setAppStartingWindow: token=" + mToken
-                    + " pkg=" + pkg + " transferFrom=" + transferFrom);
+                    + " pkg=" + pkg + " transferFrom=" + transferFrom + " newTask=" + newTask
+                    + " taskSwitch=" + taskSwitch + " processRunning=" + processRunning
+                    + " allowTaskSnapshot=" + allowTaskSnapshot);
 
             if (mContainer == null) {
                 Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + mToken);
@@ -475,7 +493,7 @@
             }
 
             final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
-                    allowTaskSnapshot);
+                    allowTaskSnapshot, activityCreated);
 
             if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
                 return createSnapshot();
@@ -536,7 +554,7 @@
                 return false;
             }
 
-            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating StartingData");
+            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
             mContainer.startingData = new SplashScreenStartingData(mService, pkg, theme,
                     compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
                     mContainer.getMergedOverrideConfiguration());
@@ -546,8 +564,9 @@
     }
 
     private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
-            boolean allowTaskSnapshot) {
-        if (newTask || !processRunning) {
+            boolean allowTaskSnapshot, boolean activityCreated) {
+        if (newTask || !processRunning
+                || (taskSwitch && !activityCreated)) {
             return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
         } else if (taskSwitch && allowTaskSnapshot) {
             return STARTING_WINDOW_TYPE_SNAPSHOT;
@@ -573,6 +592,7 @@
             return false;
         }
 
+        if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
         mContainer.startingData = new SnapshotStartingData(mService, snapshot);
         scheduleAddStartingWindow();
         return true;
@@ -582,6 +602,8 @@
         synchronized (mWindowMap) {
             if (mHandler.hasCallbacks(mRemoveStartingWindow)) {
                 // Already scheduled.
+                if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Trying to remove starting window but "
+                        + "already scheduled");
                 return;
             }
 
@@ -596,8 +618,7 @@
                 return;
             }
 
-            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1)
-                    + ": Schedule remove starting " + mContainer
+            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Schedule remove starting " + mContainer
                     + " startingWindow=" + mContainer.startingWindow);
             mHandler.post(mRemoveStartingWindow);
         }
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 96ea5e5..17db253 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -38,6 +38,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
@@ -53,7 +54,6 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Debug;
 import android.os.IBinder;
 import android.os.SystemClock;
@@ -155,6 +155,9 @@
     StartingSurface startingSurface;
     boolean startingDisplayed;
     boolean startingMoved;
+    // True if the hidden state of this token was forced to false due to a transferred starting
+    // window.
+    private boolean mHiddenSetFromTransferredStartingWindow;
     boolean firstWindowDrawn;
     private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
             new WindowState.UpdateReportedVisibilityResults();
@@ -185,7 +188,7 @@
     ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
     ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
 
-    private boolean mDisbalePreviewScreenshots;
+    private boolean mDisablePreviewScreenshots;
 
     Task mLastParent;
 
@@ -560,6 +563,9 @@
             // with it will be removed as soon as their animations are complete
             mAppAnimator.clearAnimation();
             mAppAnimator.animating = false;
+            if (stack != null) {
+                stack.mExitingAppTokens.remove(this);
+            }
             removeIfPossible();
         }
 
@@ -787,14 +793,22 @@
             if (getController() != null) {
                 getController().removeStartingWindow();
             }
-        } else if (mChildren.size() == 0 && startingData != null) {
+        } else if (mChildren.size() == 0) {
             // If this is the last window and we had requested a starting transition window,
             // well there is no point now.
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
             startingData = null;
+            if (mHiddenSetFromTransferredStartingWindow) {
+                // We set the hidden state to false for the token from a transferred starting window.
+                // We now reset it back to true since the starting window was the last window in the
+                // token.
+                hidden = true;
+            }
         } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
             // If this is the last window except for a starting transition window,
             // we need to get rid of the starting transition.
+            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
+                    + win);
             if (getController() != null) {
                 getController().removeStartingWindow();
             }
@@ -1168,6 +1182,7 @@
                     "Removing starting " + tStartingWindow + " from " + fromToken);
             fromToken.removeChild(tStartingWindow);
             fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
+            fromToken.mHiddenSetFromTransferredStartingWindow = false;
             addWindow(tStartingWindow);
 
             // Propagate other interesting state between the tokens. If the old token is displayed,
@@ -1183,6 +1198,7 @@
             if (!fromToken.hidden) {
                 hidden = false;
                 hiddenRequested = false;
+                mHiddenSetFromTransferredStartingWindow = true;
             }
             setClientHidden(fromToken.mClientHidden);
             fromToken.mAppAnimator.transferCurrentAnimation(
@@ -1359,7 +1375,7 @@
      *         windows in this app token where not considered drawn as of the last pass.
      */
     boolean updateDrawnWindowStates(WindowState w) {
-        if (DEBUG_STARTING_WINDOW && w == startingWindow) {
+        if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
             Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
                     + " allDrawn=" + allDrawn + " freezingScreen=" + mAppAnimator.freezingScreen);
         }
@@ -1541,7 +1557,7 @@
      * See {@link Activity#setDisablePreviewScreenshots}.
      */
     void setDisablePreviewScreenshots(boolean disable) {
-        mDisbalePreviewScreenshots = disable;
+        mDisablePreviewScreenshots = disable;
     }
 
     /**
@@ -1553,7 +1569,7 @@
      *         screenshot.
      */
     boolean shouldUseAppThemeSnapshot() {
-        return mDisbalePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
+        return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
                 true /* topToBottom */);
     }
 
@@ -1601,11 +1617,13 @@
                     pw.print(" mIsExiting="); pw.println(mIsExiting);
         }
         if (startingWindow != null || startingSurface != null
-                || startingDisplayed || startingMoved) {
+                || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
             pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
                     pw.print(" startingSurface="); pw.print(startingSurface);
                     pw.print(" startingDisplayed="); pw.print(startingDisplayed);
-                    pw.print(" startingMoved="); pw.println(startingMoved);
+                    pw.print(" startingMoved="); pw.print(startingMoved);
+                    pw.println(" mHiddenSetFromTransferredStartingWindow="
+                            + mHiddenSetFromTransferredStartingWindow);
         }
         if (!mFrozenBounds.isEmpty()) {
             pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 257f285..4941610 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -520,9 +520,16 @@
                 }
                 w.mLayoutNeeded = false;
                 w.prelayout();
+                final boolean firstLayout = !w.isLaidOut();
                 mService.mPolicy.layoutWindowLw(w, null);
                 w.mLayoutSeq = mService.mLayoutSeq;
 
+                // If this is the first layout, we need to initialize the last inset values as
+                // otherwise we'd immediately cause an unnecessary resize.
+                if (firstLayout) {
+                    w.updateLastInsetValues();
+                }
+
                 // Window frames may have changed. Update dim layer with the new bounds.
                 final Task task = w.getTask();
                 if (task != null) {
@@ -1892,6 +1899,11 @@
         return true;
     }
 
+    /** @return 'true' if removal of this display content is deferred due to active animation. */
+    boolean isRemovalDeferred() {
+        return mDeferredRemoval;
+    }
+
     boolean animateForIme(float interpolatedValue, float animationTarget,
             float dividerAnimationTarget) {
         boolean updated = false;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index be3558b..233e75b 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -181,7 +181,12 @@
 
         final int size = mChildren.size();
         for (int i = 0; i < size; ++i) {
-            displaysInFocusOrder.put(i, mChildren.get(i).getDisplayId());
+            final DisplayContent displayContent = mChildren.get(i);
+            if (displayContent.isRemovalDeferred()) {
+                // Don't report displays that are going to be removed soon.
+                continue;
+            }
+            displaysInFocusOrder.put(i, displayContent.getDisplayId());
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 0a999e6..27661e2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -92,6 +92,12 @@
 
     private TaskDescription mTaskDescription;
 
+    // If set to true, the task will report that it is not in the floating
+    // state regardless of it's stack affilation. As the floating state drives
+    // production of content insets this can be used to preserve them across
+    // stack moves and we in fact do so when moving from full screen to pinned.
+    private boolean mPreserveNonFloatingState = false;
+
     Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
             Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
             boolean homeTask, TaskDescription taskDescription,
@@ -194,6 +200,16 @@
         EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "reParentTask");
         final DisplayContent prevDisplayContent = getDisplayContent();
 
+        // If we are moving from the fullscreen stack to the pinned stack
+        // then we want to preserve our insets so that there will not
+        // be a jump in the area covered by system decorations. We rely
+        // on the pinned animation to later unset this value.
+        if (stack.mStackId == PINNED_STACK_ID) {
+            mPreserveNonFloatingState = true;
+        } else {
+            mPreserveNonFloatingState = false;
+        }
+
         getParent().removeChild(this);
         stack.addTask(this, position, showForAllUsers(), moveParents);
 
@@ -593,7 +609,8 @@
      * we will have a jump at the end.
      */
     boolean isFloating() {
-        return StackId.tasksAreFloating(mStack.mStackId) && !mStack.isAnimatingBoundsToFullscreen();
+        return StackId.tasksAreFloating(mStack.mStackId)
+                && !mStack.isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState;
     }
 
     WindowState getTopVisibleAppMainWindow() {
@@ -675,6 +692,10 @@
         return toShortString();
     }
 
+    void clearPreserveNonFloatingState() {
+        mPreserveNonFloatingState = false;
+    }
+
     @Override
     public String toShortString() {
         return "Task=" + mTaskId;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 0287070..866bfc0 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -209,11 +209,12 @@
                     SystemClock.sleep(DELAY_MS);
                 }
                 synchronized (mLock) {
-                    if (!mWriteQueue.isEmpty()) {
+                    final boolean writeQueueEmpty = mWriteQueue.isEmpty();
+                    if (!writeQueueEmpty && !mPaused) {
                         continue;
                     }
                     try {
-                        mQueueIdling = true;
+                        mQueueIdling = writeQueueEmpty;
                         mLock.wait();
                         mQueueIdling = false;
                     } catch (InterruptedException e) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 2b9e800..3a116bb 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -39,6 +39,7 @@
 import static com.android.internal.policy.DecorView.getColorViewLeftInset;
 import static com.android.internal.policy.DecorView.getColorViewTopInset;
 import static com.android.internal.policy.DecorView.getNavigationBarRect;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
@@ -113,10 +114,9 @@
     private final Rect mStableInsets = new Rect();
     private final Rect mContentInsets = new Rect();
     private final Rect mFrame = new Rect();
-    private final TaskSnapshot mSnapshot;
+    private TaskSnapshot mSnapshot;
     private final CharSequence mTitle;
     private boolean mHasDrawn;
-    private boolean mReportNextDraw;
     private long mShownTime;
     private final Handler mHandler;
     private boolean mSizeMismatch;
@@ -233,10 +233,14 @@
             final long now = SystemClock.uptimeMillis();
             if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS) {
                 mHandler.postAtTime(this::remove, mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS);
+                if (DEBUG_STARTING_WINDOW) {
+                    Slog.v(TAG, "Defer removing snapshot surface in "  + (now - mShownTime) + "ms");
+                }
                 return;
             }
         }
         try {
+            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing snapshot surface");
             mSession.remove(mWindow);
         } catch (RemoteException e) {
             // Local call.
@@ -255,6 +259,8 @@
 
     private void drawSnapshot() {
         final GraphicBuffer buffer = mSnapshot.getSnapshot();
+        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Drawing snapshot surface sizeMismatch="
+                + mSizeMismatch);
         if (mSizeMismatch) {
             // The dimensions of the buffer and the window don't match, so attaching the buffer
             // will fail. Better create a child window with the exact dimensions and fill the parent
@@ -263,15 +269,14 @@
         } else {
             drawSizeMatchSnapshot(buffer);
         }
-        final boolean reportNextDraw;
         synchronized (mService.mWindowMap) {
             mShownTime = SystemClock.uptimeMillis();
             mHasDrawn = true;
-            reportNextDraw = mReportNextDraw;
         }
-        if (reportNextDraw) {
-            reportDrawn();
-        }
+        reportDrawn();
+
+        // In case window manager leaks us, make sure we don't retain the snapshot.
+        mSnapshot = null;
     }
 
     private void drawSizeMatchSnapshot(GraphicBuffer buffer) {
@@ -356,9 +361,6 @@
     }
 
     private void reportDrawn() {
-        synchronized (mService.mWindowMap) {
-            mReportNextDraw = false;
-        }
         try {
             mSession.finishDrawing(mWindow);
         } catch (RemoteException e) {
@@ -376,9 +378,6 @@
                     final TaskSnapshotSurface surface = (TaskSnapshotSurface) msg.obj;
                     synchronized (surface.mService.mWindowMap) {
                         hasDrawn = surface.mHasDrawn;
-                        if (!hasDrawn) {
-                            surface.mReportNextDraw = true;
-                        }
                     }
                     if (hasDrawn) {
                         surface.reportDrawn();
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index da7a9f0..9d48ce5 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -139,6 +139,8 @@
     // Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration().
     private final Rect mBoundsAfterRotation = new Rect();
 
+    Rect mPreAnimationBounds = new Rect();
+
     TaskStack(WindowManagerService service, int stackId) {
         mService = service;
         mStackId = stackId;
@@ -336,6 +338,8 @@
         } else {
             mBoundsAnimationSourceHintBounds.setEmpty();
         }
+
+        mPreAnimationBounds.set(mBounds);
     }
 
     /**
@@ -1530,10 +1534,17 @@
         // Hold the lock since this is called from the BoundsAnimator running on the UiThread
         synchronized (mService.mWindowMap) {
             mBoundsAnimating = false;
+            for (int i = 0; i < mChildren.size(); i++) {
+                final Task t = mChildren.get(i);
+                t.clearPreserveNonFloatingState();
+            }
             mService.requestTraversal();
         }
 
         if (mStackId == PINNED_STACK_ID) {
+            // Update to the final bounds if requested. This is done here instead of in the bounds
+            // animator to allow us to coordinate this after we notify the PiP mode changed
+
             final PinnedStackWindowController controller =
                     (PinnedStackWindowController) getController();
             if (schedulePipModeChangedCallback && controller != null) {
@@ -1543,8 +1554,6 @@
                         mBoundsAnimationTarget);
             }
 
-            // Update to the final bounds if requested. This is done here instead of in the bounds
-            // animator to allow us to coordinate this after we notify the PiP mode changed
             if (finalStackSize != null) {
                 setPinnedStackSize(finalStackSize, null);
             }
@@ -1584,8 +1593,12 @@
         return mBoundsAnimating;
     }
 
+    public boolean lastAnimatingBoundsWasToFullscreen() {
+        return mBoundsAnimatingToFullscreen;
+    }
+
     public boolean isAnimatingBoundsToFullscreen() {
-        return mBoundsAnimating && mBoundsAnimatingToFullscreen;
+        return isAnimatingBounds() && lastAnimatingBoundsWasToFullscreen();
     }
 
     public boolean pinnedStackResizeDisallowed() {
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index d64dc0e..d85dd0c 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -52,6 +52,7 @@
 
     /** Is any window animating? */
     private boolean mAnimating;
+    private boolean mLastAnimating;
 
     /** Is any app window animating? */
     boolean mAppWindowAnimating;
@@ -158,7 +159,6 @@
      */
     private void animate(long frameTimeNs) {
         boolean transactionOpen = false;
-        boolean wasAnimating = false;
         try {
             synchronized (mService.mWindowMap) {
                 if (!mInitialized) {
@@ -167,8 +167,7 @@
 
                 mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
                 mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
-                wasAnimating = mAnimating;
-                setAnimating(false);
+                mAnimating = false;
                 mAppWindowAnimating = false;
                 if (DEBUG_WINDOW_TRACE) {
                     Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
@@ -269,25 +268,22 @@
                 mWindowPlacerLocked.requestTraversal();
             }
 
-            if (mAnimating && !wasAnimating) {
+            if (mAnimating && !mLastAnimating) {
 
                 // Usually app transitions but quite a load onto the system already (with all the
                 // things happening in app), so pause task snapshot persisting to not increase the
                 // load.
                 mService.mTaskSnapshotController.setPersisterPaused(true);
-                if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
-                    Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
-                }
+                Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
             }
-
-            if (!mAnimating && wasAnimating) {
+            if (!mAnimating && mLastAnimating) {
                 mWindowPlacerLocked.requestTraversal();
                 mService.mTaskSnapshotController.setPersisterPaused(false);
-                if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
-                    Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
-                }
+                Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
             }
 
+            mLastAnimating = mAnimating;
+
             if (mRemoveReplacedWindows) {
                 mService.mRoot.removeReplacedWindows();
                 mRemoveReplacedWindows = false;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 84ba139..6d3e0ed 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -16,6 +16,11 @@
 
 package com.android.server.wm;
 
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.res.Configuration.EMPTY;
+
 import android.annotation.CallSuper;
 import android.content.res.Configuration;
 import android.util.Pools;
@@ -27,11 +32,6 @@
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.content.res.Configuration.EMPTY;
-
 /**
  * Defines common functionality for classes that can hold windows directly or through their
  * children in a hierarchy form.
@@ -52,7 +52,7 @@
 
     // List of children for this window container. List is in z-order as the children appear on
     // screen with the top-most window container at the tail of the list.
-    protected final LinkedList<E> mChildren = new LinkedList();
+    protected final WindowList<E> mChildren = new WindowList<E>();
 
     /** Contains override configuration settings applied to this window container. */
     private Configuration mOverrideConfiguration = new Configuration();
@@ -258,7 +258,7 @@
             case POSITION_TOP:
                 if (mChildren.peekLast() != child) {
                     mChildren.remove(child);
-                    mChildren.addLast(child);
+                    mChildren.add(child);
                 }
                 if (includingParents && getParent() != null) {
                     getParent().positionChildAt(POSITION_TOP, this /* child */,
@@ -649,45 +649,50 @@
         }
 
         if (mParent != null && mParent == other.mParent) {
-            final LinkedList<WindowContainer> list = mParent.mChildren;
+            final WindowList<WindowContainer> list = mParent.mChildren;
             return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
         }
 
         final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
         final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
-        getParents(thisParentChain);
-        other.getParents(otherParentChain);
+        try {
+            getParents(thisParentChain);
+            other.getParents(otherParentChain);
 
-        // Find the common ancestor of both containers.
-        WindowContainer commonAncestor = null;
-        WindowContainer thisTop = thisParentChain.peekLast();
-        WindowContainer otherTop = otherParentChain.peekLast();
-        while (thisTop != null && otherTop != null && thisTop == otherTop) {
-            commonAncestor = thisParentChain.removeLast();
-            otherParentChain.removeLast();
-            thisTop = thisParentChain.peekLast();
-            otherTop = otherParentChain.peekLast();
+            // Find the common ancestor of both containers.
+            WindowContainer commonAncestor = null;
+            WindowContainer thisTop = thisParentChain.peekLast();
+            WindowContainer otherTop = otherParentChain.peekLast();
+            while (thisTop != null && otherTop != null && thisTop == otherTop) {
+                commonAncestor = thisParentChain.removeLast();
+                otherParentChain.removeLast();
+                thisTop = thisParentChain.peekLast();
+                otherTop = otherParentChain.peekLast();
+            }
+
+            // Containers don't belong to the same hierarchy???
+            if (commonAncestor == null) {
+                throw new IllegalArgumentException("No in the same hierarchy this="
+                        + thisParentChain + " other=" + otherParentChain);
+            }
+
+            // Children are always considered greater than their parents, so if one of the containers
+            // we are comparing it the parent of the other then whichever is the child is greater.
+            if (commonAncestor == this) {
+                return -1;
+            } else if (commonAncestor == other) {
+                return 1;
+            }
+
+            // The position of the first non-common ancestor in the common ancestor list determines
+            // which is greater the which.
+            final WindowList<WindowContainer> list = commonAncestor.mChildren;
+            return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
+                    ? 1 : -1;
+        } finally {
+            mTmpChain1.clear();
+            mTmpChain2.clear();
         }
-
-        // Containers don't belong to the same hierarchy???
-        if (commonAncestor == null) {
-            throw new IllegalArgumentException("No in the same hierarchy this="
-                    + thisParentChain + " other=" + otherParentChain);
-        }
-
-        // Children are always considered greater than their parents, so if one of the containers
-        // we are comparing it the parent of the other then whichever is the child is greater.
-        if (commonAncestor == this) {
-            return -1;
-        } else if (commonAncestor == other) {
-            return 1;
-        }
-
-        // The position of the first non-common ancestor in the common ancestor list determines
-        // which is greater the which.
-        final LinkedList<WindowContainer> list = commonAncestor.mChildren;
-        return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
-                ? 1 : -1;
     }
 
     private void getParents(LinkedList<WindowContainer> parents) {
diff --git a/services/core/java/com/android/server/wm/WindowList.java b/services/core/java/com/android/server/wm/WindowList.java
new file mode 100644
index 0000000..dfeba40
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WindowList.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import java.util.ArrayList;
+
+/**
+ * An {@link ArrayList} with extended functionality to be used as the children data structure in
+ * {@link WindowContainer}.
+ */
+class WindowList<E> extends ArrayList<E> {
+
+    void addFirst(E e) {
+        add(0, e);
+    }
+
+    E peekLast() {
+        return size() > 0 ? get(size() - 1) : null;
+    }
+
+    E peekFirst() {
+        return size() > 0 ? get(0) : null;
+    }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index 1b61fca..8279b51 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -51,7 +51,8 @@
     static final boolean DEBUG_APP_ORIENTATION = false;
     static final boolean DEBUG_CONFIGURATION = false;
     static final boolean DEBUG_APP_TRANSITIONS = false;
-    static final boolean DEBUG_STARTING_WINDOW = false;
+    static final boolean DEBUG_STARTING_WINDOW_VERBOSE = false;
+    static final boolean DEBUG_STARTING_WINDOW = DEBUG_STARTING_WINDOW_VERBOSE || true;
     static final boolean DEBUG_WALLPAPER = false;
     static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
     static final boolean DEBUG_DRAG = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 424f8a5..c8eb98c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1521,7 +1521,7 @@
         // Try using the target SDK of the root window
         if (attachedWindow != null) {
             return attachedWindow.mAppToken != null
-                    && attachedWindow.mAppToken.mTargetSdk > Build.VERSION_CODES.N_MR1;
+                    && attachedWindow.mAppToken.mTargetSdk >= Build.VERSION_CODES.O;
         } else {
             // Otherwise, look at the package
             try {
@@ -1532,7 +1532,7 @@
                     throw new SecurityException("Package " + packageName + " not in UID "
                             + callingUid);
                 }
-                if (appInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1) {
+                if (appInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
                     return true;
                 }
             } catch (PackageManager.NameNotFoundException e) {
@@ -1685,6 +1685,10 @@
                 // re-factor.
                 atoken.firstWindowDrawn = false;
                 atoken.clearAllDrawn();
+                final TaskStack stack = atoken.getStack();
+                if (stack != null) {
+                    stack.mExitingAppTokens.remove(atoken);
+                }
             }
         }
 
@@ -2093,6 +2097,7 @@
             outFrame.set(win.mCompatFrame);
             outOverscanInsets.set(win.mOverscanInsets);
             outContentInsets.set(win.mContentInsets);
+            win.mLastRelayoutContentInsets.set(win.mContentInsets);
             outVisibleInsets.set(win.mVisibleInsets);
             outStableInsets.set(win.mStableInsets);
             outOutsets.set(win.mOutsets);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 25b6561..2ffa152 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -80,6 +80,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
@@ -138,6 +139,7 @@
 import com.android.server.input.InputWindowHandle;
 
 import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.LinkedList;
@@ -170,7 +172,7 @@
     final int mOwnerUid;
     /** The owner has {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} */
     final boolean mOwnerCanAddInternalSystemWindow;
-    final IWindowId mWindowId;
+    final WindowId mWindowId;
     WindowToken mToken;
     // The same object as mToken if this is an app window and null for non-app windows.
     AppWindowToken mAppToken;
@@ -208,7 +210,7 @@
     boolean mHidden;    // Used to determine if to show child windows.
     boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
     private boolean mDragResizing;
-    private boolean mDragResizingChangeReported;
+    private boolean mDragResizingChangeReported = true;
     private int mResizeMode;
 
     private RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks;
@@ -257,6 +259,16 @@
      */
     final Rect mContentInsets = new Rect();
     final Rect mLastContentInsets = new Rect();
+
+    /**
+     * The last content insets returned to the client in relayout. We use
+     * these in the bounds animation to ensure we only observe inset changes
+     * at the same time that a client resizes it's surface so that we may use
+     * the geometryAppliesWithResize synchronization mechanism to keep
+     * the contents in place.
+     */
+    final Rect mLastRelayoutContentInsets = new Rect();
+
     private boolean mContentInsetsChanged;
 
     /**
@@ -577,20 +589,7 @@
         mAppToken = mToken.asAppWindowToken();
         mOwnerUid = ownerId;
         mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
-        mWindowId = new IWindowId.Stub() {
-            @Override
-            public void registerFocusObserver(IWindowFocusObserver observer) {
-                WindowState.this.registerFocusObserver(observer);
-            }
-            @Override
-            public void unregisterFocusObserver(IWindowFocusObserver observer) {
-                WindowState.this.unregisterFocusObserver(observer);
-            }
-            @Override
-            public boolean isFocused() {
-                return WindowState.this.isFocused();
-            }
-        };
+        mWindowId = new WindowId(this);
         mAttrs.copyFrom(a);
         mViewVisibility = viewVisibility;
         mPolicy = mService.mPolicy;
@@ -1145,11 +1144,7 @@
                 return;
             }
 
-            mLastOverscanInsets.set(mOverscanInsets);
-            mLastContentInsets.set(mContentInsets);
-            mLastVisibleInsets.set(mVisibleInsets);
-            mLastStableInsets.set(mStableInsets);
-            mLastOutsets.set(mOutsets);
+            updateLastInsetValues();
             mService.makeWindowFreezingScreenIfNeededLocked(this);
 
             // If the orientation is changing, or we're starting or ending a drag resizing action,
@@ -1300,7 +1295,7 @@
      *         otherwise.
      */
     boolean wouldBeVisibleIfPolicyIgnored() {
-        return mHasSurface && mPolicyVisibility && !isParentWindowHidden()
+        return mHasSurface && !isParentWindowHidden()
                 && !mAnimatingExit && !mDestroying && (!mIsWallpaper || mWallpaperVisible);
     }
 
@@ -3791,7 +3786,7 @@
 
     private void logPerformShow(String prefix) {
         if (DEBUG_VISIBILITY
-                || (DEBUG_STARTING_WINDOW && mAttrs.type == TYPE_APPLICATION_STARTING)) {
+                || (DEBUG_STARTING_WINDOW_VERBOSE && mAttrs.type == TYPE_APPLICATION_STARTING)) {
             Slog.v(TAG, prefix + this
                     + ": mDrawState=" + mWinAnimator.drawStateToString()
                     + " readyForDisplay=" + isReadyForDisplay()
@@ -4394,6 +4389,24 @@
         return result;
     }
 
+    /**
+     * @return True if this window has been laid out at least once; false otherwise.
+     */
+    boolean isLaidOut() {
+        return mLayoutSeq != -1;
+    }
+
+    /**
+     * Updates the last inset values to the current ones.
+     */
+    void updateLastInsetValues() {
+        mLastOverscanInsets.set(mOverscanInsets);
+        mLastContentInsets.set(mContentInsets);
+        mLastVisibleInsets.set(mVisibleInsets);
+        mLastStableInsets.set(mStableInsets);
+        mLastOutsets.set(mOutsets);
+    }
+
     // TODO: Hack to work around the number of states AppWindowToken needs to access without having
     // access to its windows children. Need to investigate re-writing
     // {@link AppWindowToken#updateReportedVisibilityLocked} so this can be removed.
@@ -4411,6 +4424,40 @@
         }
     }
 
+    private static final class WindowId extends IWindowId.Stub {
+        private final WeakReference<WindowState> mOuter;
+
+        private WindowId(WindowState outer) {
+
+            // Use a weak reference for the outer class. This is important to prevent the following
+            // leak: Since we send this class to the client process, binder will keep it alive as
+            // long as the client keeps it alive. Now, if the window is removed, we need to clear
+            // out our reference so even though this class is kept alive we don't leak WindowState,
+            // which can keep a whole lot of classes alive.
+            mOuter = new WeakReference<>(outer);
+        }
+
+        @Override
+        public void registerFocusObserver(IWindowFocusObserver observer) {
+            final WindowState outer = mOuter.get();
+            if (outer != null) {
+                outer.registerFocusObserver(observer);
+            }
+        }
+        @Override
+        public void unregisterFocusObserver(IWindowFocusObserver observer) {
+            final WindowState outer = mOuter.get();
+            if (outer != null) {
+                outer.unregisterFocusObserver(observer);
+            }
+        }
+        @Override
+        public boolean isFocused() {
+            final WindowState outer = mOuter.get();
+            return outer != null && outer.isFocused();
+        }
+    }
+
     boolean usesRelativeZOrdering() {
         if (!isChildWindow()) {
             return false;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 6cb4ddc..d75afcf 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -30,6 +30,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
@@ -519,7 +520,7 @@
 
     // This must be called while inside a transaction.
     boolean commitFinishDrawingLocked() {
-        if (DEBUG_STARTING_WINDOW &&
+        if (DEBUG_STARTING_WINDOW_VERBOSE &&
                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
             Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState="
                     + drawStateToString());
@@ -968,10 +969,8 @@
                 tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
             }
 
-            //TODO (multidisplay): Magnification is supported only for the default display.
-            if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
-                MagnificationSpec spec = mService.mAccessibilityController
-                        .getMagnificationSpecForWindowLocked(mWin);
+            MagnificationSpec spec = getMagnificationSpec();
+            if (spec != null) {
                 applyMagnificationSpec(spec, tmpMatrix);
             }
 
@@ -1058,11 +1057,7 @@
                 TAG, "computeShownFrameLocked: " + this +
                 " not attached, mAlpha=" + mAlpha);
 
-        MagnificationSpec spec = null;
-        //TODO (multidisplay): Magnification is supported only for the default display.
-        if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
-            spec = mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin);
-        }
+        MagnificationSpec spec = getMagnificationSpec();
         if (spec != null) {
             final Rect frame = mWin.mFrame;
             final float tmpFloats[] = mService.mTmpFloats;
@@ -1099,6 +1094,14 @@
         }
     }
 
+    private MagnificationSpec getMagnificationSpec() {
+        //TODO (multidisplay): Magnification is supported only for the default display.
+        if (mService.mAccessibilityController != null && mWin.getDisplayId() == DEFAULT_DISPLAY) {
+            return mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin);
+        }
+        return null;
+    }
+
     /**
      * In some scenarios we use a screen space clip rect (so called, final clip rect)
      * to crop to stack bounds. Generally because it's easier to deal with while
@@ -1136,6 +1139,27 @@
         if (StackId.tasksAreFloating(stack.mStackId)) {
             w.expandForSurfaceInsets(finalClipRect);
         }
+
+        // We may be applying a magnification spec to all windows,
+        // simulating a transformation in screen space, in which case
+        // we need to transform all other screen space values...including
+        // the final crop. This is kind of messed up and we should look
+        // in to actually transforming screen-space via a parent-layer.
+        // b/38322835
+        MagnificationSpec spec = getMagnificationSpec();
+        if (spec != null && !spec.isNop()) {
+            Matrix transform = mWin.mTmpMatrix;
+            RectF finalCrop = mService.mTmpRectF;
+            transform.reset();
+            transform.postScale(spec.scale, spec.scale);
+            transform.postTranslate(-spec.offsetX, -spec.offsetY);
+            transform.mapRect(finalCrop);
+            finalClipRect.top = (int)finalCrop.top;
+            finalClipRect.left = (int)finalCrop.left;
+            finalClipRect.right = (int)finalClipRect.right;
+            finalClipRect.bottom = (int)finalClipRect.bottom;
+        }
+
         return true;
     }
 
@@ -1374,7 +1398,23 @@
             int posX = mTmpSize.left;
             int posY = mTmpSize.top;
             task.mStack.getDimBounds(mTmpStackBounds);
+
+            boolean allowStretching = false;
             task.mStack.getFinalAnimationSourceHintBounds(mTmpSourceBounds);
+            // If we don't have source bounds, we can attempt to use the content insets
+            // in the following scenario:
+            //    1. We have content insets.
+            //    2. We are not transitioning to full screen
+            // We have to be careful to check "lastAnimatingBoundsWasToFullscreen" rather than
+            // the mBoundsAnimating state, as we may have already left it and only be here
+            // because of the force-scale until resize state.
+            if (mTmpSourceBounds.isEmpty() && (mWin.mLastRelayoutContentInsets.width() > 0
+                    || mWin.mLastRelayoutContentInsets.height() > 0)
+                        && !task.mStack.lastAnimatingBoundsWasToFullscreen()) {
+                mTmpSourceBounds.set(task.mStack.mPreAnimationBounds);
+                mTmpSourceBounds.inset(mWin.mLastRelayoutContentInsets);
+                allowStretching = true;
+            }
             if (!mTmpSourceBounds.isEmpty()) {
                 // Get the final target stack bounds, if we are not animating, this is just the
                 // current stack bounds
@@ -1384,14 +1424,24 @@
                 // and source bounds
                 float finalWidth = mTmpAnimatingBounds.width();
                 float initialWidth = mTmpSourceBounds.width();
-                float t = (surfaceContentWidth - mTmpStackBounds.width())
+                float tw = (surfaceContentWidth - mTmpStackBounds.width())
                         / (surfaceContentWidth - mTmpAnimatingBounds.width());
-                mExtraHScale = (initialWidth + t * (finalWidth - initialWidth)) / initialWidth;
-                mExtraVScale = mExtraHScale;
+                float th = tw;
+                mExtraHScale = (initialWidth + tw * (finalWidth - initialWidth)) / initialWidth;
+                if (allowStretching) {
+                    float finalHeight = mTmpAnimatingBounds.height();
+                    float initialHeight = mTmpSourceBounds.height();
+                    th = (surfaceContentHeight - mTmpStackBounds.height())
+                        / (surfaceContentHeight - mTmpAnimatingBounds.height());
+                    mExtraVScale = (initialHeight + tw * (finalHeight - initialHeight))
+                            / initialHeight;
+                } else {
+                    mExtraVScale = mExtraHScale;
+                }
 
                 // Adjust the position to account for the inset bounds
-                posX -= (int) (t * mExtraHScale * mTmpSourceBounds.left);
-                posY -= (int) (t * mExtraVScale * mTmpSourceBounds.top);
+                posX -= (int) (tw * mExtraHScale * mTmpSourceBounds.left);
+                posY -= (int) (th * mExtraVScale * mTmpSourceBounds.top);
 
                 // Always clip to the stack bounds since the surface can be larger with the current
                 // scale
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index 267d2a6..0812783 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -99,7 +99,7 @@
         when(mMockContext.getPackageManager()).thenReturn(mPm);
 
         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
-        upgrade.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
+        upgrade.targetSdkVersion = Build.VERSION_CODES.O;
         try {
             when(mPm.getApplicationInfoAsUser(eq(pkg), anyInt(), anyInt())).thenReturn(legacy);
             when(mPm.getApplicationInfoAsUser(eq(pkg2), anyInt(), anyInt())).thenReturn(upgrade);
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index 0f8c815..2c9c114 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -119,7 +119,7 @@
         final ApplicationInfo legacy = new ApplicationInfo();
         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
         final ApplicationInfo upgrade = new ApplicationInfo();
-        upgrade.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
+        upgrade.targetSdkVersion = Build.VERSION_CODES.O;
         when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(legacy);
         when(mPm.getApplicationInfoAsUser(eq(UPDATED_PKG), anyInt(), anyInt())).thenReturn(upgrade);
         when(mPm.getPackageUidAsUser(eq(PKG), anyInt())).thenReturn(UID);
@@ -1232,6 +1232,15 @@
     }
 
     @Test
+    public void testBadgingForUserAll() throws Exception {
+        try {
+            mHelper.badgingEnabled(UserHandle.ALL);
+        } catch (Exception e) {
+            fail("just don't throw");
+        }
+    }
+
+    @Test
     public void testBadgingOverrideUserIsolation() throws Exception {
         Secure.putIntForUser(getContext().getContentResolver(),
                 Secure.NOTIFICATION_BADGING, 0,
diff --git a/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java
index ca77528..d9d06ae 100644
--- a/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java
@@ -30,6 +30,7 @@
 import android.os.FileUtils;
 import android.os.IProgressListener;
 import android.os.UserManager;
+import android.os.storage.StorageManager;
 import android.security.KeyStore;
 import android.test.AndroidTestCase;
 
@@ -82,7 +83,7 @@
         mActivityManager = mock(IActivityManager.class);
         mDevicePolicyManager = mock(DevicePolicyManager.class);
         mContext = new MockLockSettingsContext(getContext(), mUserManager, mNotificationManager,
-                mDevicePolicyManager);
+                mDevicePolicyManager, mock(StorageManager.class));
         mStorage = new LockSettingsStorageTestable(mContext,
                 new File(getContext().getFilesDir(), "locksettings"));
         File storageDir = mStorage.mStorageDir;
diff --git a/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java
index 4677904..f242b26 100644
--- a/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java
@@ -28,6 +28,7 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.os.FileUtils;
 import android.os.UserManager;
+import android.os.storage.StorageManager;
 import android.test.AndroidTestCase;
 
 import com.android.internal.widget.LockPatternUtils;
@@ -69,7 +70,8 @@
         when(mockUserManager.getProfileParent(eq(3))).thenReturn(new UserInfo(0, "name", 0));
 
         MockLockSettingsContext context = new MockLockSettingsContext(getContext(), mockUserManager,
-                mock(NotificationManager.class), mock(DevicePolicyManager.class));
+                mock(NotificationManager.class), mock(DevicePolicyManager.class),
+                mock(StorageManager.class));
         mStorage = new LockSettingsStorageTestable(context,
                 new File(getContext().getFilesDir(), "locksettings"));
         mStorage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() {
@@ -336,7 +338,7 @@
         assertArrayEquals(data, mStorage.readSyntheticPasswordState(10, 1234L, "state"));
         assertEquals(null, mStorage.readSyntheticPasswordState(0, 1234L, "state"));
 
-        mStorage.deleteSyntheticPasswordState(10, 1234L, "state", true);
+        mStorage.deleteSyntheticPasswordState(10, 1234L, "state");
         assertEquals(null, mStorage.readSyntheticPasswordState(10, 1234L, "state"));
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java b/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java
index 8bceed4..9dede3b 100644
--- a/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java
+++ b/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java
@@ -21,19 +21,23 @@
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.os.UserManager;
+import android.os.storage.StorageManager;
 
 public class MockLockSettingsContext extends ContextWrapper {
 
     private UserManager mUserManager;
     private NotificationManager mNotificationManager;
     private DevicePolicyManager mDevicePolicyManager;
+    private StorageManager mStorageManager;
 
     public MockLockSettingsContext(Context base, UserManager userManager,
-            NotificationManager notificationManager, DevicePolicyManager devicePolicyManager) {
+            NotificationManager notificationManager, DevicePolicyManager devicePolicyManager,
+            StorageManager storageManager) {
         super(base);
         mUserManager = userManager;
         mNotificationManager = notificationManager;
         mDevicePolicyManager = devicePolicyManager;
+        mStorageManager = storageManager;
     }
 
     @Override
@@ -44,6 +48,8 @@
             return mNotificationManager;
         } else if (DEVICE_POLICY_SERVICE.equals(name)) {
             return mDevicePolicyManager;
+        } else if (STORAGE_SERVICE.equals(name)) {
+            return mStorageManager;
         } else {
             throw new RuntimeException("System service not mocked: " + name);
         }
diff --git a/services/tests/servicestests/src/com/android/server/MockStorageManager.java b/services/tests/servicestests/src/com/android/server/MockStorageManager.java
index 17c8ec2..3a17718 100644
--- a/services/tests/servicestests/src/com/android/server/MockStorageManager.java
+++ b/services/tests/servicestests/src/com/android/server/MockStorageManager.java
@@ -500,4 +500,9 @@
         throw new UnsupportedOperationException();
     }
 
+    @Override
+    public void secdiscard(String path) throws RemoteException {
+        throw new UnsupportedOperationException();
+    }
+
 }
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java b/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java
index 8afe853..72820f1 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java
@@ -25,6 +25,9 @@
 import android.view.accessibility.IAccessibilityInteractionConnection;
 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
 
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -45,12 +48,13 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyObject;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
 import static org.mockito.MockitoAnnotations.initMocks;
 
 /**
@@ -63,15 +67,50 @@
     private static final int NON_ROOT_NODE_ID = 0xAAAA5555;
     private static final long INTERROGATING_TID = 0x1234FACE;
 
-    private static final AccessibilityAction[] ACTIONS_FROM_REPLACER =
-            {ACTION_CLICK, ACTION_EXPAND};
-    private static final AccessibilityAction[] A11Y_FOCUS_ACTIONS =
-            {ACTION_ACCESSIBILITY_FOCUS, ACTION_CLEAR_ACCESSIBILITY_FOCUS};
     // We expect both the replacer actions and a11y focus actions to appear
     private static final AccessibilityAction[] REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE =
             {ACTION_CLICK, ACTION_EXPAND, ACTION_ACCESSIBILITY_FOCUS,
                     ACTION_CLEAR_ACCESSIBILITY_FOCUS};
 
+    private static final Matcher<AccessibilityNodeInfo> HAS_NO_ACTIONS =
+            new BaseMatcher<AccessibilityNodeInfo>() {
+        @Override
+        public boolean matches(Object o) {
+            AccessibilityNodeInfo node = (AccessibilityNodeInfo) o;
+            if (!node.getActionList().isEmpty()) return false;
+            return (!node.isScrollable() && !node.isLongClickable() && !node.isClickable()
+                    && !node.isContextClickable() && !node.isDismissable() && !node.isFocusable());
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            description.appendText("Has no actions");
+        }
+    };
+
+    private static final Matcher<AccessibilityNodeInfo> HAS_EXPECTED_ACTIONS_ON_ROOT =
+            new BaseMatcher<AccessibilityNodeInfo>() {
+                @Override
+                public boolean matches(Object o) {
+                    AccessibilityNodeInfo node = (AccessibilityNodeInfo) o;
+                    List<AccessibilityAction> actions = node.getActionList();
+                    if ((actions.size() != 4) || !actions.contains(ACTION_CLICK)
+                            || !actions.contains(ACTION_EXPAND)
+                            || !actions.contains(ACTION_ACCESSIBILITY_FOCUS)) {
+                        return false;
+                    }
+                    return (!node.isScrollable() && !node.isLongClickable()
+                            && !node.isLongClickable() && node.isClickable()
+                            && !node.isContextClickable() && !node.isDismissable()
+                            && !node.isFocusable());
+                }
+
+                @Override
+                public void describeTo(Description description) {
+                    description.appendText("Has only 4 actions expected on root");
+                }
+            };
+
     @Mock IAccessibilityInteractionConnectionCallback mMockServiceCallback;
     @Mock IAccessibilityInteractionConnection mMockReplacerConnection;
 
@@ -118,9 +157,10 @@
                 eq(INTERACTION_ID));
         AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
         assertEquals(AccessibilityNodeInfo.ROOT_NODE_ID, infoSentToService.getSourceNodeId());
-        assertInfoHasExactlyTheseActions(infoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
+        assertThat(infoSentToService, HAS_EXPECTED_ACTIONS_ON_ROOT);
     }
 
+    @Test
     public void testCallbacks_singleNonrootNodeThenReplacer_returnsNodeWithNoActions()
             throws RemoteException {
         AccessibilityNodeInfo infoFromApp = AccessibilityNodeInfo.obtain();
@@ -136,9 +176,10 @@
                 eq(INTERACTION_ID));
         AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
         assertEquals(NON_ROOT_NODE_ID, infoSentToService.getSourceNodeId());
-        assertTrue(infoSentToService.getActionList().isEmpty());
+        assertThat(infoSentToService, HAS_NO_ACTIONS);
     }
 
+    @Test
     public void testCallbacks_replacerThenSingleRootNode_returnsNodeWithReplacedActions()
             throws RemoteException {
         mActionReplacingCallback.setFindAccessibilityNodeInfosResult(getReplacerNodes(),
@@ -154,9 +195,10 @@
                 eq(INTERACTION_ID));
         AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
         assertEquals(AccessibilityNodeInfo.ROOT_NODE_ID, infoSentToService.getSourceNodeId());
-        assertInfoHasExactlyTheseActions(infoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
+        assertThat(infoSentToService, HAS_EXPECTED_ACTIONS_ON_ROOT);
     }
 
+    @Test
     public void testCallbacks_multipleNodesThenReplacer_clearsActionsAndAddsSomeToRoot()
             throws RemoteException {
         mActionReplacingCallback
@@ -173,11 +215,11 @@
                 mInfoListCaptor.getValue(), AccessibilityNodeInfo.ROOT_NODE_ID);
         AccessibilityNodeInfo otherInfoSentToService = getNodeWithIdFromList(
                 mInfoListCaptor.getValue(), NON_ROOT_NODE_ID);
-        assertInfoHasExactlyTheseActions(
-                rootInfoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
-        assertTrue(otherInfoSentToService.getActionList().isEmpty());
+        assertThat(rootInfoSentToService, HAS_EXPECTED_ACTIONS_ON_ROOT);
+        assertThat(otherInfoSentToService, HAS_NO_ACTIONS);
     }
 
+    @Test
     public void testCallbacks_replacerThenMultipleNodes_clearsActionsAndAddsSomeToRoot()
             throws RemoteException {
         mActionReplacingCallback.setFindAccessibilityNodeInfosResult(getReplacerNodes(),
@@ -194,18 +236,18 @@
                 mInfoListCaptor.getValue(), AccessibilityNodeInfo.ROOT_NODE_ID);
         AccessibilityNodeInfo otherInfoSentToService = getNodeWithIdFromList(
                 mInfoListCaptor.getValue(), NON_ROOT_NODE_ID);
-        assertInfoHasExactlyTheseActions(
-                rootInfoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
-        assertTrue(otherInfoSentToService.getActionList().isEmpty());
+        assertThat(rootInfoSentToService, HAS_EXPECTED_ACTIONS_ON_ROOT);
+        assertThat(otherInfoSentToService, HAS_NO_ACTIONS);
     }
 
+    @Test
     public void testConstructor_actionReplacerThrowsException_passesDataToService()
             throws RemoteException {
         doThrow(RemoteException.class).when(mMockReplacerConnection)
                 .findAccessibilityNodeInfoByAccessibilityId(eq(AccessibilityNodeInfo.ROOT_NODE_ID),
-                        (Region) anyObject(), mInteractionIdCaptor.capture(),
-                        eq(mActionReplacingCallback), eq(0), eq(INTERROGATING_PID),
-                        eq(INTERROGATING_TID), (MagnificationSpec) anyObject(), eq(null));
+                        (Region) anyObject(), anyInt(), (ActionReplacingCallback) anyObject(),
+                        eq(0),  eq(INTERROGATING_PID), eq(INTERROGATING_TID),
+                        (MagnificationSpec) anyObject(), eq(null));
         ActionReplacingCallback actionReplacingCallback = new ActionReplacingCallback(
                 mMockServiceCallback, mMockReplacerConnection, INTERACTION_ID, INTERROGATING_PID,
                 INTERROGATING_TID);
@@ -214,16 +256,17 @@
         AccessibilityNodeInfo infoFromApp = AccessibilityNodeInfo.obtain();
         infoFromApp.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID, APP_WINDOW_ID);
         infoFromApp.addAction(ACTION_CONTEXT_CLICK);
+        infoFromApp.setContextClickable(true);
         actionReplacingCallback.setFindAccessibilityNodeInfoResult(infoFromApp, INTERACTION_ID);
 
         verify(mMockServiceCallback).setFindAccessibilityNodeInfoResult(mInfoCaptor.capture(),
                 eq(INTERACTION_ID));
         AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
         assertEquals(AccessibilityNodeInfo.ROOT_NODE_ID, infoSentToService.getSourceNodeId());
-        assertEquals(1, infoSentToService.getActionList().size());
-        assertEquals(ACTION_CONTEXT_CLICK, infoSentToService.getActionList().get(0));
+        assertThat(infoSentToService, HAS_NO_ACTIONS);
     }
 
+    @Test
     public void testSetPerformAccessibilityActionResult_actsAsPassThrough() throws RemoteException {
         mActionReplacingCallback.setPerformAccessibilityActionResult(true, INTERACTION_ID);
         verify(mMockServiceCallback).setPerformAccessibilityActionResult(true, INTERACTION_ID);
@@ -236,9 +279,9 @@
         AccessibilityNodeInfo root = AccessibilityNodeInfo.obtain();
         root.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID,
                 AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
-        for (AccessibilityAction action : ACTIONS_FROM_REPLACER) {
-            root.addAction(action);
-        }
+        root.addAction(ACTION_CLICK);
+        root.addAction(ACTION_EXPAND);
+        root.setClickable(true);
 
         // Second node should have no effect
         AccessibilityNodeInfo other = AccessibilityNodeInfo.obtain();
@@ -249,13 +292,6 @@
         return Arrays.asList(root, other);
     }
 
-    private void assertInfoHasExactlyTheseActions(
-            AccessibilityNodeInfo info, AccessibilityAction[] actions) {
-        List<AccessibilityAction> nodeActions = info.getActionList();
-        assertEquals(new HashSet<AccessibilityAction>(nodeActions),
-                new HashSet<AccessibilityAction>(Arrays.asList(actions)));
-    }
-
     private AccessibilityNodeInfo getNodeWithIdFromList(
             List<AccessibilityNodeInfo> infos, long id) {
         for (AccessibilityNodeInfo info : infos) {
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
index a8c39c4..6706969 100644
--- a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.pm.IPackageInstallObserver2;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
@@ -32,6 +33,7 @@
 import android.provider.Settings;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.test.mock.MockContentResolver;
 
 import com.android.internal.util.test.FakeSettingsProvider;
@@ -40,20 +42,20 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 import java.io.File;
 import java.util.ArrayList;
 
-@RunWith(JUnit4.class)
+@RunWith(AndroidJUnit4.class)
 @SmallTest
 public class PreloadAppsInstallerTest {
     private static final int TEST_DEMO_USER = 111;
 
-    private @Mock Context mContext;
+    private Context mContext;
     private @Mock IPackageManager mIpm;
     private MockContentResolver mContentResolver;
     private File mPreloadsAppsDirectory;
@@ -66,6 +68,7 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
+        mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
         mContentResolver = new MockContentResolver(mContext);
         mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
         when(mContext.getContentResolver()).thenReturn(mContentResolver);
@@ -89,7 +92,9 @@
 
     @After
     public void tearDown() {
-        FileUtils.deleteContentsAndDir(mPreloadsAppsDirectory);
+        if (mPreloadsAppsDirectory != null) {
+            FileUtils.deleteContentsAndDir(mPreloadsAppsDirectory);
+        }
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
index ce5b8cb..2e13d29 100644
--- a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
@@ -38,6 +38,7 @@
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
@@ -59,6 +60,7 @@
 import android.provider.Settings;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
 import android.test.mock.MockContentProvider;
 import android.test.mock.MockContentResolver;
 import android.util.ArrayMap;
@@ -72,9 +74,9 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.mockito.compat.ArgumentMatcher;
 
@@ -82,7 +84,7 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-@RunWith(JUnit4.class)
+@RunWith(AndroidJUnit4.class)
 @SmallTest
 public class RetailDemoModeServiceTest {
     private static final int TEST_DEMO_USER = 111;
@@ -90,7 +92,7 @@
     private static final String TEST_CAMERA_PKG = "test.cameraapp";
     private static final String TEST_PRELOADS_DIR_NAME = "test_preloads";
 
-    private @Mock Context mContext;
+    private Context mContext;
     private @Mock UserManager mUm;
     private @Mock PackageManager mPm;
     private @Mock IPackageManager mIpm;
@@ -113,12 +115,11 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        Context originalContext = InstrumentationRegistry.getContext();
-        when(mContext.getApplicationInfo()).thenReturn(originalContext.getApplicationInfo());
-        when(mContext.getResources()).thenReturn(originalContext.getResources());
+        mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
         when(mContext.getSystemServiceName(eq(JobScheduler.class))).thenReturn(
                 Context.JOB_SCHEDULER_SERVICE);
         when(mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE)).thenReturn(mJobScheduler);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUm);
         mContentResolver = new MockContentResolver(mContext);
         mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
         mContactsProvider = new MockContactsProvider(mContext);
@@ -129,12 +130,10 @@
         mTestPreloadsDir = new File(InstrumentationRegistry.getContext().getFilesDir(),
                 TEST_PRELOADS_DIR_NAME);
 
-        Settings.Global.putString(mContentResolver,
-                Settings.Global.RETAIL_DEMO_MODE_CONSTANTS, "");
-        Settings.Global.putInt(mContentResolver,
-                Settings.Global.DEVICE_PROVISIONED, 1);
-        Settings.Global.putInt(mContentResolver,
-                Settings.Global.DEVICE_DEMO_MODE, 1);
+        Settings.Global.putString(mContentResolver, Settings.Global.RETAIL_DEMO_MODE_CONSTANTS, "");
+        Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, 1);
+        Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_DEMO_MODE, 1);
+
         // Initialize RetailDemoModeService
         mInjector = new TestInjector();
         mService = new RetailDemoModeService(mInjector);
@@ -143,7 +142,9 @@
 
     @After
     public void tearDown() {
-        FileUtils.deleteContentsAndDir(mTestPreloadsDir);
+        if (mTestPreloadsDir != null) {
+            FileUtils.deleteContentsAndDir(mTestPreloadsDir);
+        }
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index dcbedb6..da3b9c9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -97,7 +97,8 @@
         final WindowTestUtils.TestAppWindowContainerController controller =
                 createAppWindowController();
         controller.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
-                android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true);
+                android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+                false);
         waitUntilHandlersIdle();
         final AppWindowToken atoken = controller.getAppWindowToken(mDisplayContent);
         assertHasStartingWindow(atoken);
@@ -113,11 +114,12 @@
         final WindowTestUtils.TestAppWindowContainerController controller2 =
                 createAppWindowController();
         controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
-                android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true);
+                android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+                false);
         waitUntilHandlersIdle();
         controller2.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(),
-                true, true, false, true);
+                true, true, false, true, false);
         waitUntilHandlersIdle();
         assertNoStartingWindow(controller1.getAppWindowToken(mDisplayContent));
         assertHasStartingWindow(controller2.getAppWindowToken(mDisplayContent));
@@ -134,10 +136,11 @@
             // Surprise, ...! Transfer window in the middle of the creation flow.
             controller2.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
                     android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(),
-                    true, true, false, true);
+                    true, true, false, true, false);
         });
         controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
-                android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true);
+                android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+                false);
         waitUntilHandlersIdle();
         assertNoStartingWindow(controller1.getAppWindowToken(mDisplayContent));
         assertHasStartingWindow(controller2.getAppWindowToken(mDisplayContent));
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index f9254ad..856e940 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -34,6 +34,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.util.SparseIntArray;
 
 import java.util.Arrays;
 import java.util.LinkedList;
@@ -239,7 +240,7 @@
     @Test
     @Ignore
     public void testFocusedWindowMultipleDisplays() throws Exception {
-        // Create a focusable window and check that focus is calcualted correctly
+        // Create a focusable window and check that focus is calculated correctly
         final WindowState window1 =
                 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
         assertEquals(window1, sWm.mRoot.computeFocusedWindow());
@@ -310,6 +311,24 @@
         assertEquals(afterStackCount - 1, mDisplayContent.getStaskPosById(PINNED_STACK_ID));
     }
 
+    /**
+     * Test that WM does not report displays to AM that are pending to be removed.
+     */
+    @Test
+    public void testDontReportDeferredRemoval() {
+        // Create a display and add an animating window to it.
+        final DisplayContent dc = createNewDisplay();
+        final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
+        window.mAnimatingExit = true;
+        // Request display removal, it should be deferred.
+        dc.removeIfPossible();
+        // Request ordered display ids from WM.
+        final SparseIntArray orderedDisplayIds = new SparseIntArray();
+        sWm.getDisplaysInFocusOrder(orderedDisplayIds);
+        // Make sure that display that is marked for removal is not reported.
+        assertEquals(-1, orderedDisplayIds.indexOfValue(dc.getDisplayId()));
+    }
+
     private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
                              int expectedBaseHeight, int expectedBaseDensity) {
         assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index d9349ed..b83532c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -115,11 +115,11 @@
         }
 
         WindowState getFirstChild() {
-            return mChildren.getFirst();
+            return mChildren.peekFirst();
         }
 
         WindowState getLastChild() {
-            return mChildren.getLast();
+            return mChildren.peekLast();
         }
 
         int positionInParent() {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 4ba457d..0de3c7c 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -39,6 +39,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.UserInfo;
@@ -80,6 +81,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.LocalServices;
 import com.android.server.SystemService;
 
 import java.io.File;
@@ -137,6 +139,7 @@
     AppOpsManager mAppOps;
     UserManager mUserManager;
     PackageManager mPackageManager;
+    PackageManagerInternal mPackageManagerInternal;
     AppWidgetManager mAppWidgetManager;
     IDeviceIdleController mDeviceIdleController;
     private DisplayManager mDisplayManager;
@@ -179,6 +182,7 @@
         mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
         mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
         mPackageManager = getContext().getPackageManager();
+        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
         mHandler = new H(BackgroundThread.get().getLooper());
 
         File systemDataDir = new File(Environment.getDataDirectory(), "system");
@@ -407,6 +411,10 @@
         }
     }
 
+    private boolean shouldObfuscateInstantAppsForCaller(int callingUid) {
+        return !mPackageManagerInternal.canAccessInstantApps(callingUid);
+    }
+
     void clearAppIdleForPackage(String packageName, int userId) {
         synchronized (mAppIdleLock) {
             mAppIdleHistory.clearUsage(packageName, userId);
@@ -704,6 +712,11 @@
             final long elapsedRealtime = SystemClock.elapsedRealtime();
             convertToSystemTimeLocked(event);
 
+            if (event.getPackageName() != null
+                    && mPackageManagerInternal.isPackageEphemeral(userId, event.getPackageName())) {
+                event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
+            }
+
             final UserUsageStatsService service =
                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
             service.reportEvent(event);
@@ -807,7 +820,8 @@
     /**
      * Called by the Binder stub.
      */
-    List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime) {
+    List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime,
+            boolean obfuscateInstantApps) {
         synchronized (mLock) {
             final long timeNow = checkAndGetTimeLocked();
             if (!validRange(timeNow, beginTime, endTime)) {
@@ -816,7 +830,20 @@
 
             final UserUsageStatsService service =
                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
-            return service.queryUsageStats(bucketType, beginTime, endTime);
+            List<UsageStats> list = service.queryUsageStats(bucketType, beginTime, endTime);
+
+            // Mangle instant app names *using their current state (not whether they were ephemeral
+            // when the data was recorded)*.
+            if (obfuscateInstantApps) {
+                for (int i = list.size() - 1; i >= 0; i--) {
+                    final UsageStats stats = list.get(i);
+                    if (mPackageManagerInternal.isPackageEphemeral(userId, stats.mPackageName)) {
+                        list.set(i, stats.getObfuscatedForInstantApp());
+                    }
+                }
+            }
+
+            return list;
         }
     }
 
@@ -840,7 +867,8 @@
     /**
      * Called by the Binder stub.
      */
-    UsageEvents queryEvents(int userId, long beginTime, long endTime) {
+    UsageEvents queryEvents(int userId, long beginTime, long endTime,
+            boolean shouldObfuscateInstantApps) {
         synchronized (mLock) {
             final long timeNow = checkAndGetTimeLocked();
             if (!validRange(timeNow, beginTime, endTime)) {
@@ -849,7 +877,7 @@
 
             final UserUsageStatsService service =
                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
-            return service.queryEvents(beginTime, endTime);
+            return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps);
         }
     }
 
@@ -884,10 +912,15 @@
         }
     }
 
-    boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime) {
+    boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime,
+            boolean shouldObfuscateInstantApps) {
         if (isParoledOrCharging()) {
             return false;
         }
+        if (shouldObfuscateInstantApps &&
+                mPackageManagerInternal.isPackageEphemeral(userId, packageName)) {
+            return false;
+        }
         return isAppIdleFiltered(packageName, getAppId(packageName), userId, elapsedRealtime);
     }
 
@@ -1353,11 +1386,14 @@
                 return null;
             }
 
+            final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
+                    Binder.getCallingUid());
+
             final int userId = UserHandle.getCallingUserId();
             final long token = Binder.clearCallingIdentity();
             try {
                 final List<UsageStats> results = UsageStatsService.this.queryUsageStats(
-                        userId, bucketType, beginTime, endTime);
+                        userId, bucketType, beginTime, endTime, obfuscateInstantApps);
                 if (results != null) {
                     return new ParceledListSlice<>(results);
                 }
@@ -1395,10 +1431,14 @@
                 return null;
             }
 
+            final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
+                    Binder.getCallingUid());
+
             final int userId = UserHandle.getCallingUserId();
             final long token = Binder.clearCallingIdentity();
             try {
-                return UsageStatsService.this.queryEvents(userId, beginTime, endTime);
+                return UsageStatsService.this.queryEvents(userId, beginTime, endTime,
+                        obfuscateInstantApps);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1412,10 +1452,12 @@
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
+            final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
+                    Binder.getCallingUid());
             final long token = Binder.clearCallingIdentity();
             try {
                 return UsageStatsService.this.isAppIdleFilteredOrParoled(packageName, userId,
-                        SystemClock.elapsedRealtime());
+                        SystemClock.elapsedRealtime(), obfuscateInstantApps);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1647,9 +1689,10 @@
 
         @Override
         public List<UsageStats> queryUsageStatsForUser(
-                int userId, int intervalType, long beginTime, long endTime) {
+                int userId, int intervalType, long beginTime, long endTime,
+                boolean obfuscateInstantApps) {
             return UsageStatsService.this.queryUsageStats(
-                    userId, intervalType, beginTime, endTime);
+                    userId, intervalType, beginTime, endTime, obfuscateInstantApps);
         }
     }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index 96f3305..cc53a9c 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -26,7 +26,10 @@
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
 import android.content.res.Configuration;
+import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.Log;
+import android.util.LogWriter;
 
 import java.io.IOException;
 import java.net.ProtocolException;
@@ -35,6 +38,8 @@
  * UsageStats reader/writer for version 1 of the XML format.
  */
 final class UsageStatsXmlV1 {
+    private static final String TAG = "UsageStatsXmlV1";
+
     private static final String PACKAGES_TAG = "packages";
     private static final String PACKAGE_TAG = "package";
 
@@ -51,6 +56,7 @@
 
     // Attributes
     private static final String PACKAGE_ATTR = "package";
+    private static final String FLAGS_ATTR = "flags";
     private static final String CLASS_ATTR = "class";
     private static final String TOTAL_TIME_ACTIVE_ATTR = "timeActive";
     private static final String COUNT_ATTR = "count";
@@ -70,7 +76,6 @@
         if (pkg == null) {
             throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present");
         }
-
         final UsageStats stats = statsOut.getOrCreateUsageStats(pkg);
 
         // Apply the offset to the beginTime to find the absolute time.
@@ -149,11 +154,12 @@
         if (packageName == null) {
             throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present");
         }
-
         final String className = XmlUtils.readStringAttribute(parser, CLASS_ATTR);
 
         final UsageEvents.Event event = statsOut.buildEvent(packageName, className);
 
+        event.mFlags = XmlUtils.readIntAttribute(parser, FLAGS_ATTR, 0);
+
         // Apply the offset to the beginTime to find the absolute time of this event.
         event.mTimeStamp = statsOut.beginTime + XmlUtils.readLongAttribute(parser, TIME_ATTR);
 
@@ -256,6 +262,7 @@
         if (event.mClass != null) {
             XmlUtils.writeStringAttribute(xml, CLASS_ATTR, event.mClass);
         }
+        XmlUtils.writeIntAttribute(xml, FLAGS_ATTR, event.mFlags);
         XmlUtils.writeIntAttribute(xml, TYPE_ATTR, event.mEventType);
 
         switch (event.mEventType) {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 8d335a5..0abbb82 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -19,11 +19,8 @@
 import android.app.usage.ConfigurationStats;
 import android.app.usage.TimeSparseArray;
 import android.app.usage.UsageEvents;
-import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.os.SystemClock;
 import android.content.Context;
@@ -312,7 +309,8 @@
         return queryStats(bucketType, beginTime, endTime, sConfigStatsCombiner);
     }
 
-    UsageEvents queryEvents(final long beginTime, final long endTime) {
+    UsageEvents queryEvents(final long beginTime, final long endTime,
+            boolean obfuscateInstantApps) {
         final ArraySet<String> names = new ArraySet<>();
         List<UsageEvents.Event> results = queryStats(UsageStatsManager.INTERVAL_DAILY,
                 beginTime, endTime, new StatCombiner<UsageEvents.Event>() {
@@ -334,7 +332,10 @@
                                 return;
                             }
 
-                            final UsageEvents.Event event = stats.events.valueAt(i);
+                            UsageEvents.Event event = stats.events.valueAt(i);
+                            if (obfuscateInstantApps) {
+                                event = event.getObfuscatedIfInstantApp();
+                            }
                             names.add(event.mPackage);
                             if (event.mClass != null) {
                                 names.add(event.mClass);
@@ -586,6 +587,7 @@
             if (event.mShortcutId != null) {
                 pw.printPair("shortcutId", event.mShortcutId);
             }
+            pw.printHexPair("flags", event.mFlags);
             pw.println();
         }
         pw.decreaseIndent();
diff --git a/tests/UsageStatsTest/Android.mk b/tests/UsageStatsTest/Android.mk
index 5f7467a..6b5c999 100644
--- a/tests/UsageStatsTest/Android.mk
+++ b/tests/UsageStatsTest/Android.mk
@@ -8,6 +8,8 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
 
+LOCAL_CERTIFICATE := platform
+
 LOCAL_PACKAGE_NAME := UsageStatsTest
 
 include $(BUILD_PACKAGE)
diff --git a/tests/UsageStatsTest/AndroidManifest.xml b/tests/UsageStatsTest/AndroidManifest.xml
index 589674a..c27be7b 100644
--- a/tests/UsageStatsTest/AndroidManifest.xml
+++ b/tests/UsageStatsTest/AndroidManifest.xml
@@ -1,7 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
 
+<!--
+  Note: Add android:sharedUserId="android.uid.system" to the root element to simulate the system UID
+  caller case.
+-->
+
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.tests.usagestats">
+    package="com.android.tests.usagestats"
+    >
 
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
 
diff --git a/tests/UsageStatsTest/res/menu/main.xml b/tests/UsageStatsTest/res/menu/main.xml
index e781058..4ccbc81 100644
--- a/tests/UsageStatsTest/res/menu/main.xml
+++ b/tests/UsageStatsTest/res/menu/main.xml
@@ -2,4 +2,6 @@
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:id="@+id/log"
         android:title="View Log"/>
+    <item android:id="@+id/call_is_app_inactive"
+        android:title="Call isAppInactive()"/>
 </menu>
diff --git a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
index c08c1a3..9429d9b 100644
--- a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
+++ b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
@@ -16,12 +16,16 @@
 
 package com.android.tests.usagestats;
 
+import android.app.AlertDialog;
 import android.app.ListActivity;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.os.Bundle;
+import android.text.InputType;
+import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -30,6 +34,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
+import android.widget.EditText;
 import android.widget.TextView;
 
 import java.util.ArrayList;
@@ -69,6 +74,9 @@
             case R.id.log:
                 startActivity(new Intent(this, UsageLogActivity.class));
                 return true;
+            case R.id.call_is_app_inactive:
+                callIsAppInactive();
+                return true;
 
             default:
                 return super.onOptionsItemSelected(item);
@@ -81,6 +89,41 @@
         updateAdapter();
     }
 
+    private void callIsAppInactive() {
+        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+        builder.setTitle("Enter package name");
+        final EditText input = new EditText(this);
+        input.setInputType(InputType.TYPE_CLASS_TEXT);
+        input.setHint("com.android.tests.usagestats");
+        builder.setView(input);
+
+        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                final String packageName = input.getText().toString().trim();
+                if (!TextUtils.isEmpty(packageName)) {
+                    showInactive(packageName);
+                }
+            }
+        });
+        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                dialog.cancel();
+            }
+        });
+
+        builder.show();
+    }
+
+    private void showInactive(String packageName) {
+        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+        builder.setMessage(
+                "isAppInactive(\"" + packageName + "\") = "
+                        + (mUsageStatsManager.isAppInactive(packageName) ? "true" : "false"));
+        builder.show();
+    }
+
     private void updateAdapter() {
         long now = System.currentTimeMillis();
         long beginTime = now - USAGE_STATS_PERIOD;
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
new file mode 100644
index 0000000..9fcd1b5
--- /dev/null
+++ b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.tethering;
+
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
+import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
+import static android.net.ConnectivityManager.TYPE_WIFI;
+import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_NOT_REQUIRED;
+import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_REQUIRED;
+import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_UNSPECIFIED;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.res.Resources;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.util.test.BroadcastInterceptingContext;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class TetheringConfigurationTest {
+    @Mock private Context mContext;
+    @Mock private TelephonyManager mTelephonyManager;
+    @Mock private Resources mResources;
+    private Context mMockContext;
+    private boolean mHasTelephonyManager;
+
+    private class MockContext extends BroadcastInterceptingContext {
+        MockContext(Context base) {
+            super(base);
+        }
+
+        @Override
+        public Resources getResources() { return mResources; }
+
+        @Override
+        public Object getSystemService(String name) {
+            if (Context.TELEPHONY_SERVICE.equals(name)) {
+                return mHasTelephonyManager ? mTelephonyManager : null;
+            }
+            return super.getSystemService(name);
+        }
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
+                .thenReturn(new String[0]);
+        when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
+                .thenReturn(new String[0]);
+        when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
+                .thenReturn(new String[]{ "test_wlan\\d" });
+        when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
+                .thenReturn(new String[0]);
+        mMockContext = new MockContext(mContext);
+    }
+
+    @Test
+    public void testDunFromTelephonyManagerMeansDun() {
+        when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
+                .thenReturn(new int[]{TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI});
+        mHasTelephonyManager = true;
+        when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_REQUIRED);
+
+        final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext);
+        assertTrue(cfg.isDunRequired);
+        assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
+        assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
+        assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
+        // Just to prove we haven't clobbered Wi-Fi:
+        assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
+    }
+
+    @Test
+    public void testDunNotRequiredFromTelephonyManagerMeansNoDun() {
+        when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
+                .thenReturn(new int[]{TYPE_MOBILE_DUN, TYPE_WIFI});
+        mHasTelephonyManager = true;
+        when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_NOT_REQUIRED);
+
+        final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext);
+        assertFalse(cfg.isDunRequired);
+        assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
+        assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
+        assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
+        // Just to prove we haven't clobbered Wi-Fi:
+        assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
+    }
+
+    @Test
+    public void testDunFromUpstreamConfigMeansDun() {
+        when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
+                .thenReturn(new int[]{TYPE_MOBILE_DUN, TYPE_WIFI});
+        mHasTelephonyManager = false;
+        when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
+
+        final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext);
+        assertTrue(cfg.isDunRequired);
+        assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
+        // Just to prove we haven't clobbered Wi-Fi:
+        assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
+    }
+}
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 90f713b..0d1850f 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -34,42 +34,43 @@
 
 namespace aapt {
 
-constexpr const char* sXliffNamespaceUri =
-    "urn:oasis:names:tc:xliff:document:1.2";
+constexpr const char* sXliffNamespaceUri = "urn:oasis:names:tc:xliff:document:1.2";
 
-/**
- * Returns true if the element is <skip> or <eat-comment> and can be safely
- * ignored.
- */
-static bool ShouldIgnoreElement(const StringPiece& ns,
-                                const StringPiece& name) {
+// Returns true if the element is <skip> or <eat-comment> and can be safely ignored.
+static bool ShouldIgnoreElement(const StringPiece& ns, const StringPiece& name) {
   return ns.empty() && (name == "skip" || name == "eat-comment");
 }
 
-static uint32_t ParseFormatType(const StringPiece& piece) {
-  if (piece == "reference")
+static uint32_t ParseFormatTypeNoEnumsOrFlags(const StringPiece& piece) {
+  if (piece == "reference") {
     return android::ResTable_map::TYPE_REFERENCE;
-  else if (piece == "string")
+  } else if (piece == "string") {
     return android::ResTable_map::TYPE_STRING;
-  else if (piece == "integer")
+  } else if (piece == "integer") {
     return android::ResTable_map::TYPE_INTEGER;
-  else if (piece == "boolean")
+  } else if (piece == "boolean") {
     return android::ResTable_map::TYPE_BOOLEAN;
-  else if (piece == "color")
+  } else if (piece == "color") {
     return android::ResTable_map::TYPE_COLOR;
-  else if (piece == "float")
+  } else if (piece == "float") {
     return android::ResTable_map::TYPE_FLOAT;
-  else if (piece == "dimension")
+  } else if (piece == "dimension") {
     return android::ResTable_map::TYPE_DIMENSION;
-  else if (piece == "fraction")
+  } else if (piece == "fraction") {
     return android::ResTable_map::TYPE_FRACTION;
-  else if (piece == "enum")
-    return android::ResTable_map::TYPE_ENUM;
-  else if (piece == "flags")
-    return android::ResTable_map::TYPE_FLAGS;
+  }
   return 0;
 }
 
+static uint32_t ParseFormatType(const StringPiece& piece) {
+  if (piece == "enum") {
+    return android::ResTable_map::TYPE_ENUM;
+  } else if (piece == "flags") {
+    return android::ResTable_map::TYPE_FLAGS;
+  }
+  return ParseFormatTypeNoEnumsOrFlags(piece);
+}
+
 static uint32_t ParseFormatAttribute(const StringPiece& str) {
   uint32_t mask = 0;
   for (StringPiece part : util::Tokenize(str, '|')) {
@@ -83,9 +84,7 @@
   return mask;
 }
 
-/**
- * A parsed resource ready to be added to the ResourceTable.
- */
+// A parsed resource ready to be added to the ResourceTable.
 struct ParsedResource {
   ResourceName name;
   ConfigDescription config;
@@ -416,8 +415,7 @@
     can_be_bag = false;
 
     // Items have their type encoded in the type attribute.
-    if (Maybe<StringPiece> maybe_type =
-            xml::FindNonEmptyAttribute(parser, "type")) {
+    if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) {
       resource_type = maybe_type.value().to_string();
     } else {
       diag_->Error(DiagMessage(source_.WithLine(parser->line_number()))
@@ -425,13 +423,11 @@
       return false;
     }
 
-    if (Maybe<StringPiece> maybe_format =
-            xml::FindNonEmptyAttribute(parser, "format")) {
+    if (Maybe<StringPiece> maybe_format = xml::FindNonEmptyAttribute(parser, "format")) {
       // An explicit format for this resource was specified. The resource will
-      // retain
-      // its type in its name, but the accepted value for this type is
+      // retain its type in its name, but the accepted value for this type is
       // overridden.
-      resource_format = ParseFormatType(maybe_format.value());
+      resource_format = ParseFormatTypeNoEnumsOrFlags(maybe_format.value());
       if (!resource_format) {
         diag_->Error(DiagMessage(out_resource->source)
                      << "'" << maybe_format.value()
@@ -1157,21 +1153,25 @@
   return true;
 }
 
-bool ResourceParser::ParseArray(xml::XmlPullParser* parser,
-                                ParsedResource* out_resource) {
-  return ParseArrayImpl(parser, out_resource, android::ResTable_map::TYPE_ANY);
+bool ResourceParser::ParseArray(xml::XmlPullParser* parser, ParsedResource* out_resource) {
+  uint32_t resource_format = android::ResTable_map::TYPE_ANY;
+  if (Maybe<StringPiece> format_attr = xml::FindNonEmptyAttribute(parser, "format")) {
+    resource_format = ParseFormatTypeNoEnumsOrFlags(format_attr.value());
+    if (resource_format == 0u) {
+      diag_->Error(DiagMessage(source_.WithLine(parser->line_number()))
+                   << "'" << format_attr.value() << "' is an invalid format");
+      return false;
+    }
+  }
+  return ParseArrayImpl(parser, out_resource, resource_format);
 }
 
-bool ResourceParser::ParseIntegerArray(xml::XmlPullParser* parser,
-                                       ParsedResource* out_resource) {
-  return ParseArrayImpl(parser, out_resource,
-                        android::ResTable_map::TYPE_INTEGER);
+bool ResourceParser::ParseIntegerArray(xml::XmlPullParser* parser, ParsedResource* out_resource) {
+  return ParseArrayImpl(parser, out_resource, android::ResTable_map::TYPE_INTEGER);
 }
 
-bool ResourceParser::ParseStringArray(xml::XmlPullParser* parser,
-                                      ParsedResource* out_resource) {
-  return ParseArrayImpl(parser, out_resource,
-                        android::ResTable_map::TYPE_STRING);
+bool ResourceParser::ParseStringArray(xml::XmlPullParser* parser, ParsedResource* out_resource) {
+  return ParseArrayImpl(parser, out_resource, android::ResTable_map::TYPE_STRING);
 }
 
 bool ResourceParser::ParseArrayImpl(xml::XmlPullParser* parser,
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 8062c2e6..faa6607 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -571,14 +571,39 @@
 }
 
 TEST_F(ResourceParserTest, ParseStringArray) {
-  std::string input =
-      "<string-array name=\"foo\">\n"
-      "  <item>\"Werk\"</item>\n"
-      "</string-array>\n";
+  std::string input = R"EOF(
+      <string-array name="foo">
+        <item>"Werk"</item>"
+      </string-array>)EOF";
   ASSERT_TRUE(TestParse(input));
   EXPECT_NE(nullptr, test::GetValue<Array>(&table_, "array/foo"));
 }
 
+TEST_F(ResourceParserTest, ParseArrayWithFormat) {
+  std::string input = R"EOF(
+      <array name="foo" format="string">
+        <item>100</item>
+      </array>)EOF";
+  ASSERT_TRUE(TestParse(input));
+
+  Array* array = test::GetValue<Array>(&table_, "array/foo");
+  ASSERT_NE(nullptr, array);
+
+  ASSERT_EQ(1u, array->items.size());
+
+  String* str = ValueCast<String>(array->items[0].get());
+  ASSERT_NE(nullptr, str);
+  EXPECT_EQ(std::string("100"), *str->value);
+}
+
+TEST_F(ResourceParserTest, ParseArrayWithBadFormat) {
+  std::string input = R"EOF(
+      <array name="foo" format="integer">
+        <item>Hi</item>
+      </array>)EOF";
+  ASSERT_FALSE(TestParse(input));
+}
+
 TEST_F(ResourceParserTest, ParsePlural) {
   std::string input =
       "<plurals name=\"foo\">\n"
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index c192d69..5adf04a 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -372,6 +372,8 @@
     if (file_type == file::FileType::kDirectory) {
       context->GetDiagnostics()->Error(DiagMessage(input_path)
                                        << "resource file cannot be a directory");
+    } else if (file_type == file::FileType::kNonexistant) {
+      context->GetDiagnostics()->Error(DiagMessage(input_path) << "file not found");
     } else {
       context->GetDiagnostics()->Error(DiagMessage(input_path)
                                        << "not a valid resource file");
@@ -488,7 +490,7 @@
     // Ensure that we only keep the chunks we care about if we end up
     // using the original PNG instead of the crunched one.
     PngChunkFilter png_chunk_filter(content);
-    std::unique_ptr<Image> image = ReadPng(context, &png_chunk_filter);
+    std::unique_ptr<Image> image = ReadPng(context, path_data.source, &png_chunk_filter);
     if (!image) {
       return false;
     }
diff --git a/tools/aapt2/compile/Png.h b/tools/aapt2/compile/Png.h
index e4255e7..7ca1f0e 100644
--- a/tools/aapt2/compile/Png.h
+++ b/tools/aapt2/compile/Png.h
@@ -69,7 +69,12 @@
   bool Rewind() override;
   size_t ByteCount() const override { return window_start_; }
 
-  bool HadError() const override { return error_; }
+  bool HadError() const override {
+    return !error_msg_.empty();
+  }
+  std::string GetError() const override {
+    return error_msg_;
+  }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(PngChunkFilter);
@@ -79,13 +84,13 @@
   android::StringPiece data_;
   size_t window_start_ = 0;
   size_t window_end_ = 0;
-  bool error_ = false;
+  std::string error_msg_;
 };
 
 /**
  * Reads a PNG from the InputStream into memory as an RGBA Image.
  */
-std::unique_ptr<Image> ReadPng(IAaptContext* context, io::InputStream* in);
+std::unique_ptr<Image> ReadPng(IAaptContext* context, const Source& source, io::InputStream* in);
 
 /**
  * Writes the RGBA Image, with optional 9-patch meta-data, into the OutputStream
diff --git a/tools/aapt2/compile/PngChunkFilter.cpp b/tools/aapt2/compile/PngChunkFilter.cpp
index f9043b5..7073c13 100644
--- a/tools/aapt2/compile/PngChunkFilter.cpp
+++ b/tools/aapt2/compile/PngChunkFilter.cpp
@@ -16,11 +16,13 @@
 
 #include "compile/Png.h"
 
+#include "android-base/stringprintf.h"
 #include "androidfw/StringPiece.h"
 
 #include "io/Io.h"
 
 using android::StringPiece;
+using android::base::StringPrintf;
 
 namespace aapt {
 
@@ -73,7 +75,7 @@
     window_start_ = 0;
     window_end_ = kPngSignatureSize;
   } else {
-    error_ = true;
+    error_msg_ = "PNG does not start with PNG signature";
   }
 }
 
@@ -90,7 +92,7 @@
 }
 
 bool PngChunkFilter::Next(const void** buffer, size_t* len) {
-  if (error_) {
+  if (HadError()) {
     return false;
   }
 
@@ -106,16 +108,21 @@
     const size_t kMinChunkHeaderSize = 3 * sizeof(uint32_t);
 
     // Is there enough room for a chunk header?
-    if (data_.size() - window_start_ < kMinChunkHeaderSize) {
-      error_ = true;
+    if (data_.size() - window_end_ < kMinChunkHeaderSize) {
+      error_msg_ = StringPrintf("Not enough space for a PNG chunk @ byte %zu/%zu", window_end_,
+                                data_.size());
       return false;
     }
 
     // Verify the chunk length.
     const uint32_t chunk_len = Peek32LE(data_.data() + window_end_);
-    if (((uint64_t)chunk_len) + ((uint64_t)window_end_) + sizeof(uint32_t) > data_.size()) {
+    if ((size_t)chunk_len > data_.size() - window_end_ - kMinChunkHeaderSize) {
       // Overflow.
-      error_ = true;
+      const uint32_t chunk_type = Peek32LE(data_.data() + window_end_ + sizeof(uint32_t));
+      error_msg_ = StringPrintf(
+          "PNG chunk type %08x is too large: chunk length is %zu but chunk "
+          "starts at byte %zu/%zu",
+          chunk_type, (size_t)chunk_len, window_end_ + kMinChunkHeaderSize, data_.size());
       return false;
     }
 
@@ -124,6 +131,16 @@
     if (IsPngChunkWhitelisted(chunk_type)) {
       // Advance the window to include this chunk.
       window_end_ += kMinChunkHeaderSize + chunk_len;
+
+      // Special case the IEND chunk, which MUST appear last and libpng stops parsing once it hits
+      // such a chunk (let's do the same).
+      if (chunk_type == kPngChunkIEND) {
+        // Truncate the data to the end of this chunk. There may be garbage trailing after
+        // (b/38169876)
+        data_ = data_.substr(0, window_end_);
+        break;
+      }
+
     } else {
       // We want to strip this chunk. If we accumulated a window,
       // we must return the window now.
@@ -145,14 +162,14 @@
 }
 
 void PngChunkFilter::BackUp(size_t count) {
-  if (error_) {
+  if (HadError()) {
     return;
   }
   window_start_ -= count;
 }
 
 bool PngChunkFilter::Rewind() {
-  if (error_) {
+  if (HadError()) {
     return false;
   }
   window_start_ = 0;
diff --git a/tools/aapt2/compile/PngCrunch.cpp b/tools/aapt2/compile/PngCrunch.cpp
index ae98afc..42443d8 100644
--- a/tools/aapt2/compile/PngCrunch.cpp
+++ b/tools/aapt2/compile/PngCrunch.cpp
@@ -73,6 +73,11 @@
 static void LogError(png_structp png_ptr, png_const_charp error_msg) {
   IDiagnostics* diag = (IDiagnostics*)png_get_error_ptr(png_ptr);
   diag->Error(DiagMessage() << error_msg);
+
+  // Causes libpng to longjmp to the spot where setjmp was set. This is how libpng does
+  // error handling. If this custom error handler method were to return, libpng would, by
+  // default, print the error message to stdout and call the same png_longjmp method.
+  png_longjmp(png_ptr, 1);
 }
 
 static void ReadDataFromStream(png_structp png_ptr, png_bytep buffer, png_size_t len) {
@@ -82,7 +87,12 @@
   size_t in_len;
   if (!in->Next(&in_buffer, &in_len)) {
     if (in->HadError()) {
-      std::string err = in->GetError();
+      std::stringstream error_msg_builder;
+      error_msg_builder << "failed reading from input";
+      if (!in->GetError().empty()) {
+        error_msg_builder << ": " << in->GetError();
+      }
+      std::string err = error_msg_builder.str();
       png_error(png_ptr, err.c_str());
     }
     return;
@@ -103,6 +113,11 @@
   while (len > 0) {
     if (!out->Next(&out_buffer, &out_len)) {
       if (out->HadError()) {
+        std::stringstream err_msg_builder;
+        err_msg_builder << "failed writing to output";
+        if (!out->GetError().empty()) {
+          err_msg_builder << ": " << out->GetError();
+        }
         std::string err = out->GetError();
         png_error(png_ptr, err.c_str());
       }
@@ -126,7 +141,7 @@
   }
 }
 
-std::unique_ptr<Image> ReadPng(IAaptContext* context, io::InputStream* in) {
+std::unique_ptr<Image> ReadPng(IAaptContext* context, const Source& source, io::InputStream* in) {
   // Read the first 8 bytes of the file looking for the PNG signature.
   // Bail early if it does not match.
   const png_byte* signature;
@@ -163,6 +178,9 @@
     return {};
   }
 
+  // Create a diagnostics that has the source information encoded.
+  SourcePathDiagnostics source_diag(source, context->GetDiagnostics());
+
   // Automatically release PNG resources at end of scope.
   PngReadStructDeleter png_read_deleter(read_ptr, info_ptr);
 
@@ -174,7 +192,7 @@
   }
 
   // Handle warnings ourselves via IDiagnostics.
-  png_set_error_fn(read_ptr, (png_voidp)context->GetDiagnostics(), LogError, LogWarning);
+  png_set_error_fn(read_ptr, (png_voidp)&source_diag, LogError, LogWarning);
 
   // Set up the read functions which read from our custom data sources.
   png_set_read_fn(read_ptr, (png_voidp)in, ReadDataFromStream);
@@ -231,8 +249,8 @@
   // something
   // that can always be represented by 9-patch.
   if (width > std::numeric_limits<int32_t>::max() || height > std::numeric_limits<int32_t>::max()) {
-    context->GetDiagnostics()->Error(
-        DiagMessage() << "PNG image dimensions are too large: " << width << "x" << height);
+    source_diag.Error(DiagMessage()
+                      << "PNG image dimensions are too large: " << width << "x" << height);
     return {};
   }
 
diff --git a/tools/aapt2/filter/ConfigFilter.cpp b/tools/aapt2/filter/ConfigFilter.cpp
index 66aff82..5fbe77e 100644
--- a/tools/aapt2/filter/ConfigFilter.cpp
+++ b/tools/aapt2/filter/ConfigFilter.cpp
@@ -38,6 +38,43 @@
   config_mask_ |= diff_mask;
 }
 
+// Returns true if the locale script of the config should be considered matching
+// the locale script of entry.
+//
+// If both the scripts are empty, the scripts are considered matching for
+// backward compatibility reasons.
+//
+// If only one script is empty, we try to compute it based on the provided
+// language and country. If we could not compute it, we assume it's either a
+// new language we don't know about, or a private use language. We return true
+// since we don't know any better and they might as well be a match.
+//
+// Finally, when we have two scripts (one of which could be computed), we return
+// true if and only if they are an exact match.
+static bool ScriptsMatch(const ConfigDescription& config, const ConfigDescription& entry) {
+  const char* config_script = config.localeScript;
+  const char* entry_script = entry.localeScript;
+  if (config_script[0] == '\0' && entry_script[0] == '\0') {
+    return true;  // both scripts are empty. We match for backward compatibility reasons.
+  }
+
+  char script_buffer[sizeof(config.localeScript)];
+  if (config_script[0] == '\0') {
+    android::localeDataComputeScript(script_buffer, config.language, config.country);
+    if (script_buffer[0] == '\0') {  // We can't compute the script, so we match.
+      return true;
+    }
+    config_script = script_buffer;
+  } else if (entry_script[0] == '\0') {
+    android::localeDataComputeScript(script_buffer, entry.language, entry.country);
+    if (script_buffer[0] == '\0') {  // We can't compute the script, so we match.
+      return true;
+    }
+    entry_script = script_buffer;
+  }
+  return memcmp(config_script, entry_script, sizeof(config.localeScript)) == 0;
+}
+
 bool AxisConfigFilter::Match(const ConfigDescription& config) const {
   const uint32_t mask = ConfigDescription::DefaultConfig().diff(config);
   if ((config_mask_ & mask) == 0) {
@@ -57,12 +94,16 @@
       // If the locales differ, but the languages are the same and
       // the locale we are matching only has a language specified,
       // we match.
-      if (config.language[0] &&
-          memcmp(config.language, target.language, sizeof(config.language)) ==
-              0) {
-        if (config.country[0] == 0) {
-          matched_axis |= android::ResTable_config::CONFIG_LOCALE;
-        }
+      //
+      // Exception: we won't match if a script is specified for at least
+      // one of the locales and it's different from the other locale's
+      // script. (We will compute the other script if at least one of the
+      // scripts were explicitly set. In cases we can't compute an script,
+      // we match.)
+      if (config.language[0] != '\0' && config.country[0] == '\0' &&
+          config.localeVariant[0] == '\0' && config.language[0] == entry.first.language[0] &&
+          config.language[1] == entry.first.language[1] && ScriptsMatch(config, entry.first)) {
+        matched_axis |= android::ResTable_config::CONFIG_LOCALE;
       }
     } else if ((diff & diff_mask) ==
                android::ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE) {
diff --git a/tools/aapt2/filter/ConfigFilter_test.cpp b/tools/aapt2/filter/ConfigFilter_test.cpp
index 586dd5f..4a31080 100644
--- a/tools/aapt2/filter/ConfigFilter_test.cpp
+++ b/tools/aapt2/filter/ConfigFilter_test.cpp
@@ -109,4 +109,20 @@
   EXPECT_TRUE(filter.Match(test::ParseConfigOrDie("kok-rIN")));
 }
 
+TEST(ConfigFilterTest, MatchesScripts) {
+  AxisConfigFilter filter;
+
+  // "sr" gets automatically computed the script "Cyrl"
+  filter.AddConfig(test::ParseConfigOrDie("sr"));
+
+  // "sr" -> "b+sr+Cyrl"
+  EXPECT_TRUE(filter.Match(test::ParseConfigOrDie("b+sr+Cyrl")));
+
+  // The incoming "sr" is also auto-computed to "b+sr+Cyrl".
+  EXPECT_TRUE(filter.Match(test::ParseConfigOrDie("sr")));
+
+  // "sr" -> "b+sr+Cyrl", which doesn't match "Latn".
+  EXPECT_FALSE(filter.Match(test::ParseConfigOrDie("b+sr+Latn")));
+}
+
 }  // namespace aapt
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index e59b74f0..cda078a 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -452,6 +452,15 @@
     public static final int SAP_START_FAILURE_NO_CHANNEL = 1;
 
     /**
+     * Interface IP mode unspecified.
+     *
+     * @see updateInterfaceIpState(String, int)
+     *
+     * @hide
+     */
+    public static final int IFACE_IP_MODE_UNSPECIFIED = -1;
+
+    /**
      * Interface IP mode for configuration error.
      *
      * @see updateInterfaceIpState(String, int)
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
index 92c7e36..ebf5c2a 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
@@ -139,7 +139,7 @@
 
     public String getDeviceInfoHex() {
         return String.format(
-                Locale.US, "%04x%04x%04x%04x", 6, mDeviceInfo, mCtrlPort, mMaxThroughput);
+                Locale.US, "%04x%04x%04x", mDeviceInfo, mCtrlPort, mMaxThroughput);
     }
 
     public String toString() {