Merge "Align AndroidKeyStore API with user auth API." into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 2bf91a4..1117623 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23,8 +23,10 @@
     field public static final java.lang.String BIND_CARRIER_CONFIG_SERVICE = "android.permission.BIND_CARRIER_CONFIG_SERVICE";
     field public static final java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
     field public static final java.lang.String BIND_CHOOSER_TARGET_SERVICE = "android.permission.BIND_CHOOSER_TARGET_SERVICE";
+    field public static final java.lang.String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
     field public static final java.lang.String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE";
+    field public static final java.lang.String BIND_INCALL_SERVICE = "android.permission.BIND_INCALL_SERVICE";
     field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
     field public static final java.lang.String BIND_MEDIA_ROUTE_SERVICE = "android.permission.BIND_MEDIA_ROUTE_SERVICE";
     field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
@@ -278,7 +280,7 @@
     field public static final int allowParallelSyncs = 16843570; // 0x1010332
     field public static final int allowSingleTap = 16843353; // 0x1010259
     field public static final int allowTaskReparenting = 16843268; // 0x1010204
-    field public static final int allowUndo = 16844006; // 0x10104e6
+    field public static final int allowUndo = 16844005; // 0x10104e5
     field public static final int alpha = 16843551; // 0x101031f
     field public static final int alphabeticShortcut = 16843235; // 0x10101e3
     field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
@@ -299,7 +301,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 assistBlocked = 16844020; // 0x10104f4
+    field public static final int assistBlocked = 16844019; // 0x10104f3
     field public static final int author = 16843444; // 0x10102b4
     field public static final int authorities = 16842776; // 0x1010018
     field public static final int autoAdvanceViewId = 16843535; // 0x101030f
@@ -310,7 +312,7 @@
     field public static final int autoStart = 16843445; // 0x10102b5
     field public static final deprecated int autoText = 16843114; // 0x101016a
     field public static final int autoUrlDetect = 16843404; // 0x101028c
-    field public static final int autoVerify = 16844010; // 0x10104ea
+    field public static final int autoVerify = 16844009; // 0x10104e9
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -334,7 +336,7 @@
     field public static final int bottomRightRadius = 16843180; // 0x10101ac
     field public static final int breadCrumbShortTitle = 16843524; // 0x1010304
     field public static final int breadCrumbTitle = 16843523; // 0x1010303
-    field public static final int breakStrategy = 16844011; // 0x10104eb
+    field public static final int breakStrategy = 16844010; // 0x10104ea
     field public static final int bufferType = 16843086; // 0x101014e
     field public static final int button = 16843015; // 0x1010107
     field public static final int buttonBarButtonStyle = 16843567; // 0x101032f
@@ -396,7 +398,7 @@
     field public static final int colorActivatedHighlight = 16843664; // 0x1010390
     field public static final int colorBackground = 16842801; // 0x1010031
     field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
-    field public static final int colorBackgroundFloating = 16844007; // 0x10104e7
+    field public static final int colorBackgroundFloating = 16844006; // 0x10104e6
     field public static final int colorButtonNormal = 16843819; // 0x101042b
     field public static final int colorControlActivated = 16843818; // 0x101042a
     field public static final int colorControlHighlight = 16843820; // 0x101042c
@@ -505,7 +507,7 @@
     field public static final int dropDownWidth = 16843362; // 0x1010262
     field public static final int duplicateParentState = 16842985; // 0x10100e9
     field public static final int duration = 16843160; // 0x1010198
-    field public static final int dynamicResources = 16844019; // 0x10104f3
+    field public static final int dynamicResources = 16844018; // 0x10104f2
     field public static final int editTextBackground = 16843602; // 0x1010352
     field public static final int editTextColor = 16843601; // 0x1010351
     field public static final int editTextPreferenceStyle = 16842898; // 0x1010092
@@ -517,7 +519,7 @@
     field public static final int ellipsize = 16842923; // 0x10100ab
     field public static final int ems = 16843096; // 0x1010158
     field public static final int enabled = 16842766; // 0x101000e
-    field public static final int end = 16843997; // 0x10104dd
+    field public static final int end = 16843996; // 0x10104dc
     field public static final int endColor = 16843166; // 0x101019e
     field public static final deprecated int endYear = 16843133; // 0x101017d
     field public static final int enterFadeDuration = 16843532; // 0x101030c
@@ -539,7 +541,7 @@
     field public static final int expandableListViewWhiteStyle = 16843446; // 0x10102b6
     field public static final int exported = 16842768; // 0x1010010
     field public static final int extraTension = 16843371; // 0x101026b
-    field public static final int extractNativeLibs = 16844008; // 0x10104e8
+    field public static final int extractNativeLibs = 16844007; // 0x10104e7
     field public static final int factor = 16843219; // 0x10101d3
     field public static final int fadeDuration = 16843384; // 0x1010278
     field public static final int fadeEnabled = 16843390; // 0x101027e
@@ -653,8 +655,8 @@
     field public static final int host = 16842792; // 0x1010028
     field public static final int icon = 16842754; // 0x1010002
     field public static final int iconPreview = 16843337; // 0x1010249
-    field public static final int iconTint = 16844000; // 0x10104e0
-    field public static final int iconTintMode = 16844001; // 0x10104e1
+    field public static final int iconTint = 16843999; // 0x10104df
+    field public static final int iconTintMode = 16844000; // 0x10104e0
     field public static final int iconifiedByDefault = 16843514; // 0x10102fa
     field public static final int id = 16842960; // 0x10100d0
     field public static final int ignoreGravity = 16843263; // 0x10101ff
@@ -794,7 +796,7 @@
     field public static final int layout_x = 16843135; // 0x101017f
     field public static final int layout_y = 16843136; // 0x1010180
     field public static final int left = 16843181; // 0x10101ad
-    field public static final int leftIndents = 16844016; // 0x10104f0
+    field public static final int leftIndents = 16844015; // 0x10104ef
     field public static final int letterSpacing = 16843958; // 0x10104b6
     field public static final int lineSpacingExtra = 16843287; // 0x1010217
     field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
@@ -817,7 +819,7 @@
     field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208
     field public static final int listViewStyle = 16842868; // 0x1010074
     field public static final int listViewWhiteStyle = 16842869; // 0x1010075
-    field public static final int lockTaskMode = 16844015; // 0x10104ef
+    field public static final int lockTaskMode = 16844014; // 0x10104ee
     field public static final int logo = 16843454; // 0x10102be
     field public static final int longClickable = 16842982; // 0x10100e6
     field public static final int loopViews = 16843527; // 0x1010307
@@ -866,8 +868,8 @@
     field public static final int navigationContentDescription = 16843969; // 0x10104c1
     field public static final int navigationIcon = 16843968; // 0x10104c0
     field public static final int navigationMode = 16843471; // 0x10102cf
-    field public static final int navigationTint = 16844004; // 0x10104e4
-    field public static final int navigationTintMode = 16844005; // 0x10104e5
+    field public static final int navigationTint = 16844003; // 0x10104e3
+    field public static final int navigationTintMode = 16844004; // 0x10104e4
     field public static final int negativeButtonText = 16843254; // 0x10101f6
     field public static final int nestedScrollingEnabled = 16843830; // 0x1010436
     field public static final int nextFocusDown = 16842980; // 0x10100e4
@@ -881,7 +883,7 @@
     field public static final int numColumns = 16843032; // 0x1010118
     field public static final int numStars = 16843076; // 0x1010144
     field public static final int numbersBackgroundColor = 16843938; // 0x10104a2
-    field public static final int numbersInnerTextColor = 16843999; // 0x10104df
+    field public static final int numbersInnerTextColor = 16843998; // 0x10104de
     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
@@ -899,8 +901,8 @@
     field public static final int overScrollFooter = 16843459; // 0x10102c3
     field public static final int overScrollHeader = 16843458; // 0x10102c2
     field public static final int overScrollMode = 16843457; // 0x10102c1
-    field public static final int overflowTint = 16844002; // 0x10104e2
-    field public static final int overflowTintMode = 16844003; // 0x10104e3
+    field public static final int overflowTint = 16844001; // 0x10104e1
+    field public static final int overflowTintMode = 16844002; // 0x10104e2
     field public static final int overlapAnchor = 16843874; // 0x1010462
     field public static final int overridesImplicitlyEnabledSubtype = 16843682; // 0x10103a2
     field public static final int packageNames = 16843649; // 0x1010381
@@ -995,7 +997,7 @@
     field public static final int readPermission = 16842759; // 0x1010007
     field public static final int recognitionService = 16843932; // 0x101049c
     field public static final int relinquishTaskIdentity = 16843894; // 0x1010476
-    field public static final int removeBeforeMRelease = 16844014; // 0x10104ee
+    field public static final int removeBeforeMRelease = 16844013; // 0x10104ed
     field public static final int reparent = 16843964; // 0x10104bc
     field public static final int reparentWithOverlay = 16843965; // 0x10104bd
     field public static final int repeatCount = 16843199; // 0x10101bf
@@ -1014,7 +1016,6 @@
     field public static final int resizeClip = 16843983; // 0x10104cf
     field public static final int resizeMode = 16843619; // 0x1010363
     field public static final int resizeable = 16843405; // 0x101028d
-    field public static final int resizeableActivity = 16843995; // 0x10104db
     field public static final int resource = 16842789; // 0x1010025
     field public static final int restoreAnyVersion = 16843450; // 0x10102ba
     field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
@@ -1024,7 +1025,7 @@
     field public static final int reversible = 16843851; // 0x101044b
     field public static final int revisionCode = 16843989; // 0x10104d5
     field public static final int right = 16843183; // 0x10101af
-    field public static final int rightIndents = 16844017; // 0x10104f1
+    field public static final int rightIndents = 16844016; // 0x10104f0
     field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
     field public static final int ringtoneType = 16843257; // 0x10101f9
     field public static final int rotation = 16843558; // 0x1010326
@@ -1100,7 +1101,7 @@
     field public static final int showAsAction = 16843481; // 0x10102d9
     field public static final int showDefault = 16843258; // 0x10101fa
     field public static final int showDividers = 16843561; // 0x1010329
-    field public static final int showForAllUsers = 16844018; // 0x10104f2
+    field public static final int showForAllUsers = 16844017; // 0x10104f1
     field public static final deprecated int showOnLockScreen = 16843721; // 0x10103c9
     field public static final int showSilent = 16843259; // 0x10101fb
     field public static final int showText = 16843949; // 0x10104ad
@@ -1130,7 +1131,7 @@
     field public static final int stackFromBottom = 16843005; // 0x10100fd
     field public static final int stackViewStyle = 16843838; // 0x101043e
     field public static final int starStyle = 16842882; // 0x1010082
-    field public static final int start = 16843996; // 0x10104dc
+    field public static final int start = 16843995; // 0x10104db
     field public static final int startColor = 16843165; // 0x101019d
     field public static final int startDelay = 16843746; // 0x10103e2
     field public static final int startOffset = 16843198; // 0x10101be
@@ -1186,7 +1187,7 @@
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
-    field public static final int supportsAssistGesture = 16844012; // 0x10104ec
+    field public static final int supportsAssistGesture = 16844011; // 0x10104eb
     field public static final int supportsRtl = 16843695; // 0x10103af
     field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
     field public static final int supportsUploading = 16843419; // 0x101029b
@@ -1287,7 +1288,7 @@
     field public static final int thicknessRatio = 16843164; // 0x101019c
     field public static final int thumb = 16843074; // 0x1010142
     field public static final int thumbOffset = 16843075; // 0x1010143
-    field public static final int thumbPosition = 16844013; // 0x10104ed
+    field public static final int thumbPosition = 16844012; // 0x10104ec
     field public static final int thumbTextPadding = 16843634; // 0x1010372
     field public static final int thumbTint = 16843889; // 0x1010471
     field public static final int thumbTintMode = 16843890; // 0x1010472
@@ -1351,7 +1352,7 @@
     field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
     field public static final int useLevel = 16843167; // 0x101019f
     field public static final int userVisible = 16843409; // 0x1010291
-    field public static final int usesCleartextTraffic = 16844009; // 0x10104e9
+    field public static final int usesCleartextTraffic = 16844008; // 0x10104e8
     field public static final int value = 16842788; // 0x1010024
     field public static final int valueFrom = 16843486; // 0x10102de
     field public static final int valueTo = 16843487; // 0x10102df
@@ -1416,10 +1417,10 @@
     field public static final int windowExitTransition = 16843832; // 0x1010438
     field public static final int windowFrame = 16842837; // 0x1010055
     field public static final int windowFullscreen = 16843277; // 0x101020d
-    field public static final int windowHasLightStatusBar = 16843998; // 0x10104de
     field public static final int windowHideAnimation = 16842935; // 0x10100b7
     field public static final int windowIsFloating = 16842839; // 0x1010057
     field public static final int windowIsTranslucent = 16842840; // 0x1010058
+    field public static final int windowLightStatusBar = 16843997; // 0x10104dd
     field public static final int windowMinWidthMajor = 16843606; // 0x1010356
     field public static final int windowMinWidthMinor = 16843607; // 0x1010357
     field public static final int windowNoDisplay = 16843294; // 0x101021e
@@ -5729,6 +5730,7 @@
     method public int getPasswordMinimumSymbols(android.content.ComponentName);
     method public int getPasswordMinimumUpperCase(android.content.ComponentName);
     method public int getPasswordQuality(android.content.ComponentName);
+    method public int getPermissionPolicy(android.content.ComponentName);
     method public java.util.List<java.lang.String> getPermittedAccessibilityServices(android.content.ComponentName);
     method public java.util.List<java.lang.String> getPermittedInputMethods(android.content.ComponentName);
     method public boolean getScreenCaptureDisabled(android.content.ComponentName);
@@ -5781,6 +5783,8 @@
     method public void setPasswordMinimumSymbols(android.content.ComponentName, int);
     method public void setPasswordMinimumUpperCase(android.content.ComponentName, int);
     method public void setPasswordQuality(android.content.ComponentName, int);
+    method public boolean setPermissionGranted(android.content.ComponentName, java.lang.String, java.lang.String, boolean);
+    method public void setPermissionPolicy(android.content.ComponentName, int);
     method public boolean setPermittedAccessibilityServices(android.content.ComponentName, java.util.List<java.lang.String>);
     method public boolean setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>);
     method public void setPreferredSetupActivity(android.content.ComponentName, android.content.ComponentName);
@@ -5869,6 +5873,9 @@
     field public static final int PASSWORD_QUALITY_NUMERIC_COMPLEX = 196608; // 0x30000
     field public static final int PASSWORD_QUALITY_SOMETHING = 65536; // 0x10000
     field public static final int PASSWORD_QUALITY_UNSPECIFIED = 0; // 0x0
+    field public static final int PERMISSION_POLICY_AUTO_DENY = 2; // 0x2
+    field public static final int PERMISSION_POLICY_AUTO_GRANT = 1; // 0x1
+    field public static final int PERMISSION_POLICY_PROMPT = 0; // 0x0
     field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
     field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1
     field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
@@ -9402,6 +9409,7 @@
     field public static final int GET_SIGNATURES = 64; // 0x40
     field public static final int GET_UNINSTALLED_PACKAGES = 8192; // 0x2000
     field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800
+    field public static final int MATCH_ALL = 131072; // 0x20000
     field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
     field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L
     field public static final int PERMISSION_DENIED = -1; // 0xffffffff
@@ -13226,6 +13234,7 @@
     field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_POSE_TRANSLATION;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_RADIAL_DISTORTION;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REPROCESS_MAX_CAPTURE_STALL;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> REQUEST_AVAILABLE_CAPABILITIES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_INPUT_STREAMS;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC;
@@ -30418,7 +30427,6 @@
   public static abstract class InCallService.VideoCall {
     ctor public InCallService.VideoCall();
     method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback);
-    method public abstract void unregisterCallback();
     method public abstract void requestCallDataUsage();
     method public abstract void requestCameraCapabilities();
     method public abstract void sendSessionModifyRequest(android.telecom.VideoProfile);
@@ -30429,6 +30437,7 @@
     method public abstract void setPauseImage(java.lang.String);
     method public abstract void setPreviewSurface(android.view.Surface);
     method public abstract void setZoom(float);
+    method public abstract void unregisterCallback();
   }
 
   public static abstract class InCallService.VideoCall.Callback {
@@ -33983,6 +33992,7 @@
     method public static void readEvents(int[], java.util.Collection<android.util.EventLog.Event>) throws java.io.IOException;
     method public static int writeEvent(int, int);
     method public static int writeEvent(int, long);
+    method public static int writeEvent(int, float);
     method public static int writeEvent(int, java.lang.String);
     method public static int writeEvent(int, java.lang.Object...);
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 9d34060..7210666 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -351,7 +351,7 @@
     field public static final int allowParallelSyncs = 16843570; // 0x1010332
     field public static final int allowSingleTap = 16843353; // 0x1010259
     field public static final int allowTaskReparenting = 16843268; // 0x1010204
-    field public static final int allowUndo = 16844006; // 0x10104e6
+    field public static final int allowUndo = 16844005; // 0x10104e5
     field public static final int alpha = 16843551; // 0x101031f
     field public static final int alphabeticShortcut = 16843235; // 0x10101e3
     field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
@@ -372,7 +372,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 assistBlocked = 16844020; // 0x10104f4
+    field public static final int assistBlocked = 16844019; // 0x10104f3
     field public static final int author = 16843444; // 0x10102b4
     field public static final int authorities = 16842776; // 0x1010018
     field public static final int autoAdvanceViewId = 16843535; // 0x101030f
@@ -383,7 +383,7 @@
     field public static final int autoStart = 16843445; // 0x10102b5
     field public static final deprecated int autoText = 16843114; // 0x101016a
     field public static final int autoUrlDetect = 16843404; // 0x101028c
-    field public static final int autoVerify = 16844010; // 0x10104ea
+    field public static final int autoVerify = 16844009; // 0x10104e9
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -407,7 +407,7 @@
     field public static final int bottomRightRadius = 16843180; // 0x10101ac
     field public static final int breadCrumbShortTitle = 16843524; // 0x1010304
     field public static final int breadCrumbTitle = 16843523; // 0x1010303
-    field public static final int breakStrategy = 16844011; // 0x10104eb
+    field public static final int breakStrategy = 16844010; // 0x10104ea
     field public static final int bufferType = 16843086; // 0x101014e
     field public static final int button = 16843015; // 0x1010107
     field public static final int buttonBarButtonStyle = 16843567; // 0x101032f
@@ -469,7 +469,7 @@
     field public static final int colorActivatedHighlight = 16843664; // 0x1010390
     field public static final int colorBackground = 16842801; // 0x1010031
     field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
-    field public static final int colorBackgroundFloating = 16844007; // 0x10104e7
+    field public static final int colorBackgroundFloating = 16844006; // 0x10104e6
     field public static final int colorButtonNormal = 16843819; // 0x101042b
     field public static final int colorControlActivated = 16843818; // 0x101042a
     field public static final int colorControlHighlight = 16843820; // 0x101042c
@@ -578,7 +578,7 @@
     field public static final int dropDownWidth = 16843362; // 0x1010262
     field public static final int duplicateParentState = 16842985; // 0x10100e9
     field public static final int duration = 16843160; // 0x1010198
-    field public static final int dynamicResources = 16844019; // 0x10104f3
+    field public static final int dynamicResources = 16844018; // 0x10104f2
     field public static final int editTextBackground = 16843602; // 0x1010352
     field public static final int editTextColor = 16843601; // 0x1010351
     field public static final int editTextPreferenceStyle = 16842898; // 0x1010092
@@ -590,7 +590,7 @@
     field public static final int ellipsize = 16842923; // 0x10100ab
     field public static final int ems = 16843096; // 0x1010158
     field public static final int enabled = 16842766; // 0x101000e
-    field public static final int end = 16843997; // 0x10104dd
+    field public static final int end = 16843996; // 0x10104dc
     field public static final int endColor = 16843166; // 0x101019e
     field public static final deprecated int endYear = 16843133; // 0x101017d
     field public static final int enterFadeDuration = 16843532; // 0x101030c
@@ -612,7 +612,7 @@
     field public static final int expandableListViewWhiteStyle = 16843446; // 0x10102b6
     field public static final int exported = 16842768; // 0x1010010
     field public static final int extraTension = 16843371; // 0x101026b
-    field public static final int extractNativeLibs = 16844008; // 0x10104e8
+    field public static final int extractNativeLibs = 16844007; // 0x10104e7
     field public static final int factor = 16843219; // 0x10101d3
     field public static final int fadeDuration = 16843384; // 0x1010278
     field public static final int fadeEnabled = 16843390; // 0x101027e
@@ -726,8 +726,8 @@
     field public static final int host = 16842792; // 0x1010028
     field public static final int icon = 16842754; // 0x1010002
     field public static final int iconPreview = 16843337; // 0x1010249
-    field public static final int iconTint = 16844000; // 0x10104e0
-    field public static final int iconTintMode = 16844001; // 0x10104e1
+    field public static final int iconTint = 16843999; // 0x10104df
+    field public static final int iconTintMode = 16844000; // 0x10104e0
     field public static final int iconifiedByDefault = 16843514; // 0x10102fa
     field public static final int id = 16842960; // 0x10100d0
     field public static final int ignoreGravity = 16843263; // 0x10101ff
@@ -867,7 +867,7 @@
     field public static final int layout_x = 16843135; // 0x101017f
     field public static final int layout_y = 16843136; // 0x1010180
     field public static final int left = 16843181; // 0x10101ad
-    field public static final int leftIndents = 16844016; // 0x10104f0
+    field public static final int leftIndents = 16844015; // 0x10104ef
     field public static final int letterSpacing = 16843958; // 0x10104b6
     field public static final int lineSpacingExtra = 16843287; // 0x1010217
     field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
@@ -890,7 +890,7 @@
     field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208
     field public static final int listViewStyle = 16842868; // 0x1010074
     field public static final int listViewWhiteStyle = 16842869; // 0x1010075
-    field public static final int lockTaskMode = 16844015; // 0x10104ef
+    field public static final int lockTaskMode = 16844014; // 0x10104ee
     field public static final int logo = 16843454; // 0x10102be
     field public static final int longClickable = 16842982; // 0x10100e6
     field public static final int loopViews = 16843527; // 0x1010307
@@ -939,8 +939,8 @@
     field public static final int navigationContentDescription = 16843969; // 0x10104c1
     field public static final int navigationIcon = 16843968; // 0x10104c0
     field public static final int navigationMode = 16843471; // 0x10102cf
-    field public static final int navigationTint = 16844004; // 0x10104e4
-    field public static final int navigationTintMode = 16844005; // 0x10104e5
+    field public static final int navigationTint = 16844003; // 0x10104e3
+    field public static final int navigationTintMode = 16844004; // 0x10104e4
     field public static final int negativeButtonText = 16843254; // 0x10101f6
     field public static final int nestedScrollingEnabled = 16843830; // 0x1010436
     field public static final int nextFocusDown = 16842980; // 0x10100e4
@@ -954,7 +954,7 @@
     field public static final int numColumns = 16843032; // 0x1010118
     field public static final int numStars = 16843076; // 0x1010144
     field public static final int numbersBackgroundColor = 16843938; // 0x10104a2
-    field public static final int numbersInnerTextColor = 16843999; // 0x10104df
+    field public static final int numbersInnerTextColor = 16843998; // 0x10104de
     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
@@ -972,8 +972,8 @@
     field public static final int overScrollFooter = 16843459; // 0x10102c3
     field public static final int overScrollHeader = 16843458; // 0x10102c2
     field public static final int overScrollMode = 16843457; // 0x10102c1
-    field public static final int overflowTint = 16844002; // 0x10104e2
-    field public static final int overflowTintMode = 16844003; // 0x10104e3
+    field public static final int overflowTint = 16844001; // 0x10104e1
+    field public static final int overflowTintMode = 16844002; // 0x10104e2
     field public static final int overlapAnchor = 16843874; // 0x1010462
     field public static final int overridesImplicitlyEnabledSubtype = 16843682; // 0x10103a2
     field public static final int packageNames = 16843649; // 0x1010381
@@ -1068,7 +1068,7 @@
     field public static final int readPermission = 16842759; // 0x1010007
     field public static final int recognitionService = 16843932; // 0x101049c
     field public static final int relinquishTaskIdentity = 16843894; // 0x1010476
-    field public static final int removeBeforeMRelease = 16844014; // 0x10104ee
+    field public static final int removeBeforeMRelease = 16844013; // 0x10104ed
     field public static final int reparent = 16843964; // 0x10104bc
     field public static final int reparentWithOverlay = 16843965; // 0x10104bd
     field public static final int repeatCount = 16843199; // 0x10101bf
@@ -1087,7 +1087,6 @@
     field public static final int resizeClip = 16843983; // 0x10104cf
     field public static final int resizeMode = 16843619; // 0x1010363
     field public static final int resizeable = 16843405; // 0x101028d
-    field public static final int resizeableActivity = 16843995; // 0x10104db
     field public static final int resource = 16842789; // 0x1010025
     field public static final int restoreAnyVersion = 16843450; // 0x10102ba
     field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
@@ -1097,7 +1096,7 @@
     field public static final int reversible = 16843851; // 0x101044b
     field public static final int revisionCode = 16843989; // 0x10104d5
     field public static final int right = 16843183; // 0x10101af
-    field public static final int rightIndents = 16844017; // 0x10104f1
+    field public static final int rightIndents = 16844016; // 0x10104f0
     field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
     field public static final int ringtoneType = 16843257; // 0x10101f9
     field public static final int rotation = 16843558; // 0x1010326
@@ -1177,7 +1176,7 @@
     field public static final int showAsAction = 16843481; // 0x10102d9
     field public static final int showDefault = 16843258; // 0x10101fa
     field public static final int showDividers = 16843561; // 0x1010329
-    field public static final int showForAllUsers = 16844018; // 0x10104f2
+    field public static final int showForAllUsers = 16844017; // 0x10104f1
     field public static final deprecated int showOnLockScreen = 16843721; // 0x10103c9
     field public static final int showSilent = 16843259; // 0x10101fb
     field public static final int showText = 16843949; // 0x10104ad
@@ -1207,7 +1206,7 @@
     field public static final int stackFromBottom = 16843005; // 0x10100fd
     field public static final int stackViewStyle = 16843838; // 0x101043e
     field public static final int starStyle = 16842882; // 0x1010082
-    field public static final int start = 16843996; // 0x10104dc
+    field public static final int start = 16843995; // 0x10104db
     field public static final int startColor = 16843165; // 0x101019d
     field public static final int startDelay = 16843746; // 0x10103e2
     field public static final int startOffset = 16843198; // 0x10101be
@@ -1263,7 +1262,7 @@
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
-    field public static final int supportsAssistGesture = 16844012; // 0x10104ec
+    field public static final int supportsAssistGesture = 16844011; // 0x10104eb
     field public static final int supportsRtl = 16843695; // 0x10103af
     field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
     field public static final int supportsUploading = 16843419; // 0x101029b
@@ -1364,7 +1363,7 @@
     field public static final int thicknessRatio = 16843164; // 0x101019c
     field public static final int thumb = 16843074; // 0x1010142
     field public static final int thumbOffset = 16843075; // 0x1010143
-    field public static final int thumbPosition = 16844013; // 0x10104ed
+    field public static final int thumbPosition = 16844012; // 0x10104ec
     field public static final int thumbTextPadding = 16843634; // 0x1010372
     field public static final int thumbTint = 16843889; // 0x1010471
     field public static final int thumbTintMode = 16843890; // 0x1010472
@@ -1428,7 +1427,7 @@
     field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
     field public static final int useLevel = 16843167; // 0x101019f
     field public static final int userVisible = 16843409; // 0x1010291
-    field public static final int usesCleartextTraffic = 16844009; // 0x10104e9
+    field public static final int usesCleartextTraffic = 16844008; // 0x10104e8
     field public static final int value = 16842788; // 0x1010024
     field public static final int valueFrom = 16843486; // 0x10102de
     field public static final int valueTo = 16843487; // 0x10102df
@@ -1493,10 +1492,10 @@
     field public static final int windowExitTransition = 16843832; // 0x1010438
     field public static final int windowFrame = 16842837; // 0x1010055
     field public static final int windowFullscreen = 16843277; // 0x101020d
-    field public static final int windowHasLightStatusBar = 16843998; // 0x10104de
     field public static final int windowHideAnimation = 16842935; // 0x10100b7
     field public static final int windowIsFloating = 16842839; // 0x1010057
     field public static final int windowIsTranslucent = 16842840; // 0x1010058
+    field public static final int windowLightStatusBar = 16843997; // 0x10104dd
     field public static final int windowMinWidthMajor = 16843606; // 0x1010356
     field public static final int windowMinWidthMinor = 16843607; // 0x1010357
     field public static final int windowNoDisplay = 16843294; // 0x101021e
@@ -5828,6 +5827,7 @@
     method public int getPasswordMinimumSymbols(android.content.ComponentName);
     method public int getPasswordMinimumUpperCase(android.content.ComponentName);
     method public int getPasswordQuality(android.content.ComponentName);
+    method public int getPermissionPolicy(android.content.ComponentName);
     method public java.util.List<java.lang.String> getPermittedAccessibilityServices(android.content.ComponentName);
     method public java.util.List<java.lang.String> getPermittedAccessibilityServices(int);
     method public java.util.List<java.lang.String> getPermittedInputMethods(android.content.ComponentName);
@@ -5886,6 +5886,8 @@
     method public void setPasswordMinimumSymbols(android.content.ComponentName, int);
     method public void setPasswordMinimumUpperCase(android.content.ComponentName, int);
     method public void setPasswordQuality(android.content.ComponentName, int);
+    method public boolean setPermissionGranted(android.content.ComponentName, java.lang.String, java.lang.String, boolean);
+    method public void setPermissionPolicy(android.content.ComponentName, int);
     method public boolean setPermittedAccessibilityServices(android.content.ComponentName, java.util.List<java.lang.String>);
     method public boolean setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>);
     method public void setPreferredSetupActivity(android.content.ComponentName, android.content.ComponentName);
@@ -5979,6 +5981,9 @@
     field public static final int PASSWORD_QUALITY_NUMERIC_COMPLEX = 196608; // 0x30000
     field public static final int PASSWORD_QUALITY_SOMETHING = 65536; // 0x10000
     field public static final int PASSWORD_QUALITY_UNSPECIFIED = 0; // 0x0
+    field public static final int PERMISSION_POLICY_AUTO_DENY = 2; // 0x2
+    field public static final int PERMISSION_POLICY_AUTO_GRANT = 1; // 0x1
+    field public static final int PERMISSION_POLICY_PROMPT = 0; // 0x0
     field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
     field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1
     field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
@@ -9697,6 +9702,7 @@
     field public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103; // 0xffffff99
     field public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102; // 0xffffff9a
     field public static final int INSTALL_SUCCEEDED = 1; // 0x1
+    field public static final int MATCH_ALL = 131072; // 0x20000
     field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
     field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L
     field public static final int PERMISSION_DENIED = -1; // 0xffffffff
@@ -13526,6 +13532,7 @@
     field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_POSE_TRANSLATION;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<float[]> LENS_RADIAL_DISTORTION;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REPROCESS_MAX_CAPTURE_STALL;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> REQUEST_AVAILABLE_CAPABILITIES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_INPUT_STREAMS;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC;
@@ -32535,7 +32542,6 @@
   public static abstract class InCallService.VideoCall {
     ctor public InCallService.VideoCall();
     method public abstract void registerCallback(android.telecom.InCallService.VideoCall.Callback);
-    method public abstract void unregisterCallback();
     method public abstract void requestCallDataUsage();
     method public abstract void requestCameraCapabilities();
     method public abstract void sendSessionModifyRequest(android.telecom.VideoProfile);
@@ -32546,6 +32552,7 @@
     method public abstract void setPauseImage(java.lang.String);
     method public abstract void setPreviewSurface(android.view.Surface);
     method public abstract void setZoom(float);
+    method public abstract void unregisterCallback();
   }
 
   public static abstract class InCallService.VideoCall.Callback {
@@ -36187,6 +36194,7 @@
     method public static void readEvents(int[], java.util.Collection<android.util.EventLog.Event>) throws java.io.IOException;
     method public static int writeEvent(int, int);
     method public static int writeEvent(int, long);
+    method public static int writeEvent(int, float);
     method public static int writeEvent(int, java.lang.String);
     method public static int writeEvent(int, java.lang.Object...);
   }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ed814c3..cf9813f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -807,6 +807,24 @@
     public static final String ACTION_SYSTEM_UPDATE_POLICY_CHANGED
             = "android.app.action.SYSTEM_UPDATE_POLICY_CHANGED";
 
+    /**
+     * Permission policy to prompt user for new permission requests for runtime permissions.
+     * Already granted or denied permissions are not affected by this.
+     */
+    public static final int PERMISSION_POLICY_PROMPT = 0;
+
+    /**
+     * Permission policy to always grant new permission requests for runtime permissions.
+     * Already granted or denied permissions are not affected by this.
+     */
+    public static final int PERMISSION_POLICY_AUTO_GRANT = 1;
+
+    /**
+     * Permission policy to always deny new permission requests for runtime permissions.
+     * Already granted or denied permissions are not affected by this.
+     */
+    public static final int PERMISSION_POLICY_AUTO_DENY = 2;
+
 
     /**
      * Return true if the given administrator component is currently
@@ -4342,4 +4360,58 @@
             Log.w(TAG, "Failed talking with device policy service", re);
         }
     }
+
+    /**
+     * Called by profile or device owners to set the default response for future runtime permission
+     * requests by applications. The policy can allow for normal operation which prompts the
+     * user to grant a permission, or can allow automatic granting or denying of runtime
+     * permission requests by an application. This also applies to new permissions declared by app
+     * updates.
+     * @param admin Which profile or device owner this request is associated with.
+     * @param policy One of the policy constants {@link #PERMISSION_POLICY_PROMPT},
+     * {@link #PERMISSION_POLICY_AUTO_GRANT} and {@link #PERMISSION_POLICY_AUTO_DENY}.
+     */
+    public void setPermissionPolicy(ComponentName admin, int policy) {
+        try {
+            mService.setPermissionPolicy(admin, policy);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Failed talking with device policy service", re);
+        }
+    }
+
+    /**
+     * Returns the current runtime permission policy set by the device or profile owner. The
+     * default is {@link #PERMISSION_POLICY_PROMPT}.
+     * @param admin Which profile or device owner this request is associated with.
+     * @return the current policy for future permission requests.
+     */
+    public int getPermissionPolicy(ComponentName admin) {
+        try {
+            return mService.getPermissionPolicy(admin);
+        } catch (RemoteException re) {
+            return PERMISSION_POLICY_PROMPT;
+        }
+    }
+
+    /**
+     * Grants or revokes a runtime permission to a specific application so that the user
+     * does not have to be prompted. This might affect all permissions in a group that the
+     * runtime permission belongs to. This method can only be called by a profile or device
+     * owner.
+     * @param admin Which profile or device owner this request is associated with.
+     * @param packageName The application to grant or revoke a permission to.
+     * @param permission The permission to grant or revoke.
+     * @param granted Whether or not to grant the permission. If false, all permissions in the
+     * associated permission group will be denied.
+     * @return whether the permission was successfully granted or revoked
+     */
+    public boolean setPermissionGranted(ComponentName admin, String packageName,
+            String permission, boolean granted) {
+        try {
+            return mService.setPermissionGranted(admin, packageName, permission, granted);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Failed talking with device policy service", re);
+            return false;
+        }
+    }
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index a678c51..833bc00 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -229,4 +229,9 @@
     boolean getDoNotAskCredentialsOnBoot();
 
     void notifyPendingSystemUpdate(in long updateReceivedTime);
+
+    void setPermissionPolicy(in ComponentName admin, int policy);
+    int  getPermissionPolicy(in ComponentName admin);
+    boolean setPermissionGranted(in ComponentName admin, String packageName, String permission,
+            boolean granted);
 }
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index fd65d56..72e701d 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -211,7 +211,27 @@
                 // We do not call ContentProvider#query with a modified where clause since
                 // the implementation is not guaranteed to be backed by a SQL database, hence
                 // it may not handle properly the tautology where clause we would have created.
-                return new MatrixCursor(projection, 0);
+                if (projection != null) {
+                    return new MatrixCursor(projection, 0);
+                }
+
+                // Null projection means all columns but we have no idea which they are.
+                // However, the caller may be expecting to access them my index. Hence,
+                // we have to execute the query as if allowed to get a cursor with the
+                // columns. We then use the column names to return an empty cursor.
+                Cursor cursor = ContentProvider.this.query(uri, projection, selection,
+                        selectionArgs, sortOrder, CancellationSignal.fromTransport(
+                                cancellationSignal));
+
+                // Create a projection for all columns.
+                final int columnCount = cursor.getCount();
+                String[] allColumns = new String[columnCount];
+                for (int i = 0; i < columnCount; i++) {
+                    allColumns[i] = cursor.getColumnName(i);
+                }
+
+                // Return an empty cursor for all columns.
+                return new MatrixCursor(allColumns, 0);
             }
             final String original = setCallingPackage(callingPkg);
             try {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e1c271d..f01ca09 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -209,7 +209,14 @@
      * matching.  This is a synonym for including the CATEGORY_DEFAULT in your
      * supplied Intent.
      */
-    public static final int MATCH_DEFAULT_ONLY   = 0x00010000;
+    public static final int MATCH_DEFAULT_ONLY  = 0x00010000;
+
+    /**
+     * Querying flag: if set and if the platform is doing any filtering of the results, then
+     * the filtering will not happen. This is a synonym for saying that all results should
+     * be returned.
+     */
+    public static final int MATCH_ALL = 0x00020000;
 
     /**
      * Flag for {@link addCrossProfileIntentFilter}: if this flag is set:
@@ -2637,6 +2644,8 @@
      * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
      * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
      *
+     * You can also set {@link #MATCH_ALL} for preventing the filtering of the results.
+     *
      * @return A List&lt;ResolveInfo&gt; containing one entry for each matching
      *         Activity. These are ordered from best to worst match -- that
      *         is, the first item in the list is what is returned by
@@ -2658,6 +2667,8 @@
      * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
      * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
      *
+     * You can also set {@link #MATCH_ALL} for preventing the filtering of the results.
+     *
      * @return A List&lt;ResolveInfo&gt; containing one entry for each matching
      *         Activity. These are ordered from best to worst match -- that
      *         is, the first item in the list is what is returned by
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 87a1ca9..19e821c 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -603,10 +603,9 @@
     /**
      * <p>List of available high speed video size and fps range configurations
      * supported by the camera device, in the format of (width, height, fps_min, fps_max).</p>
-     * <p>When HIGH_SPEED_VIDEO is supported in {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes},
-     * this metadata will list the supported high speed video size and fps range
-     * configurations. All the sizes listed in this configuration will be a subset
-     * of the sizes reported by StreamConfigurationMap#getOutputSizes for processed
+     * <p>When HIGH_SPEED_VIDEO is supported in {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}, this metadata
+     * will list the supported high speed video size and fps range configurations. All the sizes
+     * listed in this configuration will be a subset of the sizes reported by {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } for processed
      * non-stalling formats.</p>
      * <p>For the high speed video use case, where the application will set
      * {@link CaptureRequest#CONTROL_SCENE_MODE android.control.sceneMode} to HIGH_SPEED_VIDEO in capture requests, the application must
@@ -1116,11 +1115,12 @@
      * into the 3 stream types as below:</p>
      * <ul>
      * <li>Processed (but stalling): any non-RAW format with a stallDurations &gt; 0.
-     * Typically JPEG format (ImageFormat#JPEG).</li>
-     * <li>Raw formats: ImageFormat#RAW_SENSOR, ImageFormat#RAW10, ImageFormat#RAW12,
-     * and ImageFormat#RAW_OPAQUE.</li>
+     *   Typically {@link android.graphics.ImageFormat#JPEG JPEG format}.</li>
+     * <li>Raw formats: {@link android.graphics.ImageFormat#RAW_SENSOR RAW_SENSOR}, {@link android.graphics.ImageFormat#RAW10 RAW10}, or {@link android.graphics.ImageFormat#RAW12 RAW12}.</li>
      * <li>Processed (but not-stalling): any non-RAW format without a stall duration.
-     * Typically ImageFormat#YUV_420_888, ImageFormat#NV21, ImageFormat#YV12.</li>
+     *   Typically {@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888},
+     *   {@link android.graphics.ImageFormat#NV21 NV21}, or
+     *   {@link android.graphics.ImageFormat#YV12 YV12}.</li>
      * </ul>
      * <p><b>Range of valid values:</b><br></p>
      * <p>For processed (and stalling) format streams, &gt;= 1.</p>
@@ -1148,10 +1148,9 @@
      * be any <code>RAW</code> and supported format provided by {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}.</p>
      * <p>In particular, a <code>RAW</code> format is typically one of:</p>
      * <ul>
-     * <li>ImageFormat#RAW_SENSOR</li>
-     * <li>ImageFormat#RAW10</li>
-     * <li>ImageFormat#RAW12</li>
-     * <li>Opaque <code>RAW</code></li>
+     * <li>{@link android.graphics.ImageFormat#RAW_SENSOR RAW_SENSOR}</li>
+     * <li>{@link android.graphics.ImageFormat#RAW10 RAW10}</li>
+     * <li>{@link android.graphics.ImageFormat#RAW12 RAW12}</li>
      * </ul>
      * <p>LEGACY mode devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} <code>==</code> LEGACY)
      * never support raw streams.</p>
@@ -1180,13 +1179,13 @@
      * <p>Processed (but not-stalling) is defined as any non-RAW format without a stall duration.
      * Typically:</p>
      * <ul>
-     * <li>ImageFormat#YUV_420_888</li>
-     * <li>ImageFormat#NV21</li>
-     * <li>ImageFormat#YV12</li>
-     * <li>Implementation-defined formats, i.e. StreamConfiguration#isOutputSupportedFor(Class)</li>
+     * <li>{@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888}</li>
+     * <li>{@link android.graphics.ImageFormat#NV21 NV21}</li>
+     * <li>{@link android.graphics.ImageFormat#YV12 YV12}</li>
+     * <li>Implementation-defined formats, i.e. {@link android.hardware.camera2.params.StreamConfigurationMap#isOutputSupportedFor(Class) }</li>
      * </ul>
-     * <p>For full guarantees, query StreamConfigurationMap#getOutputStallDuration with
-     * a processed format -- it will return 0 for a non-stalling stream.</p>
+     * <p>For full guarantees, query {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration } with a
+     * processed format -- it will return 0 for a non-stalling stream.</p>
      * <p>LEGACY devices will support at least 2 processing/non-stalling streams.</p>
      * <p><b>Range of valid values:</b><br></p>
      * <p>&gt;= 3
@@ -1212,10 +1211,11 @@
      * the camera device. Using more streams simultaneously may require more hardware and
      * CPU resources that will consume more power. The image format for this kind of an output stream can
      * be any non-<code>RAW</code> and supported format provided by {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}.</p>
-     * <p>A processed and stalling format is defined as any non-RAW format with a stallDurations &gt; 0.
-     * Typically only the <code>JPEG</code> format (ImageFormat#JPEG) is a stalling format.</p>
-     * <p>For full guarantees, query StreamConfigurationMap#getOutputStallDuration with
-     * a processed format -- it will return a non-0 value for a stalling stream.</p>
+     * <p>A processed and stalling format is defined as any non-RAW format with a stallDurations
+     * &gt; 0.  Typically only the {@link android.graphics.ImageFormat#JPEG JPEG format} is a
+     * stalling format.</p>
+     * <p>For full guarantees, query {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration } with a
+     * processed format -- it will return a non-0 value for a stalling stream.</p>
      * <p>LEGACY devices will support up to 1 processing/stalling stream.</p>
      * <p><b>Range of valid values:</b><br></p>
      * <p>&gt;= 1</p>
@@ -1232,10 +1232,9 @@
      * <p>The maximum numbers of any type of input streams
      * that can be configured and used simultaneously by a camera device.</p>
      * <p>When set to 0, it means no input stream is supported.</p>
-     * <p>The image format for a input stream can be any supported
-     * format returned by StreamConfigurationMap#getInputFormats. When using an
-     * input stream, there must be at least one output stream
-     * configured to to receive the reprocessed images.</p>
+     * <p>The image format for a input stream can be any supported format returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputFormats }. When using an
+     * input stream, there must be at least one output stream configured to to receive the
+     * reprocessed images.</p>
      * <p>When an input stream and some output streams are used in a reprocessing request,
      * only the input buffer will be used to produce these output stream buffers, and a
      * new sensor image will not be captured.</p>
@@ -1352,7 +1351,7 @@
 
     /**
      * <p>A list of all keys that the camera device has available
-     * to use with CaptureRequest.</p>
+     * to use with {@link android.hardware.camera2.CaptureRequest }.</p>
      * <p>Attempting to set a key into a CaptureRequest that is not
      * listed here will result in an invalid request and will be rejected
      * by the camera device.</p>
@@ -1370,7 +1369,7 @@
 
     /**
      * <p>A list of all keys that the camera device has available
-     * to use with CaptureResult.</p>
+     * to use with {@link android.hardware.camera2.CaptureResult }.</p>
      * <p>Attempting to get a key from a CaptureResult that is not
      * listed here will always return a <code>null</code> value. Getting a key from
      * a CaptureResult that is listed here will generally never return a <code>null</code>
@@ -1396,7 +1395,7 @@
 
     /**
      * <p>A list of all keys that the camera device has available
-     * to use with CameraCharacteristics.</p>
+     * to use with {@link android.hardware.camera2.CameraCharacteristics }.</p>
      * <p>This entry follows the same rules as
      * android.request.availableResultKeys (except that it applies for
      * CameraCharacteristics instead of CaptureResult). See above for more
@@ -1535,34 +1534,31 @@
      * </thead>
      * <tbody>
      * <tr>
-     * <td align="left">PRIVATE (ImageFormat#PRIVATE)</td>
-     * <td align="left">JPEG</td>
+     * <td align="left">{@link android.graphics.ImageFormat#PRIVATE }</td>
+     * <td align="left">{@link android.graphics.ImageFormat#JPEG }</td>
      * <td align="left">OPAQUE_REPROCESSING</td>
      * </tr>
      * <tr>
-     * <td align="left">PRIVATE</td>
-     * <td align="left">YUV_420_888</td>
+     * <td align="left">{@link android.graphics.ImageFormat#PRIVATE }</td>
+     * <td align="left">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
      * <td align="left">OPAQUE_REPROCESSING</td>
      * </tr>
      * <tr>
-     * <td align="left">YUV_420_888</td>
-     * <td align="left">JPEG</td>
+     * <td align="left">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
+     * <td align="left">{@link android.graphics.ImageFormat#JPEG }</td>
      * <td align="left">YUV_REPROCESSING</td>
      * </tr>
      * <tr>
-     * <td align="left">YUV_420_888</td>
-     * <td align="left">YUV_420_888</td>
+     * <td align="left">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
+     * <td align="left">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
      * <td align="left">YUV_REPROCESSING</td>
      * </tr>
      * </tbody>
      * </table>
-     * <p>PRIVATE refers to a device-internal format that is not directly application-visible.
-     * A PRIVATE input surface can be acquired by
-     * ImageReader.newOpaqueInstance(width, height, maxImages).
-     * For a OPAQUE_REPROCESSING-capable camera device, using the PRIVATE format
-     * as either input or output will never hurt maximum frame rate (i.e.
-     * StreamConfigurationMap#getOutputStallDuration(format, size) is always 0),
-     * where format is ImageFormat#PRIVATE.</p>
+     * <p>PRIVATE refers to a device-internal format that is not directly application-visible.  A
+     * PRIVATE input surface can be acquired by {@link android.media.ImageReader#newOpaqueInstance }.</p>
+     * <p>For a OPAQUE_REPROCESSING-capable camera device, using the PRIVATE format as either input
+     * or output will never hurt maximum frame rate (i.e.  {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration getOutputStallDuration(ImageFormat.PRIVATE, size)} is always 0),</p>
      * <p>Attempting to configure an input stream with output streams not
      * listed as available in this map is not valid.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -1680,7 +1676,7 @@
      * android.scaler.availableStallDurations for more details about
      * calculating the max frame rate.</p>
      * <p>(Keep in sync with
-     * StreamConfigurationMap#getOutputMinFrameDuration)</p>
+     * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration })</p>
      * <p><b>Units</b>: (format, width, height, ns) x n</p>
      * <p>This key is available on all devices.</p>
      *
@@ -1692,7 +1688,7 @@
 
     /**
      * <p>This lists the maximum stall duration for each
-     * format/size combination.</p>
+     * output format/size combination.</p>
      * <p>A stall duration is how much extra time would get added
      * to the normal minimum frame duration for a repeating request
      * that has streams with non-zero stall.</p>
@@ -1734,12 +1730,13 @@
      * ignored).</p>
      * <p>The following formats may always have a stall duration:</p>
      * <ul>
-     * <li>ImageFormat#JPEG</li>
-     * <li>ImageFormat#RAW_SENSOR</li>
+     * <li>{@link android.graphics.ImageFormat#JPEG }</li>
+     * <li>{@link android.graphics.ImageFormat#RAW_SENSOR }</li>
      * </ul>
      * <p>The following formats will never have a stall duration:</p>
      * <ul>
-     * <li>ImageFormat#YUV_420_888</li>
+     * <li>{@link android.graphics.ImageFormat#YUV_420_888 }</li>
+     * <li>{@link android.graphics.ImageFormat#RAW10 }</li>
      * </ul>
      * <p>All other formats may or may not have an allowed stall duration on
      * a per-capability basis; refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
@@ -1747,7 +1744,7 @@
      * <p>See {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration} for more information about
      * calculating the max frame rate (absent stalls).</p>
      * <p>(Keep up to date with
-     * StreamConfigurationMap#getOutputStallDuration(int, Size) )</p>
+     * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration } )</p>
      * <p><b>Units</b>: (format, width, height, ns) x n</p>
      * <p>This key is available on all devices.</p>
      *
@@ -1786,57 +1783,57 @@
      * </thead>
      * <tbody>
      * <tr>
-     * <td align="center">JPEG</td>
+     * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td>
      * <td align="center">{@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</td>
      * <td align="center">Any</td>
      * <td align="center"></td>
      * </tr>
      * <tr>
-     * <td align="center">JPEG</td>
+     * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td>
      * <td align="center">1920x1080 (1080p)</td>
      * <td align="center">Any</td>
      * <td align="center">if 1080p &lt;= activeArraySize</td>
      * </tr>
      * <tr>
-     * <td align="center">JPEG</td>
+     * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td>
      * <td align="center">1280x720 (720)</td>
      * <td align="center">Any</td>
      * <td align="center">if 720p &lt;= activeArraySize</td>
      * </tr>
      * <tr>
-     * <td align="center">JPEG</td>
+     * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td>
      * <td align="center">640x480 (480p)</td>
      * <td align="center">Any</td>
      * <td align="center">if 480p &lt;= activeArraySize</td>
      * </tr>
      * <tr>
-     * <td align="center">JPEG</td>
+     * <td align="center">{@link android.graphics.ImageFormat#JPEG }</td>
      * <td align="center">320x240 (240p)</td>
      * <td align="center">Any</td>
      * <td align="center">if 240p &lt;= activeArraySize</td>
      * </tr>
      * <tr>
-     * <td align="center">YUV_420_888</td>
+     * <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
      * <td align="center">all output sizes available for JPEG</td>
      * <td align="center">FULL</td>
      * <td align="center"></td>
      * </tr>
      * <tr>
-     * <td align="center">YUV_420_888</td>
+     * <td align="center">{@link android.graphics.ImageFormat#YUV_420_888 }</td>
      * <td align="center">all output sizes available for JPEG, up to the maximum video size</td>
      * <td align="center">LIMITED</td>
      * <td align="center"></td>
      * </tr>
      * <tr>
-     * <td align="center">IMPLEMENTATION_DEFINED</td>
+     * <td align="center">{@link android.graphics.ImageFormat#PRIVATE }</td>
      * <td align="center">same as YUV_420_888</td>
      * <td align="center">Any</td>
      * <td align="center"></td>
      * </tr>
      * </tbody>
      * </table>
-     * <p>Refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} for additional
-     * mandatory stream configurations on a per-capability basis.</p>
+     * <p>Refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} and {@link android.hardware.camera2.CameraDevice#createCaptureSession } for additional mandatory
+     * stream configurations on a per-capability basis.</p>
      * <p>This key is available on all devices.</p>
      *
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
@@ -1973,8 +1970,8 @@
      * <p>Attempting to use frame durations beyond the maximum will result in the frame
      * duration being clipped to the maximum. See that control for a full definition of frame
      * durations.</p>
-     * <p>Refer to StreamConfigurationMap#getOutputMinFrameDuration(int,Size) for the minimum
-     * frame duration values.</p>
+     * <p>Refer to {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }
+     * for the minimum frame duration values.</p>
      * <p><b>Units</b>: Nanoseconds</p>
      * <p><b>Range of valid values:</b><br>
      * For FULL capability devices
@@ -2634,6 +2631,41 @@
             new Key<Integer>("android.sync.maxLatency", int.class);
 
     /**
+     * <p>The maximal camera capture pipeline stall (in unit of frame count) introduced by a
+     * reprocess capture request.</p>
+     * <p>The key describes the maximal interference that one reprocess (input) request
+     * can introduce to the camera simultaneous streaming of regular (output) capture
+     * requests, including repeating requests.</p>
+     * <p>When a reprocessing capture request is submitted while a camera output repeating request
+     * (e.g. preview) is being served by the camera device, it may preempt the camera capture
+     * pipeline for at least one frame duration so that the camera device is unable to process
+     * the following capture request in time for the next sensor start of exposure boundary.
+     * When this happens, the application may observe a capture time gap (longer than one frame
+     * duration) between adjacent capture output frames, which usually exhibits as preview
+     * glitch if the repeating request output targets include a preview surface. This key gives
+     * the worst-case number of frame stall introduced by one reprocess request with any kind of
+     * formats/sizes combination.</p>
+     * <p>If this key reports 0, it means a reprocess request doesn't introduce any glitch to the
+     * ongoing camera repeating request outputs, as if this reprocess request is never issued.</p>
+     * <p>This key is supported if the camera device supports OPAQUE or YUV reprocessing (
+     * i.e. {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains OPAQUE_REPROCESSING or
+     * YUV_REPROCESSING).</p>
+     * <p><b>Units</b>: Number of frames.</p>
+     * <p><b>Range of valid values:</b><br>
+     * &lt;= 4</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Limited capability</b> -
+     * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
+     * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
+     *
+     * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     */
+    @PublicKey
+    public static final Key<Integer> REPROCESS_MAX_CAPTURE_STALL =
+            new Key<Integer>("android.reprocess.maxCaptureStall", int.class);
+
+    /**
      * <p>The available depth dataspace stream
      * configurations that this camera device supports
      * (i.e. format, width, height, output/input stream).</p>
@@ -2672,8 +2704,7 @@
      * <p>See {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration} and
      * android.scaler.availableStallDurations for more details about
      * calculating the max frame rate.</p>
-     * <p>(Keep in sync with
-     * StreamConfigurationMap#getOutputMinFrameDuration)</p>
+     * <p>(Keep in sync with {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration })</p>
      * <p><b>Units</b>: (format, width, height, ns) x n</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Limited capability</b> -
@@ -2689,7 +2720,7 @@
 
     /**
      * <p>This lists the maximum stall duration for each
-     * format/size combination for depth streams.</p>
+     * output format/size combination for depth streams.</p>
      * <p>A stall duration is how much extra time would get added
      * to the normal minimum frame duration for a repeating request
      * that has streams with non-zero stall.</p>
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 51b326b..f6791a4 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -54,6 +54,7 @@
      * means that high frame rate is given priority over the highest-quality
      * post-processing. These requests would normally be used with the
      * {@link CameraCaptureSession#setRepeatingRequest} method.
+     * This template is guaranteed to be supported on all camera devices.
      *
      * @see #createCaptureRequest
      */
@@ -63,6 +64,7 @@
      * Create a request suitable for still image capture. Specifically, this
      * means prioritizing image quality over frame rate. These requests would
      * commonly be used with the {@link CameraCaptureSession#capture} method.
+     * This template is guaranteed to be supported on all camera devices.
      *
      * @see #createCaptureRequest
      */
@@ -73,6 +75,7 @@
      * that a stable frame rate is used, and post-processing is set for
      * recording quality. These requests would commonly be used with the
      * {@link CameraCaptureSession#setRepeatingRequest} method.
+     * This template is guaranteed to be supported on all camera devices.
      *
      * @see #createCaptureRequest
      */
@@ -84,6 +87,9 @@
      * disrupting the ongoing recording. These requests would commonly be used
      * with the {@link CameraCaptureSession#capture} method while a request based on
      * {@link #TEMPLATE_RECORD} is is in use with {@link CameraCaptureSession#setRepeatingRequest}.
+     * This template is guaranteed to be supported on all camera devices except
+     * legacy devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+     * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY})
      *
      * @see #createCaptureRequest
      */
@@ -93,6 +99,11 @@
      * Create a request suitable for zero shutter lag still capture. This means
      * means maximizing image quality without compromising preview frame rate.
      * AE/AWB/AF should be on auto mode.
+     * This template is guaranteed to be supported on camera devices that support the
+     * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING OPAQUE_REPROCESSING}
+     * capability or the
+     * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING YUV_REPROCESSING}
+     * capability.
      *
      * @see #createCaptureRequest
      */
@@ -105,6 +116,9 @@
      * quality. The manual capture parameters (exposure, sensitivity, and so on)
      * are set to reasonable defaults, but should be overriden by the
      * application depending on the intended use case.
+     * This template is guaranteed to be supported on camera devices that support the
+     * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR MANUAL_SENSOR}
+     * capability.
      *
      * @see #createCaptureRequest
      */
@@ -473,12 +487,14 @@
      * settings as desired, instead.</p>
      *
      * @param templateType An enumeration selecting the use case for this
-     * request; one of the CameraDevice.TEMPLATE_ values.
+     * request; one of the CameraDevice.TEMPLATE_ values. Not all template
+     * types are supported on every device. See the documentation for each
+     * template type for details.
      * @return a builder for a capture request, initialized with default
      * settings for that template, and no output streams
      *
-     * @throws IllegalArgumentException if the templateType is not in the list
-     * of supported templates.
+     * @throws IllegalArgumentException if the templateType is not supported by
+     * this device.
      * @throws CameraAccessException if the camera device is no longer connected or has
      *                               encountered a fatal error
      * @throws IllegalStateException if the camera device has been closed
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index e3f1d73..ca9439b 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -461,22 +461,21 @@
      * <p>The camera device supports the Zero Shutter Lag reprocessing use case.</p>
      * <ul>
      * <li>One input stream is supported, that is, <code>{@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} == 1</code>.</li>
-     * <li>ImageFormat#PRIVATE is supported as an output/input format, that is,
-     *   ImageFormat#PRIVATE is included in the lists of formats returned by
-     *   StreamConfigurationMap#getInputFormats and
-     *   StreamConfigurationMap#getOutputFormats.</li>
-     * <li>StreamConfigurationMap#getValidOutputFormatsForInput returns non empty int[] for
-     *   each supported input format returned by StreamConfigurationMap#getInputFormats.</li>
-     * <li>Each size returned by StreamConfigurationMap#getInputSizes(ImageFormat#PRIVATE)
-     *   is also included in StreamConfigurationMap#getOutputSizes(ImageFormat#PRIVATE)</li>
-     * <li>Using ImageFormat#PRIVATE does not cause a frame rate drop
-     *   relative to the sensor's maximum capture rate (at that
-     *   resolution).</li>
-     * <li>ImageFormat#PRIVATE will be reprocessable into both YUV_420_888
-     *   and JPEG formats.</li>
+     * <li>{@link android.graphics.ImageFormat#PRIVATE } is supported as an output/input format,
+     *   that is, {@link android.graphics.ImageFormat#PRIVATE } is included in the lists of
+     *   formats returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputFormats } and {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputFormats }.</li>
+     * <li>{@link android.hardware.camera2.params.StreamConfigurationMap#getValidOutputFormatsForInput }
+     *   returns non empty int[] for each supported input format returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputFormats }.</li>
+     * <li>Each size returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputSizes getInputSizes(ImageFormat.PRIVATE)} is also included in {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes getOutputSizes(ImageFormat.PRIVATE)}</li>
+     * <li>Using {@link android.graphics.ImageFormat#PRIVATE } does not cause a frame rate drop
+     *   relative to the sensor's maximum capture rate (at that resolution).</li>
+     * <li>{@link android.graphics.ImageFormat#PRIVATE } will be reprocessable into both
+     *   {@link android.graphics.ImageFormat#YUV_420_888 } and
+     *   {@link android.graphics.ImageFormat#JPEG } formats.</li>
      * <li>The maximum available resolution for OPAQUE streams
      *   (both input/output) will match the maximum available
      *   resolution of JPEG streams.</li>
+     * <li>Static metadata {@link CameraCharacteristics#REPROCESS_MAX_CAPTURE_STALL android.reprocess.maxCaptureStall}.</li>
      * <li>Only below controls are effective for reprocessing requests and
      *   will be present in capture results, other controls in reprocess
      *   requests will be ignored by the camera device.<ul>
@@ -489,6 +488,7 @@
      *
      * @see CaptureRequest#EDGE_MODE
      * @see CaptureRequest#NOISE_REDUCTION_MODE
+     * @see CameraCharacteristics#REPROCESS_MAX_CAPTURE_STALL
      * @see CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      */
@@ -569,25 +569,25 @@
      * following:</p>
      * <ul>
      * <li>One input stream is supported, that is, <code>{@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} == 1</code>.</li>
-     * <li>YUV_420_888 is supported as an output/input format, that is,
+     * <li>{@link android.graphics.ImageFormat#YUV_420_888 } is supported as an output/input format, that is,
      *   YUV_420_888 is included in the lists of formats returned by
-     *   StreamConfigurationMap#getInputFormats and
-     *   StreamConfigurationMap#getOutputFormats.</li>
-     * <li>StreamConfigurationMap#getValidOutputFormatsForInput returns non empty int[] for
-     *   each supported input format returned by StreamConfigurationMap#getInputFormats.</li>
-     * <li>Each size returned by StreamConfigurationMap#getInputSizes(YUV_420_888)
-     *   is also included in StreamConfigurationMap#getOutputSizes(YUV_420_888)</li>
-     * <li>Using YUV_420_888 does not cause a frame rate drop
+     *   {@link android.hardware.camera2.params.StreamConfigurationMap#getInputFormats } and
+     *   {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputFormats }.</li>
+     * <li>{@link android.hardware.camera2.params.StreamConfigurationMap#getValidOutputFormatsForInput }
+     *   returns non-empty int[] for each supported input format returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputFormats }.</li>
+     * <li>Each size returned by {@link android.hardware.camera2.params.StreamConfigurationMap#getInputSizes getInputSizes(YUV_420_888)} is also included in {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes getOutputSizes(YUV_420_888)}</li>
+     * <li>Using {@link android.graphics.ImageFormat#YUV_420_888 } does not cause a frame rate drop
      *   relative to the sensor's maximum capture rate (at that resolution).</li>
-     * <li>YUV_420_888 will be reprocessable into both YUV_420_888
-     *   and JPEG formats.</li>
-     * <li>The maximum available resolution for YUV_420_888 streams
-     *   (both input/output) will match the maximum available
-     *   resolution of JPEG streams.</li>
-     * <li>Only the below controls are effective for reprocessing requests and will be
-     *   present in capture results. The reprocess requests are from the original capture
-     *   results that are assocaited with the intermidate YUV_420_888 output buffers.
-     *   All other controls in the reprocess requests will be ignored by the camera device.<ul>
+     * <li>{@link android.graphics.ImageFormat#YUV_420_888 } will be reprocessable into both
+     *   {@link android.graphics.ImageFormat#YUV_420_888 } and {@link android.graphics.ImageFormat#JPEG } formats.</li>
+     * <li>The maximum available resolution for {@link android.graphics.ImageFormat#YUV_420_888 } streams (both input/output) will match the
+     *   maximum available resolution of {@link android.graphics.ImageFormat#JPEG } streams.</li>
+     * <li>Static metadata {@link CameraCharacteristics#REPROCESS_MAX_CAPTURE_STALL android.reprocess.maxCaptureStall}.</li>
+     * <li>Only the below controls are effective for reprocessing requests and will be present
+     *   in capture results. The reprocess requests are from the original capture results that
+     *   are associated with the intermediate {@link android.graphics.ImageFormat#YUV_420_888 }
+     *   output buffers.  All other controls in the reprocess requests will be ignored by the
+     *   camera device.<ul>
      * <li>android.jpeg.*</li>
      * <li>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}</li>
      * <li>{@link CaptureRequest#EDGE_MODE android.edge.mode}</li>
@@ -599,6 +599,7 @@
      * @see CaptureRequest#EDGE_MODE
      * @see CaptureRequest#NOISE_REDUCTION_MODE
      * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
+     * @see CameraCharacteristics#REPROCESS_MAX_CAPTURE_STALL
      * @see CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      */
@@ -608,11 +609,13 @@
      * <p>The camera device can produce depth measurements from its field of view.</p>
      * <p>This capability requires the camera device to support the following:</p>
      * <ul>
-     * <li>DEPTH16 is supported as an output format.</li>
-     * <li>DEPTH_POINT_CLOUD is optionally supported as an output format.</li>
-     * <li>This camera device, and all camera devices with the same android.lens.info.facing,
-     *   will list the following calibration entries in both CameraCharacteristics and
-     *   CaptureResults:<ul>
+     * <li>{@link android.graphics.ImageFormat#DEPTH16 } is supported as an output format.</li>
+     * <li>{@link android.graphics.ImageFormat#DEPTH_POINT_CLOUD } is optionally supported as an
+     *   output format.</li>
+     * <li>This camera device, and all camera devices with the same {@link CameraCharacteristics#LENS_FACING android.lens.facing},
+     *   will list the following calibration entries in both
+     *   {@link android.hardware.camera2.CameraCharacteristics } and
+     *   {@link android.hardware.camera2.CaptureResult }:<ul>
      * <li>{@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}</li>
      * <li>{@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}</li>
      * <li>android.lens.intrinsicCalibration</li>
@@ -627,13 +630,14 @@
      * <p>Generally, depth output operates at a slower frame rate than standard color capture,
      * so the DEPTH16 and DEPTH_POINT_CLOUD formats will commonly have a stall duration that
      * should be accounted for (see
-     * android.hardware.camera2.StreamConfigurationMap#getOutputStallDuration).  On a device
-     * that supports both depth and color-based output, to enable smooth preview, using a
-     * repeating burst is recommended, where a depth-output target is only included once
-     * every N frames, where N is the ratio between preview output rate and depth output
+     * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }).
+     * On a device that supports both depth and color-based output, to enable smooth preview,
+     * using a repeating burst is recommended, where a depth-output target is only included
+     * once every N frames, where N is the ratio between preview output rate and depth output
      * rate, including depth stall time.</p>
      *
      * @see CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE
+     * @see CameraCharacteristics#LENS_FACING
      * @see CameraCharacteristics#LENS_POSE_ROTATION
      * @see CameraCharacteristics#LENS_POSE_TRANSLATION
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
@@ -707,7 +711,7 @@
 
     /**
      * <p>Timestamps from {@link CaptureResult#SENSOR_TIMESTAMP android.sensor.timestamp} are in the same timebase as
-     * android.os.SystemClock#elapsedRealtimeNanos(),
+     * {@link android.os.SystemClock#elapsedRealtimeNanos },
      * and they can be compared to other timestamps using that base.</p>
      *
      * @see CaptureResult#SENSOR_TIMESTAMP
@@ -866,7 +870,7 @@
     /**
      * <p>Every frame has the requests immediately applied.</p>
      * <p>Furthermore for all results,
-     * <code>android.sync.frameNumber == CaptureResult#getFrameNumber()</code></p>
+     * <code>android.sync.frameNumber == {@link android.hardware.camera2.CaptureResult#getFrameNumber }</code></p>
      * <p>Changing controls over multiple requests one after another will
      * produce results that have those controls applied atomically
      * each frame.</p>
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 19d17b1..ab6ce91 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1275,8 +1275,9 @@
      * <p>This control (except for MANUAL) is only effective if
      * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
      * <p>ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
-     * contains OPAQUE_REPROCESSING. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
-     * contains MANUAL_SENSOR. Other intent values are always supported.</p>
+     * contains OPAQUE_REPROCESSING or YUV_REPROCESSING. MANUAL will be supported if
+     * {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains MANUAL_SENSOR. Other intent values are
+     * always supported.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #CONTROL_CAPTURE_INTENT_CUSTOM CUSTOM}</li>
@@ -2039,8 +2040,8 @@
      * cannot process more than 1 capture at a time.</li>
      * </ul>
      * <p>The necessary information for the application, given the model above,
-     * is provided via the {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} field
-     * using StreamConfigurationMap#getOutputMinFrameDuration(int, Size).
+     * is provided via the {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} field using
+     * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }.
      * These are used to determine the maximum frame rate / minimum frame
      * duration that is possible for a given stream configuration.</p>
      * <p>Specifically, the application can use the following rules to
@@ -2049,21 +2050,19 @@
      * <ol>
      * <li>Let the set of currently configured input/output streams
      * be called <code>S</code>.</li>
-     * <li>Find the minimum frame durations for each stream in <code>S</code>, by
-     * looking it up in {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} using
-     * StreamConfigurationMap#getOutputMinFrameDuration(int, Size) (with
-     * its respective size/format). Let this set of frame durations be called
-     * <code>F</code>.</li>
+     * <li>Find the minimum frame durations for each stream in <code>S</code>, by looking
+     * it up in {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} using {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }
+     * (with its respective size/format). Let this set of frame durations be
+     * called <code>F</code>.</li>
      * <li>For any given request <code>R</code>, the minimum frame duration allowed
      * for <code>R</code> is the maximum out of all values in <code>F</code>. Let the streams
      * used in <code>R</code> be called <code>S_r</code>.</li>
      * </ol>
-     * <p>If none of the streams in <code>S_r</code> have a stall time (listed in
-     * StreamConfigurationMap#getOutputStallDuration(int,Size) using its
-     * respective size/format), then the frame duration in
-     * <code>F</code> determines the steady state frame rate that the application will
-     * get if it uses <code>R</code> as a repeating request. Let this special kind
-     * of request be called <code>Rsimple</code>.</p>
+     * <p>If none of the streams in <code>S_r</code> have a stall time (listed in {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }
+     * using its respective size/format), then the frame duration in <code>F</code>
+     * determines the steady state frame rate that the application will get
+     * if it uses <code>R</code> as a repeating request. Let this special kind of
+     * request be called <code>Rsimple</code>.</p>
      * <p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved
      * by a single capture of a new request <code>Rstall</code> (which has at least
      * one in-use stream with a non-0 stall time) and if <code>Rstall</code> has the
@@ -2071,7 +2070,7 @@
      * if all buffers from the previous <code>Rstall</code> have already been
      * delivered.</p>
      * <p>For more details about stalling, see
-     * StreamConfigurationMap#getOutputStallDuration(int,Size).</p>
+     * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }.</p>
      * <p>This control is only effective if {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} or {@link CaptureRequest#CONTROL_MODE android.control.mode} is set to
      * OFF; otherwise the auto-exposure algorithm will override this value.</p>
      * <p><b>Units</b>: Nanoseconds</p>
@@ -2647,8 +2646,12 @@
      * <p><b>Range of valid values:</b><br>
      * &gt;= 1.0</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Limited capability</b> -
+     * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
+     * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
      *
      * @see CaptureRequest#EDGE_MODE
+     * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see CaptureRequest#NOISE_REDUCTION_MODE
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      */
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index ef5d75c..3dc8970 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -1698,8 +1698,9 @@
      * <p>This control (except for MANUAL) is only effective if
      * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
      * <p>ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
-     * contains OPAQUE_REPROCESSING. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
-     * contains MANUAL_SENSOR. Other intent values are always supported.</p>
+     * contains OPAQUE_REPROCESSING or YUV_REPROCESSING. MANUAL will be supported if
+     * {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains MANUAL_SENSOR. Other intent values are
+     * always supported.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #CONTROL_CAPTURE_INTENT_CUSTOM CUSTOM}</li>
@@ -2885,8 +2886,8 @@
      * cannot process more than 1 capture at a time.</li>
      * </ul>
      * <p>The necessary information for the application, given the model above,
-     * is provided via the {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} field
-     * using StreamConfigurationMap#getOutputMinFrameDuration(int, Size).
+     * is provided via the {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} field using
+     * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }.
      * These are used to determine the maximum frame rate / minimum frame
      * duration that is possible for a given stream configuration.</p>
      * <p>Specifically, the application can use the following rules to
@@ -2895,21 +2896,19 @@
      * <ol>
      * <li>Let the set of currently configured input/output streams
      * be called <code>S</code>.</li>
-     * <li>Find the minimum frame durations for each stream in <code>S</code>, by
-     * looking it up in {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} using
-     * StreamConfigurationMap#getOutputMinFrameDuration(int, Size) (with
-     * its respective size/format). Let this set of frame durations be called
-     * <code>F</code>.</li>
+     * <li>Find the minimum frame durations for each stream in <code>S</code>, by looking
+     * it up in {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap} using {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }
+     * (with its respective size/format). Let this set of frame durations be
+     * called <code>F</code>.</li>
      * <li>For any given request <code>R</code>, the minimum frame duration allowed
      * for <code>R</code> is the maximum out of all values in <code>F</code>. Let the streams
      * used in <code>R</code> be called <code>S_r</code>.</li>
      * </ol>
-     * <p>If none of the streams in <code>S_r</code> have a stall time (listed in
-     * StreamConfigurationMap#getOutputStallDuration(int,Size) using its
-     * respective size/format), then the frame duration in
-     * <code>F</code> determines the steady state frame rate that the application will
-     * get if it uses <code>R</code> as a repeating request. Let this special kind
-     * of request be called <code>Rsimple</code>.</p>
+     * <p>If none of the streams in <code>S_r</code> have a stall time (listed in {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }
+     * using its respective size/format), then the frame duration in <code>F</code>
+     * determines the steady state frame rate that the application will get
+     * if it uses <code>R</code> as a repeating request. Let this special kind of
+     * request be called <code>Rsimple</code>.</p>
      * <p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved
      * by a single capture of a new request <code>Rstall</code> (which has at least
      * one in-use stream with a non-0 stall time) and if <code>Rstall</code> has the
@@ -2917,7 +2916,7 @@
      * if all buffers from the previous <code>Rstall</code> have already been
      * delivered.</p>
      * <p>For more details about stalling, see
-     * StreamConfigurationMap#getOutputStallDuration(int,Size).</p>
+     * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration }.</p>
      * <p>This control is only effective if {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} or {@link CaptureRequest#CONTROL_MODE android.control.mode} is set to
      * OFF; otherwise the auto-exposure algorithm will override this value.</p>
      * <p><b>Units</b>: Nanoseconds</p>
@@ -2979,11 +2978,10 @@
      * and are monotonically increasing. They can be compared with the
      * timestamps for other captures from the same camera device, but are
      * not guaranteed to be comparable to any other time source.</p>
-     * <p>When {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE android.sensor.info.timestampSource} <code>==</code> REALTIME,
-     * the timestamps measure time in the same timebase as
-     * android.os.SystemClock#elapsedRealtimeNanos(), and they can be
-     * compared to other timestamps from other subsystems that are using
-     * that base.</p>
+     * <p>When {@link CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE android.sensor.info.timestampSource} <code>==</code> REALTIME, the
+     * timestamps measure time in the same timebase as {@link android.os.SystemClock#elapsedRealtimeNanos }, and they can
+     * be compared to other timestamps from other subsystems that
+     * are using that base.</p>
      * <p><b>Units</b>: Nanoseconds</p>
      * <p><b>Range of valid values:</b><br>
      * &gt; 0</p>
@@ -3141,7 +3139,7 @@
      * <p><b>Units</b>: Nanoseconds</p>
      * <p><b>Range of valid values:</b><br>
      * &gt;= 0 and &lt;
-     * StreamConfigurationMap#getOutputMinFrameDuration(int, Size).</p>
+     * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration }.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Limited capability</b> -
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
@@ -3966,8 +3964,12 @@
      * <p><b>Range of valid values:</b><br>
      * &gt;= 1.0</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * <p><b>Limited capability</b> -
+     * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
+     * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
      *
      * @see CaptureRequest#EDGE_MODE
+     * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see CaptureRequest#NOISE_REDUCTION_MODE
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      */
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index adab9be..02793f1 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -182,6 +182,10 @@
         // The screen auto-brightness adjustment factor in the range -1 (dimmer) to 1 (brighter).
         public float screenAutoBrightnessAdjustment;
 
+        // Set to true if screenBrightness and screenAutoBrightnessAdjustment were both
+        // set by the user as opposed to being programmatically controlled by apps.
+        public boolean brightnessSetByUser;
+
         // If true, enables automatic brightness control.
         public boolean useAutoBrightness;
 
@@ -229,6 +233,7 @@
             useProximitySensor = other.useProximitySensor;
             screenBrightness = other.screenBrightness;
             screenAutoBrightnessAdjustment = other.screenAutoBrightnessAdjustment;
+            brightnessSetByUser = other.brightnessSetByUser;
             useAutoBrightness = other.useAutoBrightness;
             blockScreenOn = other.blockScreenOn;
             lowPowerMode = other.lowPowerMode;
@@ -249,6 +254,7 @@
                     && useProximitySensor == other.useProximitySensor
                     && screenBrightness == other.screenBrightness
                     && screenAutoBrightnessAdjustment == other.screenAutoBrightnessAdjustment
+                    && brightnessSetByUser == other.brightnessSetByUser
                     && useAutoBrightness == other.useAutoBrightness
                     && blockScreenOn == other.blockScreenOn
                     && lowPowerMode == other.lowPowerMode
@@ -268,6 +274,7 @@
                     + ", useProximitySensor=" + useProximitySensor
                     + ", screenBrightness=" + screenBrightness
                     + ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment
+                    + ", brightnessSetByUser=" + brightnessSetByUser
                     + ", useAutoBrightness=" + useAutoBrightness
                     + ", blockScreenOn=" + blockScreenOn
                     + ", lowPowerMode=" + lowPowerMode
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index a7d9503..ca37d49 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -214,7 +214,7 @@
                         sConstructors.put(className, constructor);
                     }
                 }
-
+                constructor.setAccessible(true);
                 return constructor.newInstance(mContext, attrs);
             }
         } catch (InstantiationException e) {
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java
index aefced8..558b8f5 100644
--- a/core/java/android/util/EventLog.java
+++ b/core/java/android/util/EventLog.java
@@ -74,6 +74,7 @@
         private static final byte LONG_TYPE   = 1;
         private static final byte STRING_TYPE = 2;
         private static final byte LIST_TYPE   = 3;
+        private static final byte FLOAT_TYPE = 4;
 
         /** @param data containing event, read from the system */
         /*package*/ Event(byte[] data) {
@@ -106,7 +107,7 @@
             return mBuffer.getInt(offset);
         }
 
-        /** @return one of Integer, Long, String, null, or Object[] of same. */
+        /** @return one of Integer, Long, Float, String, null, or Object[] of same. */
         public synchronized Object getData() {
             try {
                 int offset = mBuffer.getShort(HEADER_SIZE_OFFSET);
@@ -130,10 +131,13 @@
             byte type = mBuffer.get();
             switch (type) {
             case INT_TYPE:
-                return (Integer) mBuffer.getInt();
+                return mBuffer.getInt();
 
             case LONG_TYPE:
-                return (Long) mBuffer.getLong();
+                return mBuffer.getLong();
+
+            case FLOAT_TYPE:
+                return mBuffer.getFloat();
 
             case STRING_TYPE:
                 try {
@@ -180,6 +184,14 @@
     /**
      * Record an event log message.
      * @param tag The event type tag code
+     * @param value A value to log
+     * @return The number of bytes written
+     */
+    public static native int writeEvent(int tag, float value);
+
+    /**
+     * Record an event log message.
+     * @param tag The event type tag code
      * @param str A value to log
      * @return The number of bytes written
      */
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index eedbc70..46dd857 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -234,25 +234,13 @@
      * Draws the specified display list onto this canvas. The display list can only
      * be drawn if {@link android.view.RenderNode#isValid()} returns true.
      *
-     * @param renderNode The RenderNode to replay.
+     * @param renderNode The RenderNode to draw.
      */
     public void drawRenderNode(RenderNode renderNode) {
-        drawRenderNode(renderNode, RenderNode.FLAG_CLIP_CHILDREN);
+        nDrawRenderNode(mNativeCanvasWrapper, renderNode.getNativeDisplayList());
     }
 
-    /**
-     * Draws the specified display list onto this canvas.
-     *
-     * @param renderNode The RenderNode to replay.
-     * @param flags Optional flags about drawing, see {@link RenderNode} for
-     *              the possible flags.
-     */
-    public void drawRenderNode(RenderNode renderNode, int flags) {
-        nDrawRenderNode(mNativeCanvasWrapper, renderNode.getNativeDisplayList(), flags);
-    }
-
-    private static native void nDrawRenderNode(long renderer, long renderNode,
-            int flags);
+    private static native void nDrawRenderNode(long renderer, long renderNode);
 
     ///////////////////////////////////////////////////////////////////////////
     // Hardware layer
diff --git a/core/java/android/view/PhoneWindow.java b/core/java/android/view/PhoneWindow.java
index 794c8e7..a3e7a10 100644
--- a/core/java/android/view/PhoneWindow.java
+++ b/core/java/android/view/PhoneWindow.java
@@ -3599,7 +3599,7 @@
         if (!mForcedNavigationBarColor) {
             mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
         }
-        if (a.getBoolean(R.styleable.Window_windowHasLightStatusBar, false)) {
+        if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
             decor.setSystemUiVisibility(
                     decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
         }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7da2da4..fa74797 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -30,6 +30,7 @@
 import android.annotation.Size;
 import android.content.ClipData;
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
@@ -2591,7 +2592,7 @@
      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
      *         FLAG_TRANSLUCENT_STATUS}.
      *
-     * @see android.R.attr#windowHasLightStatusBar
+     * @see android.R.attr#windowLightStatusBar
      */
     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
 
@@ -4016,37 +4017,7 @@
 
                     final String handlerName = a.getString(attr);
                     if (handlerName != null) {
-                        setOnClickListener(new OnClickListener() {
-                            private Method mHandler;
-
-                            public void onClick(View v) {
-                                if (mHandler == null) {
-                                    try {
-                                        mHandler = getContext().getClass().getMethod(handlerName,
-                                                View.class);
-                                    } catch (NoSuchMethodException e) {
-                                        int id = getId();
-                                        String idText = id == NO_ID ? "" : " with id '"
-                                                + getContext().getResources().getResourceEntryName(
-                                                    id) + "'";
-                                        throw new IllegalStateException("Could not find a method " +
-                                                handlerName + "(View) in the activity "
-                                                + getContext().getClass() + " for onClick handler"
-                                                + " on view " + View.this.getClass() + idText, e);
-                                    }
-                                }
-
-                                try {
-                                    mHandler.invoke(getContext(), View.this);
-                                } catch (IllegalAccessException e) {
-                                    throw new IllegalStateException("Could not execute non "
-                                            + "public method of the activity", e);
-                                } catch (InvocationTargetException e) {
-                                    throw new IllegalStateException("Could not execute "
-                                            + "method of the activity", e);
-                                }
-                            }
-                        });
+                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
                     }
                     break;
                 case R.styleable.View_overScrollMode:
@@ -4238,6 +4209,66 @@
     }
 
     /**
+     * An implementation of OnClickListener that attempts to lazily load a
+     * named click handling method from a parent or ancestor context.
+     */
+    private static class DeclaredOnClickListener implements OnClickListener {
+        private final View mHostView;
+        private final String mMethodName;
+
+        private Method mMethod;
+
+        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
+            mHostView = hostView;
+            mMethodName = methodName;
+        }
+
+        @Override
+        public void onClick(@NonNull View v) {
+            if (mMethod == null) {
+                mMethod = resolveMethod(mHostView.getContext(), mMethodName);
+            }
+
+            try {
+                mMethod.invoke(mHostView.getContext(), v);
+            } catch (IllegalAccessException e) {
+                throw new IllegalStateException(
+                        "Could not execute non-public method for android:onClick", e);
+            } catch (InvocationTargetException e) {
+                throw new IllegalStateException(
+                        "Could not execute method for android:onClick", e);
+            }
+        }
+
+        @NonNull
+        private Method resolveMethod(@Nullable Context context, @NonNull String name) {
+            while (context != null) {
+                try {
+                    if (!context.isRestricted()) {
+                        return context.getClass().getMethod(mMethodName, View.class);
+                    }
+                } catch (NoSuchMethodException e) {
+                    // Failed to find method, keep searching up the hierarchy.
+                }
+
+                if (context instanceof ContextWrapper) {
+                    context = ((ContextWrapper) context).getBaseContext();
+                } else {
+                    // Can't search up the hierarchy, null out and fail.
+                    context = null;
+                }
+            }
+
+            final int id = mHostView.getId();
+            final String idText = id == NO_ID ? "" : " with id '"
+                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
+            throw new IllegalStateException("Could not find method " + mMethodName
+                    + "(View) in a parent or ancestor Context for android:onClick "
+                    + "attribute defined on view " + mHostView.getClass() + idText);
+        }
+    }
+
+    /**
      * Non-public constructor for use in testing
      */
     View() {
@@ -15509,7 +15540,7 @@
         if (!drawingWithDrawingCache) {
             if (drawingWithRenderNode) {
                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
-                ((DisplayListCanvas) canvas).drawRenderNode(renderNode, parentFlags);
+                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
             } else {
                 // Fast path for layouts with no backgrounds
                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index 478fa00..d271af2 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -286,14 +286,10 @@
         return null;
     }
 
-    private boolean isCalendarInRange(Calendar value) {
-        return value.compareTo(mMinDate) >= 0 && value.compareTo(mMaxDate) <= 0;
-    }
-
     private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() {
         @Override
         public void onDayClick(SimpleMonthView view, Calendar day) {
-            if (day != null && isCalendarInRange(day)) {
+            if (day != null) {
                 setSelectedDay(day);
 
                 if (mOnDaySelectedListener != null) {
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index 113e597..334afab 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -178,6 +178,13 @@
         });
     }
 
+    private void updateButtonVisibility(int position) {
+        final boolean hasPrev = position > 0;
+        final boolean hasNext = position < (mAdapter.getCount() - 1);
+        mPrevButton.setVisibility(hasPrev ? View.VISIBLE : View.INVISIBLE);
+        mNextButton.setVisibility(hasNext ? View.VISIBLE : View.INVISIBLE);
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final ViewPager viewPager = mViewPager;
@@ -218,12 +225,6 @@
         final int height = bottom - top;
         mViewPager.layout(0, 0, width, height);
 
-        if (mViewPager.getChildCount() < 1) {
-            leftButton.setVisibility(View.INVISIBLE);
-            rightButton.setVisibility(View.INVISIBLE);
-            return;
-        }
-
         final SimpleMonthView monthView = (SimpleMonthView) mViewPager.getChildAt(0);
         final int monthHeight = monthView.getMonthHeight();
         final int cellWidth = monthView.getCellWidth();
@@ -235,7 +236,6 @@
         final int leftIconTop = monthView.getPaddingTop() + (monthHeight - leftDH) / 2;
         final int leftIconLeft = monthView.getPaddingLeft() + (cellWidth - leftDW) / 2;
         leftButton.layout(leftIconLeft, leftIconTop, leftIconLeft + leftDW, leftIconTop + leftDH);
-        leftButton.setVisibility(View.VISIBLE);
 
         final int rightDW = rightButton.getMeasuredWidth();
         final int rightDH = rightButton.getMeasuredHeight();
@@ -243,7 +243,6 @@
         final int rightIconRight = width - monthView.getPaddingRight() - (cellWidth - rightDW) / 2;
         rightButton.layout(rightIconRight - rightDW, rightIconTop,
                 rightIconRight, rightIconTop + rightDH);
-        rightButton.setVisibility(View.VISIBLE);
     }
 
     public void setDayOfWeekTextAppearance(int resId) {
@@ -399,10 +398,7 @@
 
         @Override
         public void onPageSelected(int position) {
-            mPrevButton.setVisibility(
-                    position > 0 ? View.VISIBLE : View.INVISIBLE);
-            mNextButton.setVisibility(
-                    position < (mAdapter.getCount() - 1) ? View.VISIBLE : View.INVISIBLE);
+            updateButtonVisibility(position);
         }
     };
 
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 39b9907..089074a 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -145,16 +145,16 @@
     InputContentType mInputContentType;
     InputMethodState mInputMethodState;
 
-    private static class TextDisplayList {
-        RenderNode displayList;
+    private static class TextRenderNode {
+        RenderNode renderNode;
         boolean isDirty;
-        public TextDisplayList(String name) {
+        public TextRenderNode(String name) {
             isDirty = true;
-            displayList = RenderNode.create(name, null);
+            renderNode = RenderNode.create(name, null);
         }
-        boolean needsRecord() { return isDirty || !displayList.isValid(); }
+        boolean needsRecord() { return isDirty || !renderNode.isValid(); }
     }
-    TextDisplayList[] mTextDisplayLists;
+    TextRenderNode[] mTextRenderNodes;
 
     boolean mFrozenWithFocus;
     boolean mSelectionMoved;
@@ -360,10 +360,10 @@
     }
 
     private void destroyDisplayListsData() {
-        if (mTextDisplayLists != null) {
-            for (int i = 0; i < mTextDisplayLists.length; i++) {
-                RenderNode displayList = mTextDisplayLists[i] != null
-                        ? mTextDisplayLists[i].displayList : null;
+        if (mTextRenderNodes != null) {
+            for (int i = 0; i < mTextRenderNodes.length; i++) {
+                RenderNode displayList = mTextRenderNodes[i] != null
+                        ? mTextRenderNodes[i].renderNode : null;
                 if (displayList != null && displayList.isValid()) {
                     displayList.destroyDisplayListData();
                 }
@@ -1467,8 +1467,8 @@
                 firstLine, lastLine);
 
         if (layout instanceof DynamicLayout) {
-            if (mTextDisplayLists == null) {
-                mTextDisplayLists = ArrayUtils.emptyArray(TextDisplayList.class);
+            if (mTextRenderNodes == null) {
+                mTextRenderNodes = ArrayUtils.emptyArray(TextRenderNode.class);
             }
 
             DynamicLayout dynamicLayout = (DynamicLayout) layout;
@@ -1489,19 +1489,19 @@
                             searchStartIndex);
                     // Note how dynamic layout's internal block indices get updated from Editor
                     blockIndices[i] = blockIndex;
-                    if (mTextDisplayLists[blockIndex] != null) {
-                        mTextDisplayLists[blockIndex].isDirty = true;
+                    if (mTextRenderNodes[blockIndex] != null) {
+                        mTextRenderNodes[blockIndex].isDirty = true;
                     }
                     searchStartIndex = blockIndex + 1;
                 }
 
-                if (mTextDisplayLists[blockIndex] == null) {
-                    mTextDisplayLists[blockIndex] =
-                            new TextDisplayList("Text " + blockIndex);
+                if (mTextRenderNodes[blockIndex] == null) {
+                    mTextRenderNodes[blockIndex] =
+                            new TextRenderNode("Text " + blockIndex);
                 }
 
-                final boolean blockDisplayListIsInvalid = mTextDisplayLists[blockIndex].needsRecord();
-                RenderNode blockDisplayList = mTextDisplayLists[blockIndex].displayList;
+                final boolean blockDisplayListIsInvalid = mTextRenderNodes[blockIndex].needsRecord();
+                RenderNode blockDisplayList = mTextRenderNodes[blockIndex].renderNode;
                 if (i >= indexFirstChangedBlock || blockDisplayListIsInvalid) {
                     final int blockBeginLine = endOfPreviousBlock + 1;
                     final int top = layout.getLineTop(blockBeginLine);
@@ -1528,7 +1528,7 @@
                             // brings this range of text back to the top left corner of the viewport
                             displayListCanvas.translate(-left, -top);
                             layout.drawText(displayListCanvas, blockBeginLine, blockEndLine);
-                            mTextDisplayLists[blockIndex].isDirty = false;
+                            mTextRenderNodes[blockIndex].isDirty = false;
                             // No need to untranslate, previous context is popped after
                             // drawDisplayList
                         } finally {
@@ -1543,8 +1543,7 @@
                     blockDisplayList.setLeftTopRightBottom(left, top, right, bottom);
                 }
 
-                ((DisplayListCanvas) canvas).drawRenderNode(blockDisplayList,
-                        0 /* no child clipping, our TextView parent enforces it */);
+                ((DisplayListCanvas) canvas).drawRenderNode(blockDisplayList);
 
                 endOfPreviousBlock = blockEndLine;
             }
@@ -1558,7 +1557,7 @@
 
     private int getAvailableDisplayListIndex(int[] blockIndices, int numberOfBlocks,
             int searchStartIndex) {
-        int length = mTextDisplayLists.length;
+        int length = mTextRenderNodes.length;
         for (int i = searchStartIndex; i < length; i++) {
             boolean blockIndexFound = false;
             for (int j = 0; j < numberOfBlocks; j++) {
@@ -1572,7 +1571,7 @@
         }
 
         // No available index found, the pool has to grow
-        mTextDisplayLists = GrowingArrayUtils.append(mTextDisplayLists, length, null);
+        mTextRenderNodes = GrowingArrayUtils.append(mTextRenderNodes, length, null);
         return length;
     }
 
@@ -1589,7 +1588,7 @@
      * Invalidates all the sub-display lists that overlap the specified character range
      */
     void invalidateTextDisplayList(Layout layout, int start, int end) {
-        if (mTextDisplayLists != null && layout instanceof DynamicLayout) {
+        if (mTextRenderNodes != null && layout instanceof DynamicLayout) {
             final int firstLine = layout.getLineForOffset(start);
             final int lastLine = layout.getLineForOffset(end);
 
@@ -1609,7 +1608,7 @@
             while (i < numberOfBlocks) {
                 final int blockIndex = blockIndices[i];
                 if (blockIndex != DynamicLayout.INVALID_BLOCK_INDEX) {
-                    mTextDisplayLists[blockIndex].isDirty = true;
+                    mTextRenderNodes[blockIndex].isDirty = true;
                 }
                 if (blockEndLines[i] >= lastLine) break;
                 i++;
@@ -1618,9 +1617,9 @@
     }
 
     void invalidateTextDisplayList() {
-        if (mTextDisplayLists != null) {
-            for (int i = 0; i < mTextDisplayLists.length; i++) {
-                if (mTextDisplayLists[i] != null) mTextDisplayLists[i].isDirty = true;
+        if (mTextRenderNodes != null) {
+            for (int i = 0; i < mTextRenderNodes.length; i++) {
+                if (mTextRenderNodes[i] != null) mTextRenderNodes[i].isDirty = true;
             }
         }
     }
@@ -4491,7 +4490,7 @@
 
     private class CorrectionHighlighter {
         private final Path mPath = new Path();
-        private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        private final Paint mPaint = new Paint();
         private int mStart, mEnd;
         private long mFadingStartTime;
         private RectF mTempRectF;
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index 2778f0f..acf1df9 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -31,6 +31,7 @@
 import android.text.format.DateFormat;
 import android.util.AttributeSet;
 import android.util.IntArray;
+import android.util.MathUtils;
 import android.util.StateSet;
 import android.view.MotionEvent;
 import android.view.View;
@@ -422,7 +423,8 @@
 
             int stateMask = 0;
 
-            if (day >= mEnabledDayStart && day <= mEnabledDayEnd) {
+            final boolean isDayEnabled = isDayEnabled(day);
+            if (isDayEnabled) {
                 stateMask |= StateSet.VIEW_STATE_ENABLED;
             }
 
@@ -435,8 +437,11 @@
             } else if (mTouchedItem == day) {
                 stateMask |= StateSet.VIEW_STATE_PRESSED;
 
-                // Adjust the circle to be centered on the row.
-                canvas.drawCircle(colCenterRtl, rowCenter, mDaySelectorRadius, mDayHighlightPaint);
+                if (isDayEnabled) {
+                    // Adjust the circle to be centered on the row.
+                    canvas.drawCircle(colCenterRtl, rowCenter,
+                            mDaySelectorRadius, mDayHighlightPaint);
+                }
             }
 
             final boolean isDayToday = mToday == day;
@@ -460,6 +465,14 @@
         }
     }
 
+    private boolean isDayEnabled(int day) {
+        return day >= mEnabledDayStart && day <= mEnabledDayEnd;
+    }
+
+    private boolean isValidDayOfMonth(int day) {
+        return day >= 1 && day <= mDaysInMonth;
+    }
+
     private static boolean isValidDayOfWeek(int day) {
         return day >= Calendar.SUNDAY && day <= Calendar.SATURDAY;
     }
@@ -536,13 +549,6 @@
             mWeekStart = mCalendar.getFirstDayOfWeek();
         }
 
-        if (enabledDayStart > 0 && enabledDayEnd < 32) {
-            mEnabledDayStart = enabledDayStart;
-        }
-        if (enabledDayEnd > 0 && enabledDayEnd < 32 && enabledDayEnd >= enabledDayStart) {
-            mEnabledDayEnd = enabledDayEnd;
-        }
-
         // Figure out what day today is.
         final Calendar today = Calendar.getInstance();
         mToday = -1;
@@ -554,6 +560,9 @@
             }
         }
 
+        mEnabledDayStart = MathUtils.constrain(enabledDayStart, 1, mDaysInMonth);
+        mEnabledDayEnd = MathUtils.constrain(enabledDayEnd, mEnabledDayStart, mDaysInMonth);
+
         // Invalidate the old title.
         mTitle = null;
 
@@ -694,7 +703,7 @@
         final int col = (paddedXRtl * DAYS_IN_WEEK) / mPaddedWidth;
         final int index = col + row * DAYS_IN_WEEK;
         final int day = index + 1 - findDayOffset();
-        if (day < 1 || day > mDaysInMonth) {
+        if (!isValidDayOfMonth(day)) {
             return -1;
         }
 
@@ -708,7 +717,7 @@
      * @param outBounds the rect to populate with bounds
      */
     private boolean getBoundsForDay(int id, Rect outBounds) {
-        if (id < 1 || id > mDaysInMonth) {
+        if (!isValidDayOfMonth(id)) {
             return false;
         }
 
@@ -742,7 +751,7 @@
      * @param day the day that was clicked
      */
     private boolean onDayClicked(int day) {
-        if (day < 0 || day > mDaysInMonth) {
+        if (!isValidDayOfMonth(day) || !isDayEnabled(day)) {
             return false;
         }
 
@@ -774,7 +783,7 @@
         @Override
         protected int getVirtualViewAt(float x, float y) {
             final int day = getDayAtLocation((int) (x + 0.5f), (int) (y + 0.5f));
-            if (day >= 0) {
+            if (day != -1) {
                 return day;
             }
             return ExploreByTouchHelper.INVALID_ID;
@@ -808,7 +817,13 @@
             node.setText(getDayText(virtualViewId));
             node.setContentDescription(getDayDescription(virtualViewId));
             node.setBoundsInParent(mTempRect);
-            node.addAction(AccessibilityAction.ACTION_CLICK);
+
+            final boolean isDayEnabled = isDayEnabled(virtualViewId);
+            if (isDayEnabled) {
+                node.addAction(AccessibilityAction.ACTION_CLICK);
+            }
+
+            node.setEnabled(isDayEnabled);
 
             if (virtualViewId == mActivatedDay) {
                 // TODO: This should use activated once that's supported.
@@ -835,7 +850,7 @@
          * @return a description of the virtual view
          */
         private CharSequence getDayDescription(int id) {
-            if (id >= 1 && id <= mDaysInMonth) {
+            if (isValidDayOfMonth(id)) {
                 mTempCalendar.set(mYear, mMonth, id);
                 return DateFormat.format(DATE_FORMAT, mTempCalendar.getTimeInMillis());
             }
@@ -850,7 +865,7 @@
          * @return the visible text of the virtual view
          */
         private CharSequence getDayText(int id) {
-            if (id >= 1 && id <= mDaysInMonth) {
+            if (isValidDayOfMonth(id)) {
                 return Integer.toString(id);
             }
 
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index ae779fe..f94f97c 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -216,7 +216,7 @@
     public Switch(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
-        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
+        mTextPaint = new TextPaint();
 
         final Resources res = getResources();
         mTextPaint.density = res.getDisplayMetrics().density;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3e8df08..8ce5f08 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -668,11 +668,11 @@
         final Resources res = getResources();
         final CompatibilityInfo compat = res.getCompatibilityInfo();
 
-        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
+        mTextPaint = new TextPaint();
         mTextPaint.density = res.getDisplayMetrics().density;
         mTextPaint.setCompatibilityScaling(compat.applicationScale);
 
-        mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mHighlightPaint = new Paint();
         mHighlightPaint.setCompatibilityScaling(compat.applicationScale);
 
         mMovement = getDefaultMovementMethod();
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 2b77b2c..e347faa 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -405,8 +405,10 @@
                 int launchedFromUid, boolean filterLastUsed, ChooserTarget[] callerChooserTargets) {
             super(context, initialIntents, rList, launchedFromUid, filterLastUsed);
 
-            for (ChooserTarget target : callerChooserTargets) {
-                mCallerTargets.add(new ChooserTargetInfo(target));
+            if (callerChooserTargets != null) {
+                for (ChooserTarget target : callerChooserTargets) {
+                    mCallerTargets.add(new ChooserTargetInfo(target));
+                }
             }
         }
 
diff --git a/core/java/com/android/internal/midi/MidiFramer.java b/core/java/com/android/internal/midi/MidiFramer.java
index 53d71bb..1a7fa0b 100644
--- a/core/java/com/android/internal/midi/MidiFramer.java
+++ b/core/java/com/android/internal/midi/MidiFramer.java
@@ -17,6 +17,7 @@
 package com.android.internal.midi;
 
 import android.media.midi.MidiReceiver;
+import android.util.Log;
 
 import java.io.IOException;
 
@@ -38,6 +39,7 @@
     private int mCount;
     private int mRunningStatus;
     private int mNeeded;
+    private boolean mInSysEx;
 
     public MidiFramer(MidiReceiver receiver) {
         mReceiver = receiver;
@@ -52,12 +54,14 @@
     }
 
     /*
-     * @see android.midi.MidiReceiver#onPost(byte[], int, int, long)
+     * @see android.midi.MidiReceiver#onReceive(byte[], int, int, long)
      */
     @Override
     public void onReceive(byte[] data, int offset, int count, long timestamp)
             throws IOException {
         // Log.i(TAG, formatMidiData(data, offset, count));
+        int sysExStartOffset = (mInSysEx ? offset : -1);
+
         for (int i = 0; i < count; i++) {
             int b = data[offset] & 0xFF;
             if (b >= 0x80) { // status byte?
@@ -66,27 +70,50 @@
                     mCount = 1;
                     mNeeded = MidiConstants.getBytesPerMessage(b) - 1;
                 } else if (b < 0xF8) { // system common?
-                    mBuffer[0] = (byte) b;
-                    mRunningStatus = 0;
-                    mCount = 1;
-                    mNeeded = MidiConstants.getBytesPerMessage(b) - 1;
+                    if (b == 0xF0 /* SysEx Start */) {
+                        // Log.i(TAG, "SysEx Start");
+                        mInSysEx = true;
+                        sysExStartOffset = offset;
+                    } else if (b == 0xF7 /* SysEx End */) {
+                        // Log.i(TAG, "SysEx End");
+                        if (mInSysEx) {
+                            mReceiver.sendWithTimestamp(data, sysExStartOffset,
+                                offset - sysExStartOffset, timestamp);
+                            mInSysEx = false;
+                            sysExStartOffset = -1;
+                        }
+                    } else {
+                        mBuffer[0] = (byte) b;
+                        mRunningStatus = 0;
+                        mCount = 1;
+                        mNeeded = MidiConstants.getBytesPerMessage(b) - 1;
+                    }
                 } else { // real-time?
                     // Single byte message interleaved with other data.
                     mReceiver.sendWithTimestamp(data, offset, 1, timestamp);
                 }
             } else { // data byte
-                mBuffer[mCount++] = (byte) b;
-                if (--mNeeded == 0) {
-                    if (mRunningStatus != 0) {
-                        mBuffer[0] = (byte) mRunningStatus;
+                // Save SysEx data for SysEx End marker or end of buffer.
+                if (!mInSysEx) {
+                    mBuffer[mCount++] = (byte) b;
+                    if (--mNeeded == 0) {
+                        if (mRunningStatus != 0) {
+                            mBuffer[0] = (byte) mRunningStatus;
+                        }
+                        mReceiver.sendWithTimestamp(mBuffer, 0, mCount, timestamp);
+                        mNeeded = MidiConstants.getBytesPerMessage(mBuffer[0]) - 1;
+                        mCount = 1;
                     }
-                    mReceiver.sendWithTimestamp(mBuffer, 0, mCount, timestamp);
-                    mNeeded = MidiConstants.getBytesPerMessage(mBuffer[0]) - 1;
-                    mCount = 1;
                 }
             }
             ++offset;
         }
+
+        // send any accumulatedSysEx data
+        if (sysExStartOffset >= 0) {
+            mReceiver.sendWithTimestamp(data, sysExStartOffset,
+                    offset - sysExStartOffset, timestamp);
+        }
     }
 
 }
diff --git a/core/java/com/android/internal/util/ImageUtils.java b/core/java/com/android/internal/util/ImageUtils.java
index 7d56e9e..a0d0b20 100644
--- a/core/java/com/android/internal/util/ImageUtils.java
+++ b/core/java/com/android/internal/util/ImageUtils.java
@@ -66,7 +66,7 @@
                         COMPACT_BITMAP_SIZE, COMPACT_BITMAP_SIZE, Bitmap.Config.ARGB_8888
                 );
                 mTempCompactBitmapCanvas = new Canvas(mTempCompactBitmap);
-                mTempCompactBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+                mTempCompactBitmapPaint = new Paint();
                 mTempCompactBitmapPaint.setFilterBitmap(true);
             }
             mTempMatrix.reset();
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 1096e34..3d23986 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -17,9 +17,11 @@
 package com.android.internal.widget;
 
 import android.Manifest;
+import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
+import android.bluetooth.BluetoothClass;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -142,11 +144,6 @@
     private DevicePolicyManager mDevicePolicyManager;
     private ILockSettings mLockSettingsService;
 
-    private final boolean mMultiUserMode;
-
-    // The current user is set by KeyguardViewMediator and shared by all LockPatternUtils.
-    private static volatile int sCurrentUserId = UserHandle.USER_NULL;
-
     public DevicePolicyManager getDevicePolicyManager() {
         if (mDevicePolicyManager == null) {
             mDevicePolicyManager =
@@ -171,12 +168,6 @@
     public LockPatternUtils(Context context) {
         mContext = context;
         mContentResolver = context.getContentResolver();
-
-        // If this is being called by the system or by an application like keyguard that
-        // has permision INTERACT_ACROSS_USERS, then LockPatternUtils will operate in multi-user
-        // mode where calls are for the current user rather than the user of the calling process.
-        mMultiUserMode = context.checkCallingOrSelfPermission(
-            Manifest.permission.INTERACT_ACROSS_USERS_FULL) == PackageManager.PERMISSION_GRANTED;
     }
 
     private ILockSettings getLockSettings() {
@@ -188,93 +179,55 @@
         return mLockSettingsService;
     }
 
-    public int getRequestedMinimumPasswordLength() {
-        return getDevicePolicyManager().getPasswordMinimumLength(null, getCurrentOrCallingUserId());
+    public int getRequestedMinimumPasswordLength(int userId) {
+        return getDevicePolicyManager().getPasswordMinimumLength(null, userId);
     }
 
     /**
      * Gets the device policy password mode. If the mode is non-specific, returns
      * MODE_PATTERN which allows the user to choose anything.
      */
-    public int getRequestedPasswordQuality() {
-        return getDevicePolicyManager().getPasswordQuality(null, getCurrentOrCallingUserId());
-    }
-
-    public int getRequestedPasswordHistoryLength() {
-        return getRequestedPasswordHistoryLength(getCurrentOrCallingUserId());
+    public int getRequestedPasswordQuality(int userId) {
+        return getDevicePolicyManager().getPasswordQuality(null, userId);
     }
 
     private int getRequestedPasswordHistoryLength(int userId) {
         return getDevicePolicyManager().getPasswordHistoryLength(null, userId);
     }
 
-    public int getRequestedPasswordMinimumLetters() {
-        return getDevicePolicyManager().getPasswordMinimumLetters(null,
-                getCurrentOrCallingUserId());
+    public int getRequestedPasswordMinimumLetters(int userId) {
+        return getDevicePolicyManager().getPasswordMinimumLetters(null, userId);
     }
 
-    public int getRequestedPasswordMinimumUpperCase() {
-        return getDevicePolicyManager().getPasswordMinimumUpperCase(null,
-                getCurrentOrCallingUserId());
+    public int getRequestedPasswordMinimumUpperCase(int userId) {
+        return getDevicePolicyManager().getPasswordMinimumUpperCase(null, userId);
     }
 
-    public int getRequestedPasswordMinimumLowerCase() {
-        return getDevicePolicyManager().getPasswordMinimumLowerCase(null,
-                getCurrentOrCallingUserId());
+    public int getRequestedPasswordMinimumLowerCase(int userId) {
+        return getDevicePolicyManager().getPasswordMinimumLowerCase(null, userId);
     }
 
-    public int getRequestedPasswordMinimumNumeric() {
-        return getDevicePolicyManager().getPasswordMinimumNumeric(null,
-                getCurrentOrCallingUserId());
+    public int getRequestedPasswordMinimumNumeric(int userId) {
+        return getDevicePolicyManager().getPasswordMinimumNumeric(null, userId);
     }
 
-    public int getRequestedPasswordMinimumSymbols() {
-        return getDevicePolicyManager().getPasswordMinimumSymbols(null,
-                getCurrentOrCallingUserId());
+    public int getRequestedPasswordMinimumSymbols(int userId) {
+        return getDevicePolicyManager().getPasswordMinimumSymbols(null, userId);
     }
 
-    public int getRequestedPasswordMinimumNonLetter() {
-        return getDevicePolicyManager().getPasswordMinimumNonLetter(null,
-                getCurrentOrCallingUserId());
+    public int getRequestedPasswordMinimumNonLetter(int userId) {
+        return getDevicePolicyManager().getPasswordMinimumNonLetter(null, userId);
     }
 
-    public void reportFailedPasswordAttempt() {
-        int userId = getCurrentOrCallingUserId();
+    public void reportFailedPasswordAttempt(int userId) {
         getDevicePolicyManager().reportFailedPasswordAttempt(userId);
         getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
         getTrustManager().reportRequireCredentialEntry(userId);
     }
 
-    public void reportSuccessfulPasswordAttempt() {
-        getDevicePolicyManager().reportSuccessfulPasswordAttempt(getCurrentOrCallingUserId());
-        getTrustManager().reportUnlockAttempt(true /* authenticated */,
-                getCurrentOrCallingUserId());
-    }
-
-    public void setCurrentUser(int userId) {
-        sCurrentUserId = userId;
-    }
-
-    public int getCurrentUser() {
-        if (sCurrentUserId != UserHandle.USER_NULL) {
-            // Someone is regularly updating using setCurrentUser() use that value.
-            return sCurrentUserId;
-        }
-        try {
-            return ActivityManagerNative.getDefault().getCurrentUser().id;
-        } catch (RemoteException re) {
-            return UserHandle.USER_OWNER;
-        }
-    }
-
-    private int getCurrentOrCallingUserId() {
-        if (mMultiUserMode) {
-            // TODO: This is a little inefficient. See if all users of this are able to
-            // handle USER_CURRENT and pass that instead.
-            return getCurrentUser();
-        } else {
-            return UserHandle.getCallingUserId();
-        }
+    public void reportSuccessfulPasswordAttempt(int userId) {
+        getDevicePolicyManager().reportSuccessfulPasswordAttempt(userId);
+        getTrustManager().reportUnlockAttempt(true /* authenticated */, userId);
     }
 
     /**
@@ -286,8 +239,7 @@
      * @param challenge The challenge to verify against the pattern
      * @return the attestation that the challenge was verified, or null.
      */
-    public byte[] verifyPattern(List<LockPatternView.Cell> pattern, long challenge) {
-        final int userId = getCurrentOrCallingUserId();
+    public byte[] verifyPattern(List<LockPatternView.Cell> pattern, long challenge, int userId) {
         try {
             return getLockSettings().verifyPattern(patternToString(pattern), challenge, userId);
         } catch (RemoteException re) {
@@ -301,8 +253,7 @@
      * @param pattern The pattern to check.
      * @return Whether the pattern matches the stored one.
      */
-    public boolean checkPattern(List<LockPatternView.Cell> pattern) {
-        final int userId = getCurrentOrCallingUserId();
+    public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId) {
         try {
             return getLockSettings().checkPattern(patternToString(pattern), userId);
         } catch (RemoteException re) {
@@ -319,8 +270,7 @@
      * @param challenge The challenge to verify against the password
      * @return the attestation that the challenge was verified, or null.
      */
-    public byte[] verifyPassword(String password, long challenge) {
-        final int userId = getCurrentOrCallingUserId();
+    public byte[] verifyPassword(String password, long challenge, int userId) {
         try {
             return getLockSettings().verifyPassword(password, challenge, userId);
         } catch (RemoteException re) {
@@ -334,8 +284,7 @@
      * @param password The password to check.
      * @return Whether the password matches the stored one.
      */
-    public boolean checkPassword(String password) {
-        final int userId = getCurrentOrCallingUserId();
+    public boolean checkPassword(String password, int userId) {
         try {
             return getLockSettings().checkPassword(password, userId);
         } catch (RemoteException re) {
@@ -348,8 +297,7 @@
      * Note that this also clears vold's copy of the password.
      * @return Whether the vold password matches or not.
      */
-    public boolean checkVoldPassword() {
-        final int userId = getCurrentOrCallingUserId();
+    public boolean checkVoldPassword(int userId) {
         try {
             return getLockSettings().checkVoldPassword(userId);
         } catch (RemoteException re) {
@@ -364,8 +312,7 @@
      * @param password The password to check.
      * @return Whether the password matches any in the history.
      */
-    public boolean checkPasswordHistory(String password) {
-        int userId = getCurrentOrCallingUserId();
+    public boolean checkPasswordHistory(String password, int userId) {
         String passwordHashString = new String(
                 passwordToHash(password, userId), StandardCharsets.UTF_8);
         String passwordHistory = getString(PASSWORD_HISTORY_KEY, userId);
@@ -374,7 +321,7 @@
         }
         // Password History may be too long...
         int passwordHashLength = passwordHashString.length();
-        int passwordHistoryLength = getRequestedPasswordHistoryLength();
+        int passwordHistoryLength = getRequestedPasswordHistoryLength(userId);
         if(passwordHistoryLength == 0) {
             return false;
         }
@@ -416,16 +363,8 @@
      *
      * @return True if the user has ever chosen a pattern.
      */
-    public boolean isPatternEverChosen() {
-        return getBoolean(PATTERN_EVER_CHOSEN_KEY, false, getCurrentOrCallingUserId());
-    }
-
-    /**
-     * Used by device policy manager to validate the current password
-     * information it has.
-     */
-    public int getActivePasswordQuality() {
-        return getActivePasswordQuality(getCurrentOrCallingUserId());
+    public boolean isPatternEverChosen(int userId) {
+        return getBoolean(PATTERN_EVER_CHOSEN_KEY, false, userId);
     }
 
     /**
@@ -448,10 +387,6 @@
         return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
     }
 
-    public void clearLock() {
-        clearLock(getCurrentOrCallingUserId());
-    }
-
     /**
      * Clear any lock pattern or password.
      */
@@ -479,16 +414,6 @@
     }
 
     /**
-     * Disable showing lock screen at all when the DevicePolicyManager allows it.
-     * This is only meaningful if pattern, pin or password are not set.
-     *
-     * @param disable Disables lock screen when true
-     */
-    public void setLockScreenDisabled(boolean disable) {
-        setLockScreenDisabled(disable, getCurrentOrCallingUserId());
-    }
-
-    /**
      * Disable showing lock screen at all for a given user.
      * This is only meaningful if pattern, pin or password are not set.
      *
@@ -505,21 +430,16 @@
      *
      * @return true if lock screen is disabled
      */
-    public boolean isLockScreenDisabled() {
-        return !isSecure() &&
-                getBoolean(DISABLE_LOCKSCREEN_KEY, false, getCurrentOrCallingUserId());
+    public boolean isLockScreenDisabled(int userId) {
+        return !isSecure(userId) &&
+                getBoolean(DISABLE_LOCKSCREEN_KEY, false, userId);
     }
 
     /**
      * Save a lock pattern.
      * @param pattern The new pattern to save.
-     * @param savedPattern The previously saved pattern, or null if none
+     * @param userId the user whose pattern is to be saved.
      */
-    public void saveLockPattern(List<LockPatternView.Cell> pattern,
-            String savedPattern) {
-        this.saveLockPattern(pattern, savedPattern, getCurrentOrCallingUserId());
-    }
-
     public void saveLockPattern(List<LockPatternView.Cell> pattern, int userId) {
         this.saveLockPattern(pattern, null, userId);
     }
@@ -588,8 +508,7 @@
         updateCryptoUserInfo(userId);
     }
 
-    public void setOwnerInfoEnabled(boolean enabled) {
-        int userId = getCurrentOrCallingUserId();
+    public void setOwnerInfoEnabled(boolean enabled, int userId) {
         setBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, enabled, userId);
         updateCryptoUserInfo(userId);
     }
@@ -598,11 +517,7 @@
         return getString(LOCK_SCREEN_OWNER_INFO, userId);
     }
 
-    public boolean isOwnerInfoEnabled() {
-        return isOwnerInfoEnabled(getCurrentOrCallingUserId());
-    }
-
-    private boolean isOwnerInfoEnabled(int userId) {
+    public boolean isOwnerInfoEnabled(int userId) {
         return getBoolean(LOCK_SCREEN_OWNER_INFO_ENABLED, false, userId);
     }
 
@@ -724,21 +639,10 @@
     /**
      * Save a lock password.  Does not ensure that the password is as good
      * as the requested mode, but will adjust the mode to be as good as the
-     * pattern.
+     * password.
      * @param password The password to save
      * @param savedPassword The previously saved lock password, or null if none
      * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
-     */
-    public void saveLockPassword(String password, String savedPassword, int quality) {
-        saveLockPassword(password, savedPassword, quality, getCurrentOrCallingUserId());
-    }
-
-    /**
-     * Save a lock password.  Does not ensure that the password is as good
-     * as the requested mode, but will adjust the mode to be as good as the
-     * pattern.
-     * @param password The password to save
-     * @param quality {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
      * @param userHandle The userId of the user to change the password for
      */
     public void saveLockPassword(String password, String savedPassword, int quality,
@@ -865,16 +769,6 @@
     }
 
     /**
-     * Retrieves the quality mode we're in.
-     * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
-     *
-     * @return stored password quality
-     */
-    public int getKeyguardStoredPasswordQuality() {
-        return getKeyguardStoredPasswordQuality(getCurrentOrCallingUserId());
-    }
-
-    /**
      * Retrieves the quality mode for {@param userHandle}.
      * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
      *
@@ -997,13 +891,6 @@
     }
 
     /**
-     * @return Whether the lock screen is secured.
-     */
-    public boolean isSecure() {
-        return isSecure(getCurrentOrCallingUserId());
-    }
-
-    /**
      * @param userId the user for which to report the value
      * @return Whether the lock screen is secured.
      */
@@ -1012,13 +899,6 @@
         return isLockPatternEnabled(mode, userId) || isLockPasswordEnabled(mode, userId);
     }
 
-    /**
-     * @return Whether the lock password is enabled
-     */
-    public boolean isLockPasswordEnabled() {
-        return isLockPasswordEnabled(getCurrentOrCallingUserId());
-    }
-
     public boolean isLockPasswordEnabled(int userId) {
         return isLockPasswordEnabled(getKeyguardStoredPasswordQuality(userId), userId);
     }
@@ -1035,10 +915,6 @@
     /**
      * @return Whether the lock pattern is enabled
      */
-    public boolean isLockPatternEnabled() {
-        return isLockPatternEnabled(getCurrentOrCallingUserId());
-    }
-
     public boolean isLockPatternEnabled(int userId) {
         return isLockPatternEnabled(getKeyguardStoredPasswordQuality(userId), userId);
     }
@@ -1051,16 +927,14 @@
     /**
      * @return Whether the visible pattern is enabled.
      */
-    public boolean isVisiblePatternEnabled() {
-        return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false, getCurrentOrCallingUserId());
+    public boolean isVisiblePatternEnabled(int userId) {
+        return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, false, userId);
     }
 
     /**
      * Set whether the visible pattern is enabled.
      */
-    public void setVisiblePatternEnabled(boolean enabled) {
-        int userId = getCurrentOrCallingUserId();
-
+    public void setVisiblePatternEnabled(boolean enabled, int userId) {
         setBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, enabled, userId);
 
         // Update for crypto if owner
@@ -1095,9 +969,9 @@
      * pattern until the deadline has passed.
      * @return the chosen deadline.
      */
-    public long setLockoutAttemptDeadline() {
+    public long setLockoutAttemptDeadline(int userId) {
         final long deadline = SystemClock.elapsedRealtime() + FAILED_ATTEMPT_TIMEOUT_MS;
-        setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline, getCurrentOrCallingUserId());
+        setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline, userId);
         return deadline;
     }
 
@@ -1106,8 +980,8 @@
      *   attempt to enter his/her lock pattern, or 0 if the user is welcome to
      *   enter a pattern.
      */
-    public long getLockoutAttemptDeadline() {
-        final long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L, getCurrentOrCallingUserId());
+    public long getLockoutAttemptDeadline(int userId) {
+        final long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L, userId);
         final long now = SystemClock.elapsedRealtime();
         if (deadline < now || deadline > (now + FAILED_ATTEMPT_TIMEOUT_MS)) {
             return 0L;
@@ -1166,21 +1040,12 @@
         }
     }
 
-    public void setPowerButtonInstantlyLocks(boolean enabled) {
-        setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled, getCurrentOrCallingUserId());
+    public void setPowerButtonInstantlyLocks(boolean enabled, int userId) {
+        setBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, enabled, userId);
     }
 
-    public boolean getPowerButtonInstantlyLocks() {
-        return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true,
-                getCurrentOrCallingUserId());
-    }
-
-    public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents) {
-        setEnabledTrustAgents(activeTrustAgents, getCurrentOrCallingUserId());
-    }
-
-    public List<ComponentName> getEnabledTrustAgents() {
-        return getEnabledTrustAgents(getCurrentOrCallingUserId());
+    public boolean getPowerButtonInstantlyLocks(int userId) {
+        return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true, userId);
     }
 
     public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId) {
@@ -1192,7 +1057,7 @@
             sb.append(cn.flattenToShortString());
         }
         setString(ENABLED_TRUST_AGENTS, sb.toString(), userId);
-        getTrustManager().reportEnabledTrustAgentsChanged(getCurrentOrCallingUserId());
+        getTrustManager().reportEnabledTrustAgentsChanged(userId);
     }
 
     public List<ComponentName> getEnabledTrustAgents(int userId) {
@@ -1228,7 +1093,7 @@
     }
 
     public void setCredentialRequiredToDecrypt(boolean required) {
-        if (getCurrentUser() != UserHandle.USER_OWNER) {
+        if (ActivityManager.getCurrentUser() != UserHandle.USER_OWNER) {
             Log.w(TAG, "Only device owner may call setCredentialRequiredForDecrypt()");
             return;
         }
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index d86f71a..c384ef9 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -587,9 +587,8 @@
 static jboolean android_media_AudioRecord_setInputDevice(
         JNIEnv *env,  jobject thiz, jint device_id) {
 
-//    sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
-//    return lpRecorder->setInputDevice(device_id) == NO_ERROR;
-    return false;
+    sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+    return lpRecorder->setInputDevice(device_id) == NO_ERROR;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index cfbedda..fb82075 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -200,10 +200,8 @@
          * that can be made while an exception is pending, so we want to
          * get the VM ptr, throw the exception, and then detach the thread.
          */
-        JavaVM* vm = jnienv_to_javavm(env);
         env->Throw(excep);
-        vm->DetachCurrentThread();
-        sleep(60);
+        env->ExceptionDescribe();
         ALOGE("Forcefully exiting");
         exit(1);
     }
diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp
index 5cb8b2e..05bc125 100644
--- a/core/jni/android_util_EventLog.cpp
+++ b/core/jni/android_util_EventLog.cpp
@@ -40,6 +40,9 @@
 static jclass gLongClass;
 static jfieldID gLongValueID;
 
+static jclass gFloatClass;
+static jfieldID gFloatValueID;
+
 static jclass gStringClass;
 
 /*
@@ -66,6 +69,17 @@
 
 /*
  * In class android.util.EventLog:
+ *  static native int writeEvent(long tag, float value)
+ */
+static jint android_util_EventLog_writeEvent_Float(JNIEnv* env UNUSED,
+                                                  jobject clazz UNUSED,
+                                                  jint tag, jfloat value)
+{
+    return android_btWriteLog(tag, EVENT_TYPE_FLOAT, &value, sizeof(value));
+}
+
+/*
+ * In class android.util.EventLog:
  *  static native int writeEvent(int tag, String value)
  */
 static jint android_util_EventLog_writeEvent_String(JNIEnv* env,
@@ -128,6 +142,12 @@
             buf[pos++] = EVENT_TYPE_LONG;
             memcpy(&buf[pos], &longVal, sizeof(longVal));
             pos += sizeof(longVal);
+        } else if (env->IsInstanceOf(item, gFloatClass)) {
+            jfloat floatVal = env->GetFloatField(item, gFloatValueID);
+            if (pos + 1 + sizeof(floatVal) > max) break;
+            buf[pos++] = EVENT_TYPE_FLOAT;
+            memcpy(&buf[pos], &floatVal, sizeof(floatVal));
+            pos += sizeof(floatVal);
         } else {
             jniThrowException(env,
                     "java/lang/IllegalArgumentException",
@@ -233,6 +253,7 @@
     /* name, signature, funcPtr */
     { "writeEvent", "(II)I", (void*) android_util_EventLog_writeEvent_Integer },
     { "writeEvent", "(IJ)I", (void*) android_util_EventLog_writeEvent_Long },
+    { "writeEvent", "(IF)I", (void*) android_util_EventLog_writeEvent_Float },
     { "writeEvent",
       "(ILjava/lang/String;)I",
       (void*) android_util_EventLog_writeEvent_String
@@ -251,6 +272,7 @@
     { "android/util/EventLog$Event", &gEventClass },
     { "java/lang/Integer", &gIntegerClass },
     { "java/lang/Long", &gLongClass },
+    { "java/lang/Float", &gFloatClass },
     { "java/lang/String", &gStringClass },
     { "java/util/Collection", &gCollectionClass },
 };
@@ -258,6 +280,7 @@
 static struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = {
     { &gIntegerClass, "value", "I", &gIntegerValueID },
     { &gLongClass, "value", "J", &gLongValueID },
+    { &gFloatClass, "value", "F", &gFloatValueID },
 };
 
 static struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = {
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index 6bcc92e..a362684 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -112,8 +112,7 @@
         jlong rendererPtr, jlong functorPtr) {
     DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
     Functor* functor = reinterpret_cast<Functor*>(functorPtr);
-    android::uirenderer::Rect dirty;
-    renderer->callDrawGLFunction(functor, dirty);
+    renderer->callDrawGLFunction(functor);
 }
 
 // ----------------------------------------------------------------------------
@@ -212,12 +211,10 @@
 }
 
 static void android_view_DisplayListCanvas_drawRenderNode(JNIEnv* env,
-        jobject clazz, jlong rendererPtr, jlong renderNodePtr,
-        jint flags) {
+        jobject clazz, jlong rendererPtr, jlong renderNodePtr) {
     DisplayListCanvas* renderer = reinterpret_cast<DisplayListCanvas*>(rendererPtr);
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
-    android::uirenderer::Rect bounds;
-    renderer->drawRenderNode(renderNode, bounds, flags);
+    renderer->drawRenderNode(renderNode);
 }
 
 // ----------------------------------------------------------------------------
@@ -283,7 +280,7 @@
     { "nDrawCircle",        "(JJJJJ)V",        (void*) android_view_DisplayListCanvas_drawCircleProps },
 
     { "nFinishRecording",   "(J)J",            (void*) android_view_DisplayListCanvas_finishRecording },
-    { "nDrawRenderNode",    "(JJI)V",          (void*) android_view_DisplayListCanvas_drawRenderNode },
+    { "nDrawRenderNode",    "(JJ)V",           (void*) android_view_DisplayListCanvas_drawRenderNode },
 
     { "nCreateDisplayListCanvas", "()J",     (void*) android_view_DisplayListCanvas_createDisplayListCanvas },
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 018c1a1..45c078d 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1178,13 +1178,13 @@
     <permission android:name="android.permission.REGISTER_CONNECTION_MANAGER"
         android:protectionLevel="system|signature" />
 
-    <!-- @SystemApi Allows an application to bind to InCallService implementations.
-         @hide -->
+    <!-- Must be required by a {@link android.telecom.InCallService},
+         to ensure that only the system can bind to it. -->
     <permission android:name="android.permission.BIND_INCALL_SERVICE"
         android:protectionLevel="system|signature" />
 
-    <!-- @SystemApi Allows an application to bind to ConnectionService implementations.
-         @hide -->
+    <!-- Must be required by a {@link android.telecom.ConnectionService},
+         to ensure that only the system can bind to it. -->
     <permission android:name="android.permission.BIND_CONNECTION_SERVICE"
         android:protectionLevel="system|signature" />
 
diff --git a/core/res/res/color/primary_text_activated_material_dark.xml b/core/res/res/color/primary_text_activated_material_dark.xml
deleted file mode 100644
index f1b742a..0000000
--- a/core/res/res/color/primary_text_activated_material_dark.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_activated="true"
-          android:color="@color/primary_text_default_material_light"/>
-    <item android:color="@color/primary_text_default_material_dark"/>
-</selector>
diff --git a/core/res/res/color/primary_text_activated_material_light.xml b/core/res/res/color/primary_text_activated_material_light.xml
deleted file mode 100644
index d92da63..0000000
--- a/core/res/res/color/primary_text_activated_material_light.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_activated="true"
-          android:color="@color/primary_text_default_material_dark"/>
-    <item android:color="@color/primary_text_default_material_light"/>
-</selector>
diff --git a/core/res/res/color/primary_text_inverse_when_activated_material.xml b/core/res/res/color/primary_text_inverse_when_activated_material.xml
new file mode 100644
index 0000000..0f7f9cdf
--- /dev/null
+++ b/core/res/res/color/primary_text_inverse_when_activated_material.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_enabled="false"
+        android:state_activated="true"
+        android:color="?attr/textColorPrimaryInverse"
+        android:alpha="?attr/disabledAlpha" />
+    <item
+        android:state_enabled="false"
+        android:color="?attr/textColorPrimary"
+        android:alpha="?attr/disabledAlpha" />
+    <item
+        android:state_activated="true"
+        android:color="?attr/textColorPrimaryInverse" />
+    <item
+        android:color="?attr/textColorPrimary" />
+</selector>
diff --git a/core/res/res/color/secondary_text_activated_material_dark.xml b/core/res/res/color/secondary_text_activated_material_dark.xml
deleted file mode 100644
index 7a8428a..0000000
--- a/core/res/res/color/secondary_text_activated_material_dark.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_activated="true"
-          android:color="@color/secondary_text_default_material_light"/>
-    <item android:color="@color/secondary_text_default_material_dark"/>
-</selector>
diff --git a/core/res/res/color/secondary_text_activated_material_light.xml b/core/res/res/color/secondary_text_activated_material_light.xml
deleted file mode 100644
index 36ff408..0000000
--- a/core/res/res/color/secondary_text_activated_material_light.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_activated="true"
-          android:color="@color/secondary_text_default_material_dark"/>
-    <item android:color="@color/secondary_text_default_material_light"/>
-</selector>
diff --git a/core/res/res/color/secondary_text_inverse_when_activated_material.xml b/core/res/res/color/secondary_text_inverse_when_activated_material.xml
new file mode 100644
index 0000000..5b259de
--- /dev/null
+++ b/core/res/res/color/secondary_text_inverse_when_activated_material.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_enabled="false"
+        android:state_activated="true"
+        android:color="?attr/textColorSecondaryInverse"
+        android:alpha="?attr/disabledAlpha" />
+    <item
+        android:state_enabled="false"
+        android:color="?attr/textColorSecondary"
+        android:alpha="?attr/disabledAlpha" />
+    <item
+        android:state_activated="true"
+        android:color="?attr/textColorSecondaryInverse" />
+    <item
+        android:color="?attr/textColorSecondary" />
+</selector>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 887b0a5..a95cc79 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1971,7 +1971,7 @@
              {@link android.R.attr#windowTranslucentStatus}.
              Corresponds to setting {@link android.view.View#SYSTEM_UI_FLAG_LIGHT_STATUS_BAR} on
              the decor view. -->
-        <attr name="windowHasLightStatusBar" format="boolean" />
+        <attr name="windowLightStatusBar" format="boolean" />
     </declare-styleable>
 
     <!-- The set of attributes that describe a AlertDialog's theme. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0c685e0..4631427 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1044,7 +1044,8 @@
 
          <p>NOTE: The value of {@link android.R.attr#screenOrientation} will be ignored for
          resizeable activities as the system doesn't support fixed orientation on a resizeable
-         activity. -->
+         activity.
+         @hide -->
     <attr name="resizeableActivity" format="boolean" />
 
     <!-- This value indicates how tasks rooted at this activity will behave in lockTask mode.
@@ -1796,6 +1797,7 @@
         <attr name="autoRemoveFromRecents" />
         <attr name="relinquishTaskIdentity" />
         <attr name="resumeWhilePausing" />
+        <!-- @hide -->
         <attr name="resizeableActivity" />
         <attr name="lockTaskMode" />
         <attr name="showForAllUsers" />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 7920949..dd4c134 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2610,10 +2610,9 @@
 
   <public type="attr" name="trackTint" />
   <public type="attr" name="trackTintMode" />
-  <public type="attr" name="resizeableActivity" />
   <public type="attr" name="start" />
   <public type="attr" name="end" />
-  <public type="attr" name="windowHasLightStatusBar" />
+  <public type="attr" name="windowLightStatusBar" />
   <public type="attr" name="numbersInnerTextColor" />
   <public type="attr" name="iconTint" />
   <public type="attr" name="iconTintMode" />
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index b0f673c..e679e0a 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -56,11 +56,11 @@
 
         <item name="textColorPrimary">@color/primary_text_material_dark</item>
         <item name="textColorPrimaryInverse">@color/primary_text_material_light</item>
-        <item name="textColorPrimaryActivated">@color/primary_text_activated_material_dark</item>
+        <item name="textColorPrimaryActivated">@color/primary_text_inverse_when_activated_material</item>
         <item name="textColorPrimaryDisableOnly">@color/primary_text_disable_only_material_dark</item>
         <item name="textColorSecondary">@color/secondary_text_material_dark</item>
         <item name="textColorSecondaryInverse">@color/secondary_text_material_light</item>
-        <item name="textColorSecondaryActivated">@color/secondary_text_activated_material_dark</item>
+        <item name="textColorSecondaryActivated">@color/secondary_text_inverse_when_activated_material</item>
         <item name="textColorTertiary">@color/secondary_text_material_dark</item>
         <item name="textColorTertiaryInverse">@color/secondary_text_material_light</item>
         <item name="textColorHint">@color/hint_foreground_material_dark</item>
@@ -410,10 +410,10 @@
 
         <item name="textColorPrimary">@color/primary_text_material_light</item>
         <item name="textColorPrimaryInverse">@color/primary_text_material_dark</item>
-        <item name="textColorPrimaryActivated">@color/primary_text_activated_material_light</item>
+        <item name="textColorPrimaryActivated">@color/primary_text_inverse_when_activated_material</item>
         <item name="textColorSecondary">@color/secondary_text_material_light</item>
         <item name="textColorSecondaryInverse">@color/secondary_text_material_dark</item>
-        <item name="textColorSecondaryActivated">@color/secondary_text_activated_material_light</item>
+        <item name="textColorSecondaryActivated">@color/secondary_text_inverse_when_activated_material</item>
         <item name="textColorTertiary">@color/secondary_text_material_light</item>
         <item name="textColorTertiaryInverse">@color/secondary_text_material_dark</item>
         <item name="textColorPrimaryDisableOnly">@color/primary_text_disable_only_material_light</item>
@@ -760,7 +760,7 @@
          status bar contents. -->
     <style name="Theme.Material.Light.LightStatusBar">
         <item name="colorPrimaryDark">@color/primary_dark_material_light_light_status_bar</item>
-        <item name="windowHasLightStatusBar">true</item>
+        <item name="windowLightStatusBar">true</item>
     </style>
 
     <style name="ThemeOverlay" />
@@ -777,10 +777,8 @@
 
         <item name="textColorPrimary">@color/primary_text_material_light</item>
         <item name="textColorPrimaryInverse">@color/primary_text_material_dark</item>
-        <item name="textColorPrimaryActivated">@color/primary_text_activated_material_light</item>
         <item name="textColorSecondary">@color/secondary_text_material_light</item>
         <item name="textColorSecondaryInverse">@color/secondary_text_material_dark</item>
-        <item name="textColorSecondaryActivated">@color/secondary_text_activated_material_light</item>
         <item name="textColorTertiary">@color/secondary_text_material_light</item>
         <item name="textColorTertiaryInverse">@color/secondary_text_material_dark</item>
         <item name="textColorPrimaryDisableOnly">@color/primary_text_disable_only_material_light</item>
@@ -814,11 +812,9 @@
 
         <item name="textColorPrimary">@color/primary_text_material_dark</item>
         <item name="textColorPrimaryInverse">@color/primary_text_material_light</item>
-        <item name="textColorPrimaryActivated">@color/primary_text_activated_material_dark</item>
         <item name="textColorPrimaryDisableOnly">@color/primary_text_disable_only_material_dark</item>
         <item name="textColorSecondary">@color/secondary_text_material_dark</item>
         <item name="textColorSecondaryInverse">@color/secondary_text_material_light</item>
-        <item name="textColorSecondaryActivated">@color/secondary_text_activated_material_dark</item>
         <item name="textColorTertiary">@color/secondary_text_material_dark</item>
         <item name="textColorTertiaryInverse">@color/secondary_text_material_light</item>
         <item name="textColorHint">@color/hint_foreground_material_dark</item>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index e04c214..4b82c3d 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -184,10 +184,10 @@
         result.putInt("ap-discovered", ssidAppearInScanResultsCount);
         getInstrumentation().sendStatus(Activity.RESULT_FIRST_USER, result);
         if (i == mScanIterations + 1) {
-            writeOutput(String.format("iteration %d out of %d", i, mScanIterations));
+            writeOutput(String.format("iteration %d out of %d", i - 1, mScanIterations));
             writeOutput(String.format("average scanning time is %d", scanTimeSum / (i - 1)));
             writeOutput(String.format("ssid appear %d out of %d scan iterations",
-                    ssidAppearInScanResultsCount, i));
+                    ssidAppearInScanResultsCount, i - 1));
         }
     }
 
@@ -289,7 +289,7 @@
         getInstrumentation().sendStatus(Activity.RESULT_FIRST_USER, result);
         if (i == mReconnectIterations + 1) {
             writeOutput(String.format("iteration %d out of %d",
-                    i, mReconnectIterations));
+                    i - 1, mReconnectIterations));
         }
     }
 }
diff --git a/docs/html/distribute/tools/promote/brand.jd b/docs/html/distribute/tools/promote/brand.jd
index a12e753..cf83a5e 100644
--- a/docs/html/distribute/tools/promote/brand.jd
+++ b/docs/html/distribute/tools/promote/brand.jd
@@ -37,6 +37,18 @@
       <p>If used with your logo, "for Android" should be no larger than 90% of your logo’s size.
       First instance of this use should be followed by a TM symbol, "for Android&trade;".</p>
     </li>
+    <li>"Android TV", "Android Wear" and "Android Auto" may only be used to identify or market
+      products or services with prior approval.  Use "for Android" or "with Android" for all
+      other Android-based products
+      <ul>
+        <li><span style="color:red">Incorrect</span>: "Android TV Streaming Stick",
+          "Streaming Stick with Android TV"</li>
+        <li><span style="color:green">Correct</span>: "Streaming Stick with Android"</li>
+      </ul>
+      <p>If used with your logo, "for Android" or "with Android" should be no larger than 90% of
+        your logo’s size. First instance of this use should be followed by a TM symbol,
+        "for Android&trade;".</p>
+    </li>
     <li>Android may be used as a descriptor, as long as it is followed by a
         proper generic term. (Think of "Android" as a term used in place of
         "the Android platform.")
diff --git a/docs/html/training/wearables/data-layer/messages.jd b/docs/html/training/wearables/data-layer/messages.jd
index 043aff2..ef9bfb1 100644
--- a/docs/html/training/wearables/data-layer/messages.jd
+++ b/docs/html/training/wearables/data-layer/messages.jd
@@ -34,7 +34,7 @@
 
 <p>Multiple wearable devices can be connected to a user’s handheld device. Each connected device in
 the network is considered a <em>node</em>. With multiple connected devices, you must consider which
-nodes receive the messages. For example, In a voice transcription app that receives voice data on
+nodes receive the messages. For example, in a voice transcription app that receives voice data on
 the wearable device, you should send the message to a node with the processing power and battery
 capacity to handle the request, such as a handheld device.</p>
 
@@ -196,7 +196,15 @@
 
 <p>The following example shows how to send a message to the transcription-capable node from a
 wearable device. Verify that the node is available before you attempt to send the message. This call
-is synchronous and blocks processing until the message is received or until the request times out.
+is synchronous and blocks processing until the system queues the message for delivery.
+</p>
+
+<p class="note"><strong>Note:</strong> A successful result code does not guarantee delivery of the
+message. If your app requires data reliability, use
+<a href="{@docRoot}reference/com/google/android/gms/wearable/DataItem.html"><code>DataItem</code></a>
+objects or the
+<a href="{@docRoot}reference/com/google/android/gms/wearable/ChannelApi.html"><code>ChannelApi</code></a>
+class to send data between devices.
 </p>
 
 <pre>
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 4c2817c..dc9aa67 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -133,7 +133,7 @@
 
     private GradientState mGradientState;
 
-    private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+    private final Paint mFillPaint = new Paint();
     private Rect mPadding;
     private Paint mStrokePaint;   // optional, set by the caller
     private ColorFilter mColorFilter;   // optional, set by the caller
@@ -323,7 +323,7 @@
 
     private void setStrokeInternal(int width, int color, float dashWidth, float dashGap) {
         if (mStrokePaint == null)  {
-            mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            mStrokePaint = new Paint();
             mStrokePaint.setStyle(Paint.Style.STROKE);
         }
         mStrokePaint.setStrokeWidth(width);
@@ -1802,7 +1802,7 @@
         mPadding = state.mPadding;
 
         if (state.mStrokeWidth >= 0) {
-            mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            mStrokePaint = new Paint();
             mStrokePaint.setStyle(Paint.Style.STROKE);
             mStrokePaint.setStrokeWidth(state.mStrokeWidth);
 
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 3bbbc71..c3d8cfa 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -1464,7 +1464,8 @@
                     bounds.right - insetR - padR, bounds.bottom - r.mInsetB - padB);
 
             // Apply resolved gravity to drawable based on resolved size.
-            final int gravity = resolveGravity(r.mGravity, r.mWidth, r.mHeight);
+            final int gravity = resolveGravity(r.mGravity, r.mWidth, r.mHeight,
+                    d.getIntrinsicWidth(), d.getIntrinsicHeight());
             final int w = r.mWidth < 0 ? d.getIntrinsicWidth() : r.mWidth;
             final int h = r.mHeight < 0 ? d.getIntrinsicHeight() : r.mHeight;
             Gravity.apply(gravity, w, h, container, outRect, layoutDirection);
@@ -1491,7 +1492,8 @@
      * @param height height of the layer if set, -1 otherwise
      * @return the default gravity for the layer
      */
-    private static int resolveGravity(int gravity, int width, int height) {
+    private static int resolveGravity(int gravity, int width, int height,
+            int intrinsicWidth, int intrinsicHeight) {
         if (!Gravity.isHorizontal(gravity)) {
             if (width < 0) {
                 gravity |= Gravity.FILL_HORIZONTAL;
@@ -1508,6 +1510,17 @@
             }
         }
 
+        // If a dimension if not specified, either implicitly or explicitly,
+        // force FILL for that dimension's gravity. This ensures that colors
+        // are handled correctly and ensures backward compatibility.
+        if (width < 0 && intrinsicWidth < 0) {
+            gravity |= Gravity.FILL_HORIZONTAL;
+        }
+
+        if (height < 0 && intrinsicHeight < 0) {
+            gravity |= Gravity.FILL_VERTICAL;
+        }
+
         return gravity;
     }
 
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 334b3bd..caa0787 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -501,7 +501,7 @@
             if (mShapeState.mPaint != null) {
                 mShapeState.mPaint = new Paint(mShapeState.mPaint);
             } else {
-                mShapeState.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+                mShapeState.mPaint = new Paint();
             }
             if (mShapeState.mPadding != null) {
                 mShapeState.mPadding = new Rect(mShapeState.mPadding);
@@ -555,7 +555,7 @@
                 mAlpha = orig.mAlpha;
                 mShaderFactory = orig.mShaderFactory;
             } else {
-                mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+                mPaint = new Paint();
             }
         }
 
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index 6b86030..a7784b6 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -88,8 +88,7 @@
 void DisplayListCanvas::resume() {
 }
 
-void DisplayListCanvas::callDrawGLFunction(Functor *functor, Rect& dirty) {
-    // Ignore dirty during recording, it matters only when we replay
+void DisplayListCanvas::callDrawGLFunction(Functor *functor) {
     addDrawOp(new (alloc()) DrawFunctorOp(functor));
     mDisplayListData->functors.add(functor);
 }
@@ -202,12 +201,12 @@
     return mState.clipRegion(region, op);
 }
 
-void DisplayListCanvas::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t flags) {
+void DisplayListCanvas::drawRenderNode(RenderNode* renderNode) {
     LOG_ALWAYS_FATAL_IF(!renderNode, "missing rendernode");
 
     // dirty is an out parameter and should not be recorded,
     // it matters only when replaying the display list
-    DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *mState.currentTransform());
+    DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, *mState.currentTransform());
     addRenderNodeOp(op);
 }
 
diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h
index 2b0b6b2..fa4b2b4 100644
--- a/libs/hwui/DisplayListCanvas.h
+++ b/libs/hwui/DisplayListCanvas.h
@@ -115,10 +115,10 @@
 // HWUI Canvas draw operations - special
 // ----------------------------------------------------------------------------
     void drawLayer(DeferredLayerUpdater* layerHandle, float x, float y);
-    void drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t replayFlags);
+    void drawRenderNode(RenderNode* renderNode);
 
     // TODO: rename for consistency
-    void callDrawGLFunction(Functor* functor, Rect& dirty);
+    void callDrawGLFunction(Functor* functor);
 
     void setHighContrastText(bool highContrastText) {
         mHighContrastText = highContrastText;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index b5801fc..4863ed2 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1398,10 +1398,9 @@
     friend class RenderNode; // grant RenderNode access to info of child
     friend class DisplayListData; // grant DisplayListData access to info of child
 public:
-    DrawRenderNodeOp(RenderNode* renderNode, int flags, const mat4& transformFromParent)
+    DrawRenderNodeOp(RenderNode* renderNode, const mat4& transformFromParent)
             : DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), nullptr)
             , mRenderNode(renderNode)
-            , mFlags(flags)
             , mTransformFromParent(transformFromParent)
             , mSkipInOrderDraw(false) {}
 
@@ -1424,7 +1423,7 @@
     }
 
     virtual void output(int level, uint32_t logFlags) const override {
-        OP_LOG("Draw RenderNode %p %s, flags %#x", mRenderNode, mRenderNode->getName(), mFlags);
+        OP_LOG("Draw RenderNode %p %s, flags %#x", mRenderNode, mRenderNode->getName());
         if (mRenderNode && (logFlags & kOpLogFlag_Recurse)) {
             mRenderNode->output(level + 1);
         }
@@ -1436,7 +1435,6 @@
 
 private:
     RenderNode* mRenderNode;
-    const int mFlags;
 
     ///////////////////////////
     // Properties below are used by RenderNode::computeOrderingImpl() and issueOperations()
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index 61ad082..62782af 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -111,15 +111,13 @@
 public:
     std::vector< sp<RenderNode> > cards;
     void createContent(int width, int height, DisplayListCanvas* renderer) override {
-        android::uirenderer::Rect DUMMY;
-
         renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
         renderer->insertReorderBarrier(true);
 
         for (int x = dp(16); x < (width - dp(116)); x += dp(116)) {
             for (int y = dp(16); y < (height - dp(116)); y += dp(116)) {
                 sp<RenderNode> card = createCard(x, y, dp(100), dp(100));
-                renderer->drawRenderNode(card.get(), DUMMY, 0);
+                renderer->drawRenderNode(card.get());
                 cards.push_back(card);
             }
         }
@@ -153,13 +151,11 @@
 public:
     sp<RenderNode> card;
     void createContent(int width, int height, DisplayListCanvas* renderer) override {
-        android::uirenderer::Rect DUMMY;
-
         renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
         renderer->insertReorderBarrier(true);
 
         card = createCard(40, 40, 200, 200);
-        renderer->drawRenderNode(card.get(), DUMMY, 0);
+        renderer->drawRenderNode(card.get());
 
         renderer->insertReorderBarrier(false);
     }
@@ -202,13 +198,11 @@
 public:
     sp<RenderNode> card;
     void createContent(int width, int height, DisplayListCanvas* renderer) override {
-        android::uirenderer::Rect DUMMY;
-
         renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
         renderer->insertReorderBarrier(true);
 
         card = createCard(40, 40, 400, 400);
-        renderer->drawRenderNode(card.get(), DUMMY, 0);
+        renderer->drawRenderNode(card.get());
 
         renderer->insertReorderBarrier(false);
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index 1699809..25b1875 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -120,7 +120,7 @@
             KeyguardUpdateMonitor.getInstance(mContext).reportEmergencyCallAction(
                     true /* bypassHandler */);
             getContext().startActivityAsUser(INTENT_EMERGENCY_DIAL,
-                    new UserHandle(mLockPatternUtils.getCurrentUser()));
+                    new UserHandle(KeyguardUpdateMonitor.getCurrentUser()));
         }
     }
 
@@ -138,7 +138,7 @@
                     visible = mEnableEmergencyCallWhileSimLocked;
                 } else {
                     // Only show if there is a secure screen (pin/pattern/SIM pin/SIM puk);
-                    visible = mLockPatternUtils.isSecure();
+                    visible = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser());
                 }
             }
         }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 322be91..c4f4b9a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -63,7 +63,8 @@
         // start fresh
         resetPasswordText(false /* animate */);
         // if the user is currently locked out, enforce it.
-        long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
+        long deadline = mLockPatternUtils.getLockoutAttemptDeadline(
+                KeyguardUpdateMonitor.getCurrentUser());
         if (shouldLockout(deadline)) {
             handleAttemptLockout(deadline);
         } else {
@@ -106,7 +107,7 @@
 
     protected void verifyPasswordAndUnlock() {
         String entry = getPasswordText();
-        if (mLockPatternUtils.checkPassword(entry)) {
+        if (mLockPatternUtils.checkPassword(entry, KeyguardUpdateMonitor.getCurrentUser())) {
             mCallback.reportUnlockAttempt(true);
             mCallback.dismiss(true);
         } else {
@@ -116,7 +117,8 @@
                 mCallback.reportUnlockAttempt(false);
                 int attempts = KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts();
                 if (0 == (attempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
-                    long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
+                    long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
+                            KeyguardUpdateMonitor.getCurrentUser());
                     handleAttemptLockout(deadline);
                 }
             }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index be71b034..2cf30ba 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -71,7 +71,7 @@
 
         @Override
         public void onTrustGrantedWithFlags(int flags, int userId) {
-            if (userId != mLockPatternUtils.getCurrentUser()) return;
+            if (userId != KeyguardUpdateMonitor.getCurrentUser()) return;
             if (!isAttachedToWindow()) return;
             boolean bouncerVisible = isVisibleToUser();
             boolean initiatedByUser =
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 9aa5729..557cd13 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -130,7 +130,8 @@
         mLockPatternView.setOnPatternListener(new UnlockPatternListener());
 
         // stealth mode will be the same for the life of this screen
-        mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled());
+        mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
+                KeyguardUpdateMonitor.getCurrentUser()));
 
         // vibrate mode will be the same for the life of this screen
         mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
@@ -176,7 +177,8 @@
         mLockPatternView.clearPattern();
 
         // if the user is currently locked out, enforce it.
-        long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
+        long deadline = mLockPatternUtils.getLockoutAttemptDeadline(
+                KeyguardUpdateMonitor.getCurrentUser());
         if (deadline != 0) {
             handleAttemptLockout(deadline);
         } else {
@@ -213,7 +215,7 @@
         }
 
         public void onPatternDetected(List<LockPatternView.Cell> pattern) {
-            if (mLockPatternUtils.checkPattern(pattern)) {
+            if (mLockPatternUtils.checkPattern(pattern, KeyguardUpdateMonitor.getCurrentUser())) {
                 mCallback.reportUnlockAttempt(true);
                 mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
                 mCallback.dismiss(true);
@@ -230,7 +232,8 @@
                 int attempts = mKeyguardUpdateMonitor.getFailedUnlockAttempts();
                 if (registeredAttempt &&
                         0 == (attempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
-                    long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
+                    long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
+                            KeyguardUpdateMonitor.getCurrentUser());
                     handleAttemptLockout(deadline);
                 } else {
                     mSecurityMessageDisplay.setMessage(R.string.kg_wrong_pattern, true);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 5af7783..ae4baad 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -261,7 +261,7 @@
 
         SecurityMode mode = mSecurityModel.getSecurityMode();
         final boolean usingPattern = mode == KeyguardSecurityModel.SecurityMode.Pattern;
-        final int currentUser = mLockPatternUtils.getCurrentUser();
+        final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
         final DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
         final int failedAttemptsBeforeWipe =
                 dpm.getMaximumFailedPasswordsForWipe(null, currentUser);
@@ -296,7 +296,7 @@
                 (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0;
         }
         monitor.reportFailedUnlockAttempt();
-        mLockPatternUtils.reportFailedPasswordAttempt();
+        mLockPatternUtils.reportFailedPasswordAttempt(KeyguardUpdateMonitor.getCurrentUser());
         if (showTimeout) {
             showTimeoutDialog();
         }
@@ -321,7 +321,7 @@
     boolean showNextSecurityScreenOrFinish(boolean authenticated) {
         if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
         boolean finish = false;
-        if (mUpdateMonitor.getUserHasTrust(mLockPatternUtils.getCurrentUser())) {
+        if (mUpdateMonitor.getUserHasTrust(KeyguardUpdateMonitor.getCurrentUser())) {
             finish = true;
         } else if (SecurityMode.None == mCurrentSecuritySelection) {
             SecurityMode securityMode = mSecurityModel.getSecurityMode();
@@ -430,7 +430,8 @@
             KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
             if (success) {
                 monitor.clearFailedUnlockAttempts();
-                mLockPatternUtils.reportSuccessfulPasswordAttempt();
+                mLockPatternUtils.reportSuccessfulPasswordAttempt(
+                        KeyguardUpdateMonitor.getCurrentUser());
             } else {
                 KeyguardSecurityContainer.this.reportFailedUnlockAttempt();
             }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
index 3eb31ad..454221a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -67,7 +67,8 @@
             return SecurityMode.SimPuk;
         }
 
-        final int security = mLockPatternUtils.getActivePasswordQuality();
+        final int security = mLockPatternUtils.getActivePasswordQuality(
+                KeyguardUpdateMonitor.getCurrentUser());
         switch (security) {
             case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
             case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
index af6360a..4e9621a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
@@ -200,9 +200,10 @@
     private String getOwnerInfo() {
         ContentResolver res = getContext().getContentResolver();
         String info = null;
-        final boolean ownerInfoEnabled = mLockPatternUtils.isOwnerInfoEnabled();
+        final boolean ownerInfoEnabled = mLockPatternUtils.isOwnerInfoEnabled(
+                KeyguardUpdateMonitor.getCurrentUser());
         if (ownerInfoEnabled) {
-            info = mLockPatternUtils.getOwnerInfo(mLockPatternUtils.getCurrentUser());
+            info = mLockPatternUtils.getOwnerInfo(KeyguardUpdateMonitor.getCurrentUser());
         }
         return info;
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 1eec5325..b8d9053 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -244,6 +244,16 @@
     private SparseBooleanArray mUserFingerprintAuthenticated = new SparseBooleanArray();
     private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
 
+    private static int sCurrentUser;
+
+    public synchronized static void setCurrentUser(int currentUser) {
+        sCurrentUser = currentUser;
+    }
+
+    public synchronized static int getCurrentUser() {
+        return sCurrentUser;
+    }
+
     @Override
     public void onTrustChanged(boolean enabled, int userId, int flags) {
         mUserHasTrust.put(userId, enabled);
@@ -669,7 +679,7 @@
                 cb.onScreenTurnedOn();
             }
         }
-        startListeningForFingerprint();
+        updateFingerprintListeningState();
     }
 
     protected void handleScreenTurnedOff(int arg1) {
@@ -681,7 +691,7 @@
                 cb.onScreenTurnedOff(arg1);
             }
         }
-        stopListeningForFingerprint();
+        updateFingerprintListeningState();
     }
 
     /**
@@ -754,14 +764,14 @@
                             mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
                                     newUserId, 0, reply));
                             mSwitchingUser = true;
-                            stopListeningForFingerprint();
+                            updateFingerprintListeningState();
                         }
                         @Override
                         public void onUserSwitchComplete(int newUserId) throws RemoteException {
                             mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
                                     newUserId, 0));
                             mSwitchingUser = false;
-                            startListeningForFingerprint();
+                            updateFingerprintListeningState();
                         }
                         @Override
                         public void onForegroundProfileSwitch(int newProfileId) {
@@ -777,7 +787,20 @@
         trustManager.registerTrustListener(this);
 
         mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
-        startListeningForFingerprint();
+        updateFingerprintListeningState();
+    }
+
+    private void updateFingerprintListeningState() {
+        boolean shouldListenForFingerprint = shouldListenForFingerprint();
+        if (mFingerprintDetectionRunning && !shouldListenForFingerprint) {
+            stopListeningForFingerprint();
+        } else if (!mFingerprintDetectionRunning && shouldListenForFingerprint) {
+            startListeningForFingerprint();
+        }
+    }
+
+    private boolean shouldListenForFingerprint() {
+        return mScreenOn && mKeyguardIsVisible && !mSwitchingUser;
     }
 
     private void startListeningForFingerprint() {
@@ -794,7 +817,7 @@
         }
     }
 
-    public void stopListeningForFingerprint() {
+    private void stopListeningForFingerprint() {
         if (DEBUG) Log.v(TAG, "stopListeningForFingerprint()");
         if (isFingerprintDetectionRunning()) {
             mFingerprintCancelSignal.cancel();
@@ -1052,6 +1075,7 @@
                 cb.onKeyguardVisibilityChangedRaw(isShowing);
             }
         }
+        updateFingerprintListeningState();
     }
 
     /**
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 870f043..7bf2223 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -2066,7 +2066,7 @@
                     LockPatternUtils lpu = new LockPatternUtils(mContext);
                     List<LockPatternView.Cell> cellPattern =
                             LockPatternUtils.stringToPattern(lockPattern);
-                    lpu.saveLockPattern(cellPattern, null);
+                    lpu.saveLockPattern(cellPattern, null, UserHandle.USER_OWNER);
                 } catch (IllegalArgumentException e) {
                     // Don't want corrupted lock pattern to hang the reboot process
                 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 7f826ef..d99f741 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -754,7 +754,7 @@
      */
     private byte[] getLockSettings() {
         final LockPatternUtils lockPatternUtils = new LockPatternUtils(this);
-        final boolean ownerInfoEnabled = lockPatternUtils.isOwnerInfoEnabled();
+        final boolean ownerInfoEnabled = lockPatternUtils.isOwnerInfoEnabled(UserHandle.myUserId());
         final String ownerInfo = lockPatternUtils.getOwnerInfo(UserHandle.myUserId());
 
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -871,7 +871,8 @@
                 }
                 switch (key) {
                     case KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED:
-                        lockPatternUtils.setOwnerInfoEnabled("1".equals(value));
+                        lockPatternUtils.setOwnerInfoEnabled("1".equals(value),
+                                UserHandle.myUserId());
                         break;
                     case KEY_LOCK_SETTINGS_OWNER_INFO:
                         lockPatternUtils.setOwnerInfo(value, UserHandle.myUserId());
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_fingerprint_ridges_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_fingerprint_ridges_animation.xml
new file mode 100644
index 0000000..c6a4622
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_fingerprint_ridges_animation.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="100"
+            android:propertyName="rotation"
+            android:valueFrom="0.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="566"
+            android:propertyName="rotation"
+            android:valueFrom="0.0"
+            android:valueTo="-305.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_3" />
+        <objectAnimator
+            android:duration="1066"
+            android:propertyName="rotation"
+            android:valueFrom="-305.0"
+            android:valueTo="-305.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0" />
+        <objectAnimator
+            android:duration="800"
+            android:propertyName="rotation"
+            android:valueFrom="-305.0"
+            android:valueTo="-720.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_group_1_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_group_1_animation.xml
new file mode 100644
index 0000000..0e2c2f0
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_group_1_animation.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="183"
+            android:propertyName="rotation"
+            android:valueFrom="285.0"
+            android:valueTo="285.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="516"
+            android:propertyName="rotation"
+            android:valueFrom="285.0"
+            android:valueTo="90.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_1" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_group_2_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_group_2_animation.xml
new file mode 100644
index 0000000..c01010d
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_group_2_animation.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="283"
+            android:propertyName="scaleX"
+            android:valueFrom="0.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="316"
+            android:propertyName="scaleX"
+            android:valueFrom="0.0"
+            android:valueTo="1.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_1" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="283"
+            android:propertyName="scaleY"
+            android:valueFrom="0.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="316"
+            android:propertyName="scaleY"
+            android:valueFrom="0.0"
+            android:valueTo="1.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_1" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="283"
+            android:propertyName="rotation"
+            android:valueFrom="184.0"
+            android:valueTo="184.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="316"
+            android:propertyName="rotation"
+            android:valueFrom="184.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_1" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_path_3_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_path_3_animation.xml
new file mode 100644
index 0000000..454be24
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_path_3_animation.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="233"
+            android:propertyName="trimPathStart"
+            android:valueFrom="1.0"
+            android:valueTo="1.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="466"
+            android:propertyName="trimPathStart"
+            android:valueFrom="1.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_1_path_0_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_1_path_0_animation.xml
new file mode 100644
index 0000000..faeecf4
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_1_path_0_animation.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="133"
+        android:propertyName="trimPathEnd"
+        android:valueFrom="0.0"
+        android:valueTo="1.0"
+        android:valueType="floatType"
+        android:interpolator="@android:interpolator/fast_out_slow_in" />
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="100"
+            android:propertyName="trimPathStart"
+            android:valueFrom="0.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="100"
+            android:propertyName="trimPathStart"
+            android:valueFrom="0.0"
+            android:valueTo="1.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_2" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_1_path_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_1_path_animation.xml
new file mode 100644
index 0000000..3bacf03
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_1_path_animation.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="16"
+            android:propertyName="trimPathStart"
+            android:valueFrom="0.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="66"
+            android:propertyName="trimPathStart"
+            android:valueFrom="0.0"
+            android:valueTo="1.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_2_path_0_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_2_path_0_animation.xml
new file mode 100644
index 0000000..80a0faa
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_2_path_0_animation.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="116"
+            android:propertyName="trimPathEnd"
+            android:valueFrom="1.0"
+            android:valueTo="1.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="116"
+            android:propertyName="trimPathEnd"
+            android:valueFrom="1.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_3" />
+    </set>
+    <objectAnimator
+        android:duration="166"
+        android:propertyName="trimPathStart"
+        android:valueFrom="1.0"
+        android:valueTo="0.0"
+        android:valueType="floatType"
+        android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_3" />
+</set>
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_2_path_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_2_path_animation.xml
new file mode 100644
index 0000000..3a18296
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_2_path_animation.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="16"
+            android:propertyName="trimPathEnd"
+            android:valueFrom="1.0"
+            android:valueTo="1.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="133"
+            android:propertyName="trimPathEnd"
+            android:valueFrom="1.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_5_path_0_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_5_path_0_animation.xml
new file mode 100644
index 0000000..1e16df7
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_5_path_0_animation.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="166"
+        android:propertyName="trimPathEnd"
+        android:valueFrom="0.0"
+        android:valueTo="1.0"
+        android:valueType="floatType"
+        android:interpolator="@android:interpolator/fast_out_slow_in" />
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="150"
+            android:propertyName="trimPathStart"
+            android:valueFrom="0.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="166"
+            android:propertyName="trimPathStart"
+            android:valueFrom="0.0"
+            android:valueTo="1.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_2" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_5_path_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_5_path_animation.xml
new file mode 100644
index 0000000..a1cf8df
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_5_path_animation.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="150"
+        android:propertyName="trimPathStart"
+        android:valueFrom="0.0"
+        android:valueTo="1.0"
+        android:valueType="floatType"
+        android:interpolator="@android:interpolator/linear" />
+</set>
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_6_path_0_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_6_path_0_animation.xml
new file mode 100644
index 0000000..f88c070
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_6_path_0_animation.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="250"
+        android:propertyName="trimPathEnd"
+        android:valueFrom="0.0"
+        android:valueTo="1.0"
+        android:valueType="floatType"
+        android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0" />
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="133"
+            android:propertyName="trimPathStart"
+            android:valueFrom="0.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="216"
+            android:propertyName="trimPathStart"
+            android:valueFrom="0.0"
+            android:valueTo="1.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_6_path_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_6_path_animation.xml
new file mode 100644
index 0000000..ada7c10
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_6_path_animation.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="16"
+            android:propertyName="trimPathStart"
+            android:valueFrom="0.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="216"
+            android:propertyName="trimPathStart"
+            android:valueFrom="0.0"
+            android:valueTo="1.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_7_path_0_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_7_path_0_animation.xml
new file mode 100644
index 0000000..e6b12da
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_7_path_0_animation.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="16"
+            android:propertyName="trimPathEnd"
+            android:valueFrom="0.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="216"
+            android:propertyName="trimPathEnd"
+            android:valueFrom="0.0"
+            android:valueTo="1.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="133"
+            android:propertyName="trimPathStart"
+            android:valueFrom="0.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="266"
+            android:propertyName="trimPathStart"
+            android:valueFrom="0.0"
+            android:valueTo="1.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_2" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_7_path_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_7_path_animation.xml
new file mode 100644
index 0000000..8c6e71d
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_ridge_7_path_animation.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="33"
+            android:propertyName="trimPathStart"
+            android:valueFrom="0.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="150"
+            android:propertyName="trimPathStart"
+            android:valueFrom="0.0"
+            android:valueTo="1.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_white_fingerprint_ridges_animation.xml b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_white_fingerprint_ridges_animation.xml
new file mode 100644
index 0000000..c6a4622
--- /dev/null
+++ b/packages/SystemUI/res/anim/lockscreen_fingerprint_error_state_white_fingerprint_ridges_animation.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="100"
+            android:propertyName="rotation"
+            android:valueFrom="0.0"
+            android:valueTo="0.0"
+            android:valueType="floatType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="566"
+            android:propertyName="rotation"
+            android:valueFrom="0.0"
+            android:valueTo="-305.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_3" />
+        <objectAnimator
+            android:duration="1066"
+            android:propertyName="rotation"
+            android:valueFrom="-305.0"
+            android:valueTo="-305.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0" />
+        <objectAnimator
+            android:duration="800"
+            android:propertyName="rotation"
+            android:valueFrom="-305.0"
+            android:valueTo="-720.0"
+            android:valueType="floatType"
+            android:interpolator="@interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state.xml b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state.xml
new file mode 100644
index 0000000..cc8aba9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state.xml
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:name="lockscreen_fingerprint_error_state"
+    android:width="32dp"
+    android:viewportWidth="32"
+    android:height="32dp"
+    android:viewportHeight="32" >
+    <group
+        android:name="white_fingerprint_ridges"
+        android:translateX="16.125"
+        android:translateY="19.75" >
+        <group
+            android:name="white_fingerprint_ridges_pivot"
+            android:translateX="33.2085"
+            android:translateY="30.91685" >
+            <group
+                android:name="ridge_5" >
+                <path
+                    android:name="ridge_5_path"
+                    android:pathData="M -25.3591003418,-24.4138946533 c -0.569000244141,0.106399536133 -1.12660217285,0.140594482422 -1.45460510254,0.140594482422 c -1.29689025879,0.0 -2.53239440918,-0.343307495117 -3.62019348145,-1.12400817871 c -1.67700195312,-1.20349121094 -2.76950073242,-3.17008972168 -2.76950073242,-5.39189147949"
+                    android:strokeColor="#FFFFFFFF"
+                    android:strokeAlpha="0.5"
+                    android:strokeWidth="1.45"
+                    android:strokeLineCap="round" />
+            </group>
+            <group
+                android:name="ridge_4" >
+                <path
+                    android:name="ridge_7_path"
+                    android:pathData="M -36.1409912109,-21.7843475342 c -1.00540161133,-1.19300842285 -1.57499694824,-1.9181060791 -2.36520385742,-3.50170898438 c -0.827560424805,-1.65869140625 -1.31352233887,-3.49159240723 -1.31352233887,-5.48489379883 c 0.0,-3.66279602051 2.96932983398,-6.63220214844 6.63221740723,-6.63220214844 c 3.6628112793,0.0 6.63220214844,2.96940612793 6.63220214844,6.63220214844"
+                    android:strokeColor="#FFFFFFFF"
+                    android:strokeAlpha="0.5"
+                    android:strokeWidth="1.45"
+                    android:strokeLineCap="round" />
+            </group>
+            <group
+                android:name="ridge_3" >
+                <path
+                    android:name="ridge_6_path"
+                    android:pathData="M -42.1907958984,-25.6756896973 c -0.758117675781,-2.14370727539 -0.896545410156,-3.86891174316 -0.896545410156,-5.12921142578 c 0.0,-1.46069335938 0.249176025391,-2.84799194336 0.814682006836,-4.09748840332 c 1.56153869629,-3.45030212402 5.03434753418,-5.85076904297 9.0679473877,-5.85076904297 c 5.49430847168,0.0 9.94830322266,4.4539642334 9.94830322266,9.94825744629 c 0.0,1.83151245117 -1.48460388184,3.31610107422 -3.31610107422,3.31610107422 c -1.83149719238,0.0 -3.31610107422,-1.48469543457 -3.31610107422,-3.31610107422 c 0.0,-1.83139038086 -1.48458862305,-3.31610107422 -3.31610107422,-3.31610107422 c -1.83149719238,0.0 -3.31610107422,1.48471069336 -3.31610107422,3.31610107422 c 0.0,2.57020568848 0.989517211914,4.88710021973 2.60510253906,6.5865020752 c 1.22210693359,1.28550720215 2.43139648438,2.09950256348 4.47590637207,2.69030761719"
+                    android:strokeColor="#FFFFFFFF"
+                    android:strokeAlpha="0.5"
+                    android:strokeWidth="1.45"
+                    android:strokeLineCap="round" />
+            </group>
+            <group
+                android:name="ridge_2" >
+                <path
+                    android:name="ridge_2_path"
+                    android:pathData="M -44.0646514893,-38.1672973633 c 1.19026184082,-1.77430725098 2.67503356934,-3.24531555176 4.55902099609,-4.27278137207 c 1.88395690918,-1.0274810791 4.04466247559,-1.61137390137 6.34175109863,-1.61137390137 c 2.28761291504,0.0 4.43991088867,0.579071044922 6.31831359863,1.59861755371 c 1.8784942627,1.01954650879 3.36059570312,2.4796295166 4.55279541016,4.24153137207"
+                    android:strokeColor="#FFFFFFFF"
+                    android:strokeAlpha="0.5"
+                    android:strokeWidth="1.45"
+                    android:strokeLineCap="round" />
+            </group>
+            <group
+                android:name="ridge_1"
+                android:translateX="-97.5"
+                android:translateY="-142.5" >
+                <path
+                    android:name="ridge_1_path"
+                    android:pathData="M 71.7812347412,97.0507202148 c -2.27149963379,-1.31344604492 -4.71360778809,-2.07006835938 -7.56221008301,-2.07006835938 c -2.84869384766,0.0 -5.23320007324,0.779556274414 -7.34411621094,2.07006835938"
+                    android:strokeColor="#FFFFFFFF"
+                    android:strokeAlpha="0.5"
+                    android:strokeWidth="1.45"
+                    android:strokeLineCap="round" />
+            </group>
+        </group>
+    </group>
+    <group
+        android:name="fingerprint_ridges"
+        android:translateX="16.125"
+        android:translateY="19.75" >
+        <group
+            android:name="fingerprint_ridges_pivot"
+            android:translateX="33.2085"
+            android:translateY="30.91685" >
+            <group
+                android:name="ridge_6" >
+                <path
+                    android:name="ridge_5_path_0"
+                    android:pathData="M -25.3591003418,-24.4138946533 c -0.569000244141,0.106399536133 -1.12660217285,0.140594482422 -1.45460510254,0.140594482422 c -1.29689025879,0.0 -2.53239440918,-0.343307495117 -3.62019348145,-1.12400817871 c -1.67700195312,-1.20349121094 -2.76950073242,-3.17008972168 -2.76950073242,-5.39189147949"
+                    android:strokeColor="#FFF2501D"
+                    android:strokeWidth="1.45"
+                    android:strokeLineCap="round"
+                    android:trimPathEnd="0" />
+            </group>
+            <group
+                android:name="ridge_7" >
+                <path
+                    android:name="ridge_7_path_0"
+                    android:pathData="M -36.1409912109,-21.7843475342 c -1.00540161133,-1.19300842285 -1.57499694824,-1.9181060791 -2.36520385742,-3.50170898438 c -0.827560424805,-1.65869140625 -1.31352233887,-3.49159240723 -1.31352233887,-5.48489379883 c 0.0,-3.66279602051 2.96932983398,-6.63220214844 6.63221740723,-6.63220214844 c 3.6628112793,0.0 6.63220214844,2.96940612793 6.63220214844,6.63220214844"
+                    android:strokeColor="#FFF2501D"
+                    android:strokeWidth="1.45"
+                    android:strokeLineCap="round"
+                    android:trimPathEnd="0" />
+            </group>
+            <group
+                android:name="ridge_8" >
+                <path
+                    android:name="ridge_6_path_0"
+                    android:pathData="M -42.1907958984,-25.6756896973 c -0.758117675781,-2.14370727539 -0.896545410156,-3.86891174316 -0.896545410156,-5.12921142578 c 0.0,-1.46069335938 0.249176025391,-2.84799194336 0.814682006836,-4.09748840332 c 1.56153869629,-3.45030212402 5.03434753418,-5.85076904297 9.0679473877,-5.85076904297 c 5.49430847168,0.0 9.94830322266,4.4539642334 9.94830322266,9.94825744629 c 0.0,1.83151245117 -1.48460388184,3.31610107422 -3.31610107422,3.31610107422 c -1.83149719238,0.0 -3.31610107422,-1.48469543457 -3.31610107422,-3.31610107422 c 0.0,-1.83139038086 -1.48458862305,-3.31610107422 -3.31610107422,-3.31610107422 c -1.83149719238,0.0 -3.31610107422,1.48471069336 -3.31610107422,3.31610107422 c 0.0,2.57020568848 0.989517211914,4.88710021973 2.60510253906,6.5865020752 c 1.22210693359,1.28550720215 2.43139648438,2.09950256348 4.47590637207,2.69030761719"
+                    android:strokeColor="#FFF2501D"
+                    android:strokeWidth="1.45"
+                    android:strokeLineCap="round"
+                    android:trimPathEnd="0" />
+            </group>
+            <group
+                android:name="ridge_9" >
+                <path
+                    android:name="ridge_2_path_0"
+                    android:pathData="M -44.0646514893,-38.1672973633 c 1.19026184082,-1.77430725098 2.67503356934,-3.24531555176 4.55902099609,-4.27278137207 c 1.88395690918,-1.0274810791 4.04466247559,-1.61137390137 6.34175109863,-1.61137390137 c 2.28761291504,0.0 4.43991088867,0.579071044922 6.31831359863,1.59861755371 c 1.8784942627,1.01954650879 3.36059570312,2.4796295166 4.55279541016,4.24153137207"
+                    android:strokeColor="#FFF2501D"
+                    android:strokeWidth="1.45"
+                    android:strokeLineCap="round"
+                    android:trimPathStart="1" />
+            </group>
+            <group
+                android:name="ridge_10"
+                android:translateX="-97.5"
+                android:translateY="-142.5" >
+                <path
+                    android:name="ridge_1_path_0"
+                    android:pathData="M 71.7812347412,97.0507202148 c -2.27149963379,-1.31344604492 -4.71360778809,-2.07006835938 -7.56221008301,-2.07006835938 c -2.84869384766,0.0 -5.23320007324,0.779556274414 -7.34411621094,2.07006835938"
+                    android:strokeColor="#FFF2501D"
+                    android:strokeWidth="1.45"
+                    android:strokeLineCap="round"
+                    android:trimPathEnd="0" />
+            </group>
+        </group>
+    </group>
+    <group
+        android:name="exclamation"
+        android:translateX="16"
+        android:translateY="16" >
+        <group
+            android:name="group_2"
+            android:scaleX="0"
+            android:scaleY="0"
+            android:rotation="184" >
+            <path
+                android:name="path_2_merged"
+                android:pathData="M 1.35900878906,6.76104736328 c 0.0,0.0 -2.69998168945,0.0 -2.69998168945,0.0 c 0.0,0.0 0.0,-2.69995117188 0.0,-2.69995117188 c 0.0,0.0 2.69998168945,0.0 2.69998168945,0.0 c 0.0,0.0 0.0,2.69995117188 0.0,2.69995117188 Z M 1.35363769531,1.36633300781 c 0.0,0.0 -2.69998168945,0.0 -2.69998168945,0.0 c 0.0,0.0 0.0,-8.09997558594 0.0,-8.09997558594 c 0.0,0.0 2.69998168945,0.0 2.69998168945,0.0 c 0.0,0.0 0.0,8.09997558594 0.0,8.09997558594 Z"
+                android:fillColor="#FFF2501D" />
+        </group>
+    </group>
+    <group
+        android:name="circle_outline"
+        android:translateX="16"
+        android:translateY="16" >
+        <group
+            android:name="group_1"
+            android:scaleX="1.12734"
+            android:scaleY="1.12734"
+            android:rotation="285" >
+            <path
+                android:name="path_3"
+                android:pathData="M 0.0101470947266,10.8087768555 c -5.96701049805,0.0 -10.8000183105,-4.8330078125 -10.8000183105,-10.8000488281 c 0.0,-5.96691894531 4.8330078125,-10.7999267578 10.8000183105,-10.7999267578 c 5.96697998047,0.0 10.799987793,4.8330078125 10.799987793,10.7999267578 c 0.0,5.96704101562 -4.8330078125,10.8000488281 -10.799987793,10.8000488281 Z"
+                android:strokeColor="#FFF2501D"
+                android:strokeWidth="2"
+                android:trimPathStart="1" />
+        </group>
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_animation.xml b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_animation.xml
new file mode 100644
index 0000000..8cc8ac2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_animation.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<animated-vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/lockscreen_fingerprint_error_state" >
+    <target
+        android:name="white_fingerprint_ridges"
+        android:animation="@anim/lockscreen_fingerprint_error_state_white_fingerprint_ridges_animation" />
+    <target
+        android:name="ridge_5_path"
+        android:animation="@anim/lockscreen_fingerprint_error_state_ridge_5_path_animation" />
+    <target
+        android:name="ridge_7_path"
+        android:animation="@anim/lockscreen_fingerprint_error_state_ridge_7_path_animation" />
+    <target
+        android:name="ridge_6_path"
+        android:animation="@anim/lockscreen_fingerprint_error_state_ridge_6_path_animation" />
+    <target
+        android:name="ridge_2_path"
+        android:animation="@anim/lockscreen_fingerprint_error_state_ridge_2_path_animation" />
+    <target
+        android:name="ridge_1_path"
+        android:animation="@anim/lockscreen_fingerprint_error_state_ridge_1_path_animation" />
+    <target
+        android:name="fingerprint_ridges"
+        android:animation="@anim/lockscreen_fingerprint_error_state_fingerprint_ridges_animation" />
+    <target
+        android:name="ridge_5_path_0"
+        android:animation="@anim/lockscreen_fingerprint_error_state_ridge_5_path_0_animation" />
+    <target
+        android:name="ridge_7_path_0"
+        android:animation="@anim/lockscreen_fingerprint_error_state_ridge_7_path_0_animation" />
+    <target
+        android:name="ridge_6_path_0"
+        android:animation="@anim/lockscreen_fingerprint_error_state_ridge_6_path_0_animation" />
+    <target
+        android:name="ridge_2_path_0"
+        android:animation="@anim/lockscreen_fingerprint_error_state_ridge_2_path_0_animation" />
+    <target
+        android:name="ridge_1_path_0"
+        android:animation="@anim/lockscreen_fingerprint_error_state_ridge_1_path_0_animation" />
+    <target
+        android:name="group_2"
+        android:animation="@anim/lockscreen_fingerprint_error_state_group_2_animation" />
+    <target
+        android:name="group_1"
+        android:animation="@anim/lockscreen_fingerprint_error_state_group_1_animation" />
+    <target
+        android:name="path_3"
+        android:animation="@anim/lockscreen_fingerprint_error_state_path_3_animation" />
+</animated-vector>
diff --git a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0.xml
new file mode 100644
index 0000000..39c5211
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_0.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<pathInterpolator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 c 0.16666666667,0.0 0.83333333333,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_1.xml b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_1.xml
new file mode 100644
index 0000000..d3ae9d7
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_1.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<pathInterpolator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 c 0.0,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_2.xml b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_2.xml
new file mode 100644
index 0000000..e10db01
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_2.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<pathInterpolator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 c 0.8,0.0 0.5,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_3.xml b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_3.xml
new file mode 100644
index 0000000..736eac6
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/lockscreen_fingerprint_error_state_animation_interpolator_3.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<pathInterpolator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 c 0.4,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index fca8231..1057464 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -61,7 +61,7 @@
         android:scaleType="center"
         android:contentDescription="@string/accessibility_phone_button" />
 
-    <com.android.systemui.statusbar.KeyguardAffordanceView
+    <com.android.systemui.statusbar.phone.LockIcon
         android:id="@+id/lock_icon"
         android:layout_width="@dimen/keyguard_affordance_width"
         android:layout_height="@dimen/keyguard_affordance_height"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 2e44547..81f2953 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -150,7 +150,7 @@
     <integer name="heads_up_notification_minimum_time">2000</integer>
 
     <!-- milliseconds before the heads up notification accepts touches. -->
-    <integer name="heads_up_sensitivity_delay">700</integer>
+    <integer name="touch_acceptance_delay">700</integer>
 
     <!-- The duration in seconds to wait before the dismiss buttons are shown. -->
     <integer name="recents_task_bar_dismiss_delay_seconds">1</integer>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 0d331d1..3fbc76b 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -225,23 +225,23 @@
         mSubpixelSmoothingRight = context.getResources().getFraction(
                 R.fraction.battery_subpixel_smoothing_right, 1, 1);
 
-        mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mFramePaint = new Paint();
         mFramePaint.setColor(frameColor);
         mFramePaint.setDither(true);
         mFramePaint.setStrokeWidth(0);
         mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE);
 
-        mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mBatteryPaint = new Paint();
         mBatteryPaint.setDither(true);
         mBatteryPaint.setStrokeWidth(0);
         mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE);
 
-        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mTextPaint = new Paint();
         Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD);
         mTextPaint.setTypeface(font);
         mTextPaint.setTextAlign(Paint.Align.CENTER);
 
-        mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mWarningTextPaint = new Paint();
         mWarningTextPaint.setColor(mColors[1]);
         font = Typeface.create("sans-serif", Typeface.BOLD);
         mWarningTextPaint.setTypeface(font);
@@ -249,7 +249,7 @@
 
         mChargeColor = context.getColor(R.color.batterymeter_charge_color);
 
-        mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mBoltPaint = new Paint();
         mBoltPaint.setColor(context.getColor(R.color.batterymeter_bolt_color));
         mBoltPoints = loadBoltPoints(res);
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 7b555fc..6479dc5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -539,10 +539,11 @@
         mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
 
         mLockPatternUtils = new LockPatternUtils(mContext);
-        mLockPatternUtils.setCurrentUser(ActivityManager.getCurrentUser());
+        KeyguardUpdateMonitor.setCurrentUser(ActivityManager.getCurrentUser());
 
         // Assume keyguard is showing (unless it's disabled) until we know for sure...
-        setShowingLocked(!shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled());
+        setShowingLocked(!shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled(
+                KeyguardUpdateMonitor.getCurrentUser()));
         mTrustManager.reportKeyguardShowingChanged();
 
         mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext,
@@ -623,8 +624,10 @@
             // Lock immediately based on setting if secure (user has a pin/pattern/password).
             // This also "locks" the device when not secure to provide easy access to the
             // camera while preventing unwanted input.
+            int currentUser = KeyguardUpdateMonitor.getCurrentUser();
             final boolean lockImmediately =
-                mLockPatternUtils.getPowerButtonInstantlyLocks() || !mLockPatternUtils.isSecure();
+                mLockPatternUtils.getPowerButtonInstantlyLocks(currentUser)
+                        || !mLockPatternUtils.isSecure(currentUser);
 
             notifyScreenOffLocked();
 
@@ -670,7 +673,7 @@
 
         // From DevicePolicyAdmin
         final long policyTimeout = mLockPatternUtils.getDevicePolicyManager()
-                .getMaximumTimeToLock(null, mLockPatternUtils.getCurrentUser());
+                .getMaximumTimeToLock(null, KeyguardUpdateMonitor.getCurrentUser());
 
         long timeout;
         if (policyTimeout > 0) {
@@ -719,7 +722,8 @@
     }
 
     private void maybeSendUserPresentBroadcast() {
-        if (mSystemReady && mLockPatternUtils.isLockScreenDisabled()) {
+        if (mSystemReady && mLockPatternUtils.isLockScreenDisabled(
+                KeyguardUpdateMonitor.getCurrentUser())) {
             // Lock screen is disabled because the user has set the preference to "None".
             // In this case, send out ACTION_USER_PRESENT here instead of in
             // handleKeyguardDone()
@@ -733,7 +737,7 @@
      */
     public void onDreamingStarted() {
         synchronized (this) {
-            if (mScreenOn && mLockPatternUtils.isSecure()) {
+            if (mScreenOn && mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
                 doKeyguardLaterLocked();
             }
         }
@@ -974,12 +978,13 @@
             return;
         }
 
-        if (mLockPatternUtils.isLockScreenDisabled() && !lockedOrMissing) {
+        if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser())
+                && !lockedOrMissing) {
             if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
             return;
         }
 
-        if (mLockPatternUtils.checkVoldPassword()) {
+        if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {
             if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
             // Without this, settings is not enabled until the lock screen first appears
             setShowingLocked(false);
@@ -1072,7 +1077,7 @@
     }
 
     public boolean isSecure() {
-        return mLockPatternUtils.isSecure()
+        return mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())
             || KeyguardUpdateMonitor.getInstance(mContext).isSimPinSecure();
     }
 
@@ -1083,7 +1088,7 @@
      * @param newUserId The id of the incoming user.
      */
     public void setCurrentUser(int newUserId) {
-        mLockPatternUtils.setCurrentUser(newUserId);
+        KeyguardUpdateMonitor.setCurrentUser(newUserId);
     }
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -1213,7 +1218,7 @@
     private void sendUserPresentBroadcast() {
         synchronized (this) {
             if (mBootCompleted) {
-                final UserHandle currentUser = new UserHandle(mLockPatternUtils.getCurrentUser());
+                final UserHandle currentUser = new UserHandle(KeyguardUpdateMonitor.getCurrentUser());
                 final UserManager um = (UserManager) mContext.getSystemService(
                         Context.USER_SERVICE);
                 List <UserInfo> userHandles = um.getProfiles(currentUser.getIdentifier());
@@ -1393,14 +1398,9 @@
             updateActivityLockScreenState();
             adjustStatusBarLocked();
             sendUserPresentBroadcast();
-            maybeStopListeningForFingerprint();
         }
     }
 
-    private void maybeStopListeningForFingerprint() {
-        mUpdateMonitor.stopListeningForFingerprint();
-    }
-
     private void adjustStatusBarLocked() {
         if (mStatusBarManager == null) {
             mStatusBarManager = (StatusBarManager)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 7271469..26c3b4e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -87,6 +87,7 @@
 import com.android.internal.statusbar.StatusBarIconList;
 import com.android.internal.util.NotificationColorUtil;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.SwipeHelper;
@@ -639,7 +640,7 @@
                 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 1)) {
             Log.d(TAG, "user hasn't seen notification about hidden notifications");
             final LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
-            if (!lockPatternUtils.isSecure()) {
+            if (!lockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
                 Log.d(TAG, "insecure lockscreen, skipping notification");
                 Settings.Secure.putInt(mContext.getContentResolver(),
                         Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
@@ -708,18 +709,6 @@
         mNotificationListener.setNotificationsShown(keys);
     }
 
-    protected void setNotificationsShownAll() {
-        ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
-        final int N = activeNotifications.size();
-
-        String[] keys = new String[N];
-        for (int i = 0; i < N; i++) {
-            NotificationData.Entry entry = activeNotifications.get(i);
-            keys[i] = entry.key;
-        }
-        setNotificationsShown(keys);
-    }
-
     protected boolean isCurrentProfile(int userId) {
         synchronized (mCurrentProfiles) {
             return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null;
@@ -795,7 +784,8 @@
     protected void applyColorsAndBackgrounds(StatusBarNotification sbn,
             NotificationData.Entry entry) {
 
-        if (entry.expanded.getId() != com.android.internal.R.id.status_bar_latest_event_content) {
+        if (entry.getContentView().getId()
+                != com.android.internal.R.id.status_bar_latest_event_content) {
             // Using custom RemoteViews
             if (entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD
                     && entry.targetSdk < Build.VERSION_CODES.LOLLIPOP) {
@@ -820,8 +810,9 @@
 
     public boolean isMediaNotification(NotificationData.Entry entry) {
         // TODO: confirm that there's a valid media key
-        return entry.expandedBig != null &&
-               entry.expandedBig.findViewById(com.android.internal.R.id.media_actions) != null;
+        return entry.getExpandedContentView() != null &&
+               entry.getExpandedContentView()
+                       .findViewById(com.android.internal.R.id.media_actions) != null;
     }
 
     // The gear button in the guts that links to the app's own notification settings
@@ -1145,9 +1136,9 @@
     }
 
     /**
-     * if the interrupting notification had a fullscreen intent, fire it now.
+     * If there is an active heads-up notification and it has a fullscreen intent, fire it now.
      */
-    public abstract void escalateHeadsUp();
+    public abstract void maybeEscalateHeadsUp();
 
     /**
      * Save the current "public" (locked and secure) state of the lockscreen.
@@ -1348,8 +1339,8 @@
         View publicViewLocal = null;
         if (publicNotification != null) {
             try {
-                publicViewLocal = publicNotification.contentView.apply(mContext, contentContainerPublic,
-                        mOnClickHandler);
+                publicViewLocal = publicNotification.contentView.apply(mContext,
+                        contentContainerPublic, mOnClickHandler);
 
                 if (publicViewLocal != null) {
                     publicViewLocal.setIsRootNamespace(true);
@@ -1456,9 +1447,7 @@
         entry.row = row;
         entry.row.setHeightRange(mRowMinHeight, maxHeight);
         entry.row.setOnActivatedListener(this);
-        entry.expanded = contentViewLocal;
-        entry.expandedPublic = publicViewLocal;
-        entry.setBigContentView(bigContentViewLocal);
+        entry.row.setExpandable(bigContentViewLocal != null);
 
         applyColorsAndBackgrounds(sbn, entry);
 
@@ -1547,12 +1536,13 @@
 
         // See if we have somewhere to put that remote input
         if (remoteInput != null) {
-            if (entry.expandedBig != null) {
-                inflateRemoteInput(entry.expandedBig, remoteInput, actions);
+            View bigContentView = entry.getExpandedContentView();
+            if (bigContentView != null) {
+                inflateRemoteInput(bigContentView, remoteInput, actions);
             }
-            View headsUpChild = entry.row.getPrivateLayout().getHeadsUpChild();
-            if (headsUpChild != null) {
-                inflateRemoteInput(headsUpChild, remoteInput, actions);
+            View headsUpContentView = entry.getHeadsUpContentView();
+            if (headsUpContentView != null) {
+                inflateRemoteInput(headsUpContentView, remoteInput, actions);
             }
         }
 
@@ -1701,7 +1691,6 @@
                 boolean clearNotificationEffects =
                         (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED);
                 mBarService.onPanelRevealed(clearNotificationEffects);
-                setNotificationsShownAll();
             } else {
                 mBarService.onPanelHidden();
             }
@@ -1895,15 +1884,14 @@
             logUpdate(entry, n);
         }
         boolean applyInPlace = shouldApplyInPlace(entry, n);
-        final boolean shouldInterrupt = shouldInterrupt(notification);
-        final boolean alertAgain = alertAgain(entry, n);
+        boolean shouldInterrupt = shouldInterrupt(notification);
+        boolean alertAgain = alertAgain(entry, n);
 
         entry.notification = notification;
         mGroupManager.onEntryUpdated(entry, entry.notification);
 
         boolean updateSuccessful = false;
         if (applyInPlace) {
-            // We can just reapply the notifications in place
             if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
             try {
                 if (entry.icon != null) {
@@ -1924,7 +1912,7 @@
                 updateSuccessful = true;
             }
             catch (RuntimeException e) {
-                // It failed to add cleanly.  Log, and remove the view from the panel.
+                // It failed to apply cleanly.
                 Log.w(TAG, "Couldn't reapply views for package " + n.contentView.getPackage(), e);
             }
         }
@@ -1948,11 +1936,12 @@
         // swipe-dismissable)
         updateNotificationVetoButton(entry.row, notification);
 
-        // Is this for you?
-        boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
-        if (DEBUG) Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
+        if (DEBUG) {
+            // Is this for you?
+            boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
+            Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
+        }
 
-        // Recalculate the position of the sliding windows and the titles.
         setAreThereNotifications();
     }
 
@@ -1963,7 +1952,7 @@
         StatusBarNotification oldNotification = oldEntry.notification;
         Log.d(TAG, "old notification: when=" + oldNotification.getNotification().when
                 + " ongoing=" + oldNotification.isOngoing()
-                + " expanded=" + oldEntry.expanded
+                + " expanded=" + oldEntry.getContentView()
                 + " contentView=" + oldNotification.getNotification().contentView
                 + " bigContentView=" + oldNotification.getNotification().bigContentView
                 + " publicView=" + oldNotification.getNotification().publicVersion
@@ -1976,7 +1965,8 @@
     }
 
     /**
-     * @return whether we can just reapply the RemoteViews in place when it is updated
+     * @return whether we can just reapply the RemoteViews from a notification in-place when it is
+     * updated
      */
     private boolean shouldApplyInPlace(Entry entry, Notification n) {
         StatusBarNotification oldNotification = entry.notification;
@@ -1994,15 +1984,15 @@
         final Notification publicNotification = n.publicVersion;
         final RemoteViews publicContentView = publicNotification != null
                 ? publicNotification.contentView : null;
-        boolean contentsUnchanged = entry.expanded != null
+        boolean contentsUnchanged = entry.getContentView() != null
                 && contentView.getPackage() != null
                 && oldContentView.getPackage() != null
                 && oldContentView.getPackage().equals(contentView.getPackage())
                 && oldContentView.getLayoutId() == contentView.getLayoutId();
         // large view may be null
         boolean bigContentsUnchanged =
-                (entry.getBigContentView() == null && bigContentView == null)
-                || ((entry.getBigContentView() != null && bigContentView != null)
+                (entry.getExpandedContentView() == null && bigContentView == null)
+                || ((entry.getExpandedContentView() != null && bigContentView != null)
                     && bigContentView.getPackage() != null
                     && oldBigContentView.getPackage() != null
                     && oldBigContentView.getPackage().equals(bigContentView.getPackage())
@@ -2034,12 +2024,12 @@
                 : null;
 
         // Reapply the RemoteViews
-        contentView.reapply(mContext, entry.expanded, mOnClickHandler);
-        if (bigContentView != null && entry.getBigContentView() != null) {
-            bigContentView.reapply(mContext, entry.getBigContentView(),
+        contentView.reapply(mContext, entry.getContentView(), mOnClickHandler);
+        if (bigContentView != null && entry.getExpandedContentView() != null) {
+            bigContentView.reapply(mContext, entry.getExpandedContentView(),
                     mOnClickHandler);
         }
-        View headsUpChild = entry.row.getPrivateLayout().getHeadsUpChild();
+        View headsUpChild = entry.getHeadsUpContentView();
         if (headsUpContentView != null && headsUpChild != null) {
             headsUpContentView.reapply(mContext, headsUpChild, mOnClickHandler);
         }
@@ -2062,7 +2052,7 @@
     }
 
     protected void notifyHeadsUpScreenOff() {
-        escalateHeadsUp();
+        maybeEscalateHeadsUp();
     }
 
     private boolean alertAgain(Entry oldEntry, Notification newNotification) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index cb8217e..9ef495d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -84,7 +84,6 @@
     private ExpansionLogger mLogger;
     private String mLoggingKey;
     private boolean mWasReset;
-
     private NotificationGuts mGuts;
     private StatusBarNotification mStatusBarNotification;
     private boolean mIsHeadsUp;
@@ -102,6 +101,7 @@
     private ViewStub mGutsStub;
     private boolean mHasExpandAction;
     private boolean mIsSystemChildExpanded;
+    private boolean mIsPinned;
     private OnClickListener mExpandClickListener = new OnClickListener() {
         @Override
         public void onClick(View v) {
@@ -109,7 +109,6 @@
                     !mChildrenExpanded);
         }
     };
-    private boolean mInShade;
 
     public NotificationContentView getPrivateLayout() {
         return mPrivateLayout;
@@ -284,12 +283,18 @@
         return realActualHeight;
     }
 
-    public void setInShade(boolean inShade) {
-        mInShade = inShade;
+    /**
+     * Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this
+     * the notification will be rendered on top of the screen.
+     *
+     * @param pinned whether it is pinned
+     */
+    public void setPinned(boolean pinned) {
+        mIsPinned = pinned;
     }
 
-    public boolean isInShade() {
-        return mInShade;
+    public boolean isPinned() {
+        return mIsPinned;
     }
 
     public int getHeadsUpHeight() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 1c53655..110b14c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -32,37 +32,34 @@
 import com.android.systemui.R;
 
 /**
- * A frame layout containing the actual payload of the notification, including the contracted and
- * expanded layout. This class is responsible for clipping the content and and switching between the
- * expanded and contracted view depending on its clipped size.
+ * A frame layout containing the actual payload of the notification, including the contracted,
+ * expanded and heads up layout. This class is responsible for clipping the content and and
+ * switching between the expanded, contracted and the heads up view depending on its clipped size.
  */
 public class NotificationContentView extends FrameLayout {
 
     private static final long ANIMATION_DURATION_LENGTH = 170;
-    private static final int CONTRACTED = 1;
-    private static final int EXPANDED = 2;
-    private static final int HEADSUP = 3;
+    private static final int VISIBLE_TYPE_CONTRACTED = 0;
+    private static final int VISIBLE_TYPE_EXPANDED = 1;
+    private static final int VISIBLE_TYPE_HEADSUP = 2;
 
     private final Rect mClipBounds = new Rect();
+    private final int mSmallHeight;
+    private final int mHeadsUpHeight;
+    private final Interpolator mLinearInterpolator = new LinearInterpolator();
 
     private View mContractedChild;
     private View mExpandedChild;
     private View mHeadsUpChild;
 
     private NotificationViewWrapper mContractedWrapper;
-
-    private final int mSmallHeight;
-    private final int mHeadsUpHeight;
     private int mClipTopAmount;
-
     private int mContentHeight;
-
-    private final Interpolator mLinearInterpolator = new LinearInterpolator();
-    private int mVisibleView = CONTRACTED;
-
+    private int mVisibleType = VISIBLE_TYPE_CONTRACTED;
     private boolean mDark;
     private final Paint mFadePaint = new Paint();
     private boolean mAnimate;
+    private boolean mIsHeadsUp;
     private ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener
             = new ViewTreeObserver.OnPreDrawListener() {
         @Override
@@ -72,7 +69,6 @@
             return true;
         }
     };
-    private boolean mIsHeadsUp;
 
     public NotificationContentView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -105,9 +101,9 @@
                 // An actual height is set
                 size = Math.min(maxSize, layoutParams.height);
             }
-            int spec = size == Integer.MAX_VALUE ?
-                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED) :
-                    MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
+            int spec = size == Integer.MAX_VALUE
+                    ? MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
+                    : MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
             mExpandedChild.measure(widthMeasureSpec, spec);
             maxChildHeight = Math.max(maxChildHeight, mExpandedChild.getMeasuredHeight());
         }
@@ -153,7 +149,7 @@
         mContractedChild = null;
         mExpandedChild = null;
         mHeadsUpChild = null;
-        mVisibleView = CONTRACTED;
+        mVisibleType = VISIBLE_TYPE_CONTRACTED;
         if (resetActualHeight) {
             mContentHeight = mSmallHeight;
         }
@@ -263,30 +259,32 @@
         if (mContractedChild == null) {
             return;
         }
-        int visibleView = calculateVisibleView();
-        if (visibleView != mVisibleView || force) {
-            if (animate && mExpandedChild != null) {
-                runSwitchAnimation(visibleView);
+        int visibleType = calculateVisibleType();
+        if (visibleType != mVisibleType || force) {
+            if (animate && (visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
+                    || (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
+                    || visibleType == VISIBLE_TYPE_CONTRACTED) {
+                runSwitchAnimation(visibleType);
             } else {
-                updateViewVisibilities(visibleView);
+                updateViewVisibilities(visibleType);
             }
-            mVisibleView = visibleView;
+            mVisibleType = visibleType;
         }
     }
 
-    private void updateViewVisibilities(int visibleView) {
-        boolean contractedVisible = visibleView == CONTRACTED;
+    private void updateViewVisibilities(int visibleType) {
+        boolean contractedVisible = visibleType == VISIBLE_TYPE_CONTRACTED;
         mContractedChild.setVisibility(contractedVisible ? View.VISIBLE : View.INVISIBLE);
         mContractedChild.setAlpha(contractedVisible ? 1f : 0f);
         mContractedChild.setLayerType(LAYER_TYPE_NONE, null);
         if (mExpandedChild != null) {
-            boolean expandedVisible = visibleView == EXPANDED;
+            boolean expandedVisible = visibleType == VISIBLE_TYPE_EXPANDED;
             mExpandedChild.setVisibility(expandedVisible ? View.VISIBLE : View.INVISIBLE);
             mExpandedChild.setAlpha(expandedVisible ? 1f : 0f);
             mExpandedChild.setLayerType(LAYER_TYPE_NONE, null);
         }
         if (mHeadsUpChild != null) {
-            boolean headsUpVisible = visibleView == HEADSUP;
+            boolean headsUpVisible = visibleType == VISIBLE_TYPE_HEADSUP;
             mHeadsUpChild.setVisibility(headsUpVisible ? View.VISIBLE : View.INVISIBLE);
             mHeadsUpChild.setAlpha(headsUpVisible ? 1f : 0f);
             mHeadsUpChild.setLayerType(LAYER_TYPE_NONE, null);
@@ -294,9 +292,9 @@
         setLayerType(LAYER_TYPE_NONE, null);
     }
 
-    private void runSwitchAnimation(int visibleView) {
-        View shownView = getViewFromFlag(visibleView);
-        View hiddenView = getViewFromFlag(mVisibleView);
+    private void runSwitchAnimation(int visibleType) {
+        View shownView = getViewForVisibleType(visibleType);
+        View hiddenView = getViewForVisibleType(mVisibleType);
         shownView.setVisibility(View.VISIBLE);
         hiddenView.setVisibility(View.VISIBLE);
         shownView.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint);
@@ -314,34 +312,42 @@
                 .withEndAction(new Runnable() {
                     @Override
                     public void run() {
-                        updateViewVisibilities(mVisibleView);
+                        updateViewVisibilities(mVisibleType);
                     }
                 });
     }
 
-    private View getViewFromFlag(int visibleView) {
-        switch (visibleView) {
-            case EXPANDED:
+    /**
+     * @param visibleType one of the static enum types in this view
+     * @return the corresponding view according to the given visible type
+     */
+    private View getViewForVisibleType(int visibleType) {
+        switch (visibleType) {
+            case VISIBLE_TYPE_EXPANDED:
                 return mExpandedChild;
-            case HEADSUP:
+            case VISIBLE_TYPE_HEADSUP:
                 return mHeadsUpChild;
+            default:
+                return mContractedChild;
         }
-        return mContractedChild;
     }
 
-    private int calculateVisibleView() {
+    /**
+     * @return one of the static enum types in this view, calculated form the current state
+     */
+    private int calculateVisibleType() {
         boolean noExpandedChild = mExpandedChild == null;
         if (mIsHeadsUp && mHeadsUpChild != null) {
             if (mContentHeight <= mHeadsUpChild.getHeight() || noExpandedChild) {
-                return HEADSUP;
+                return VISIBLE_TYPE_HEADSUP;
             } else {
-                return EXPANDED;
+                return VISIBLE_TYPE_EXPANDED;
             }
         } else {
             if (mContentHeight <= mSmallHeight || noExpandedChild) {
-                return CONTRACTED;
+                return VISIBLE_TYPE_CONTRACTED;
             } else {
-                return EXPANDED;
+                return VISIBLE_TYPE_EXPANDED;
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 429889d..2a8b4ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -45,9 +45,6 @@
         public StatusBarNotification notification;
         public StatusBarIconView icon;
         public ExpandableNotificationRow row; // the outer expanded view
-        public View expanded; // the inflated RemoteViews
-        public View expandedPublic; // for insecure lockscreens
-        public View expandedBig;
         private boolean interruption;
         public boolean autoRedacted; // whether the redacted notification was generated by us
         public boolean legacy; // whether the notification has a legacy, dark background
@@ -58,14 +55,6 @@
             this.notification = n;
             this.icon = ic;
         }
-        public void setBigContentView(View bigContentView) {
-            this.expandedBig = bigContentView;
-            row.setExpandable(bigContentView != null);
-        }
-        public View getBigContentView() {
-            return expandedBig;
-        }
-        public View getPublicContentView() { return expandedPublic; }
 
         public void setInterruption() {
             interruption = true;
@@ -81,15 +70,28 @@
         public void reset() {
             // NOTE: Icon needs to be preserved for now.
             // We should fix this at some point.
-            expanded = null;
-            expandedPublic = null;
-            expandedBig = null;
             autoRedacted = false;
             legacy = false;
             if (row != null) {
                 row.reset();
             }
         }
+
+        public View getContentView() {
+            return row.getPrivateLayout().getContractedChild();
+        }
+
+        public View getExpandedContentView() {
+            return row.getPrivateLayout().getExpandedChild();
+        }
+
+        public View getHeadsUpContentView() {
+            return row.getPrivateLayout().getHeadsUpChild();
+        }
+
+        public View getPublicContentView() {
+            return row.getPublicLayout().getContractedChild();
+        }
     }
 
     private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
@@ -258,7 +260,7 @@
      */
     public boolean hasActiveClearableNotifications() {
         for (Entry e : mSortedAndFiltered) {
-            if (e.expanded != null) { // the view successfully inflated
+            if (e.getContentView() != null) { // the view successfully inflated
                 if (e.notification.isClearable()) {
                     return true;
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index 3997807..fe7bc97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -27,7 +27,7 @@
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
 /**
- * A Helper class to handle touches on the heads-up views
+ * A helper class to handle touches on the heads-up views.
  */
 public class HeadsUpTouchHelper implements Gefingerpoken {
 
@@ -37,19 +37,30 @@
     private float mTouchSlop;
     private float mInitialTouchX;
     private float mInitialTouchY;
-    private boolean mMotionOnHeadsUpView;
+    private boolean mTouchingHeadsUpView;
     private boolean mTrackingHeadsUp;
     private boolean mCollapseSnoozes;
     private NotificationPanelView mPanel;
     private ExpandableNotificationRow mPickedChild;
 
+    public HeadsUpTouchHelper(HeadsUpManager headsUpManager,
+            NotificationStackScrollLayout stackScroller,
+            NotificationPanelView notificationPanelView) {
+        mHeadsUpManager = headsUpManager;
+        mStackScroller = stackScroller;
+        mPanel = notificationPanelView;
+        Context context = stackScroller.getContext();
+        final ViewConfiguration configuration = ViewConfiguration.get(context);
+        mTouchSlop = configuration.getScaledTouchSlop();
+    }
+
     public boolean isTrackingHeadsUp() {
         return mTrackingHeadsUp;
     }
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
-        if (!mMotionOnHeadsUpView && event.getActionMasked() != MotionEvent.ACTION_DOWN) {
+        if (!mTouchingHeadsUpView && event.getActionMasked() != MotionEvent.ACTION_DOWN) {
             return false;
         }
         int pointerIndex = event.findPointerIndex(mTrackingPointer);
@@ -65,10 +76,10 @@
                 mInitialTouchX = x;
                 setTrackingHeadsUp(false);
                 ExpandableView child = mStackScroller.getChildAtPosition(x, y);
-                mMotionOnHeadsUpView = false;
+                mTouchingHeadsUpView = false;
                 if (child instanceof ExpandableNotificationRow) {
                     mPickedChild = (ExpandableNotificationRow) child;
-                    mMotionOnHeadsUpView = mPickedChild.isHeadsUp() && !mPickedChild.isInShade();
+                    mTouchingHeadsUpView = mPickedChild.isHeadsUp() && mPickedChild.isPinned();
                 }
                 break;
             case MotionEvent.ACTION_POINTER_UP:
@@ -97,7 +108,8 @@
 
             case MotionEvent.ACTION_CANCEL:
             case MotionEvent.ACTION_UP:
-                if (mPickedChild != null && mMotionOnHeadsUpView) {
+                if (mPickedChild != null && mTouchingHeadsUpView) {
+                    // We may swallow this click if the heads up just came in.
                     if (mHeadsUpManager.shouldSwallowClick(
                             mPickedChild.getStatusBarNotification().getKey())) {
                         endMotion();
@@ -141,20 +153,6 @@
     private void endMotion() {
         mTrackingPointer = -1;
         mPickedChild = null;
-        mMotionOnHeadsUpView = false;
-    }
-
-    public ExpandableView getPickedChild() {
-        return mPickedChild;
-    }
-
-    public void bind(HeadsUpManager headsUpManager, NotificationStackScrollLayout stackScroller,
-            NotificationPanelView notificationPanelView) {
-        mHeadsUpManager = headsUpManager;
-        mStackScroller = stackScroller;
-        mPanel = notificationPanelView;
-        Context context = stackScroller.getContext();
-        final ViewConfiguration configuration = ViewConfiguration.get(context);
-        mTouchSlop = configuration.getScaledTouchSlop();
+        mTouchingHeadsUpView = false;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index e5ef6ff..fabc1a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -86,7 +86,7 @@
 
     private KeyguardAffordanceView mCameraImageView;
     private KeyguardAffordanceView mPhoneImageView;
-    private KeyguardAffordanceView mLockIcon;
+    private LockIcon mLockIcon;
     private TextView mIndicationText;
     private ViewGroup mPreviewContainer;
 
@@ -102,11 +102,8 @@
     private AccessibilityController mAccessibilityController;
     private PhoneStatusBar mPhoneStatusBar;
 
-    private final TrustDrawable mTrustDrawable;
     private final Interpolator mLinearOutSlowInInterpolator;
-    private int mLastUnlockIconRes = 0;
     private boolean mPrewarmSent;
-    private boolean mTransientFpError;
 
     public KeyguardBottomAreaView(Context context) {
         this(context, null);
@@ -123,7 +120,6 @@
     public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
-        mTrustDrawable = new TrustDrawable(mContext);
         mLinearOutSlowInInterpolator =
                 AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in);
     }
@@ -169,20 +165,19 @@
         mPreviewContainer = (ViewGroup) findViewById(R.id.preview_container);
         mCameraImageView = (KeyguardAffordanceView) findViewById(R.id.camera_button);
         mPhoneImageView = (KeyguardAffordanceView) findViewById(R.id.phone_button);
-        mLockIcon = (KeyguardAffordanceView) findViewById(R.id.lock_icon);
+        mLockIcon = (LockIcon) findViewById(R.id.lock_icon);
         mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text);
         watchForCameraPolicyChanges();
         updateCameraVisibility();
         updatePhoneVisibility();
         mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
         mUnlockMethodCache.addListener(this);
-        updateLockIcon();
+        mLockIcon.update();
         setClipChildren(false);
         setClipToPadding(false);
         mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
         inflatePreviews();
         mLockIcon.setOnClickListener(this);
-        mLockIcon.setBackground(mTrustDrawable);
         mLockIcon.setOnLongClickListener(this);
         mCameraImageView.setOnClickListener(this);
         mPhoneImageView.setOnClickListener(this);
@@ -222,6 +217,7 @@
 
     public void setAccessibilityController(AccessibilityController accessibilityController) {
         mAccessibilityController = accessibilityController;
+        mLockIcon.setAccessibilityController(accessibilityController);
         accessibilityController.addStateChangedCallback(this);
     }
 
@@ -233,9 +229,9 @@
     private Intent getCameraIntent() {
         KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
         boolean currentUserHasTrust = updateMonitor.getUserHasTrust(
-                mLockPatternUtils.getCurrentUser());
-        return mLockPatternUtils.isSecure() && !currentUserHasTrust
-                ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
+                KeyguardUpdateMonitor.getCurrentUser());
+        boolean secure = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser());
+        return (secure && !currentUserHasTrust) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
     }
 
     private void updateCameraVisibility() {
@@ -245,7 +241,7 @@
         }
         ResolveInfo resolved = mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
                 PackageManager.MATCH_DEFAULT_ONLY,
-                mLockPatternUtils.getCurrentUser());
+                KeyguardUpdateMonitor.getCurrentUser());
         boolean visible = !isCameraDisabledByDpm() && resolved != null
                 && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance);
         mCameraImageView.setVisibility(visible ? View.VISIBLE : View.GONE);
@@ -294,21 +290,7 @@
         mPhoneImageView.setClickable(touchExplorationEnabled);
         mCameraImageView.setFocusable(accessibilityEnabled);
         mPhoneImageView.setFocusable(accessibilityEnabled);
-        updateLockIconClickability();
-    }
-
-    private void updateLockIconClickability() {
-        if (mAccessibilityController == null) {
-            return;
-        }
-        boolean clickToUnlock = mAccessibilityController.isTouchExplorationEnabled();
-        boolean clickToForceLock = mUnlockMethodCache.isTrustManaged()
-                && !mAccessibilityController.isAccessibilityEnabled();
-        boolean longClickToForceLock = mUnlockMethodCache.isTrustManaged()
-                && !clickToForceLock;
-        mLockIcon.setClickable(clickToForceLock || clickToUnlock);
-        mLockIcon.setLongClickable(longClickToForceLock);
-        mLockIcon.setFocusable(mAccessibilityController.isAccessibilityEnabled());
+        mLockIcon.update();
     }
 
     @Override
@@ -339,13 +321,13 @@
                 0 /* velocityDp - N/A */);
         mIndicationController.showTransientIndication(
                 R.string.keyguard_indication_trust_disabled);
-        mLockPatternUtils.requireCredentialEntry(mLockPatternUtils.getCurrentUser());
+        mLockPatternUtils.requireCredentialEntry(KeyguardUpdateMonitor.getCurrentUser());
     }
 
     public void prewarmCamera() {
         Intent intent = getCameraIntent();
         String targetPackage = PreviewInflater.getTargetPackage(mContext, intent,
-                mLockPatternUtils.getCurrentUser());
+                KeyguardUpdateMonitor.getCurrentUser());
         if (targetPackage != null) {
             Intent prewarm = new Intent(MediaStore.ACTION_STILL_IMAGE_CAMERA_PREWARM);
             prewarm.setPackage(targetPackage);
@@ -361,7 +343,7 @@
         mPrewarmSent = false;
         Intent intent = getCameraIntent();
         String targetPackage = PreviewInflater.getTargetPackage(mContext, intent,
-                mLockPatternUtils.getCurrentUser());
+                KeyguardUpdateMonitor.getCurrentUser());
         if (targetPackage != null) {
             Intent prewarm = new Intent(MediaStore.ACTION_STILL_IMAGE_CAMERA_COOLDOWN);
             prewarm.setPackage(targetPackage);
@@ -375,7 +357,7 @@
         mPrewarmSent = false;
         final Intent intent = getCameraIntent();
         boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
-                mContext, intent, mLockPatternUtils.getCurrentUser());
+                mContext, intent, KeyguardUpdateMonitor.getCurrentUser());
         if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
             AsyncTask.execute(new Runnable() {
                 @Override
@@ -409,69 +391,12 @@
     @Override
     protected void onVisibilityChanged(View changedView, int visibility) {
         super.onVisibilityChanged(changedView, visibility);
-        if (isShown()) {
-            mTrustDrawable.start();
-        } else {
-            mTrustDrawable.stop();
-        }
         if (changedView == this && visibility == VISIBLE) {
-            updateLockIcon();
+            mLockIcon.update();
             updateCameraVisibility();
         }
     }
 
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        mTrustDrawable.stop();
-    }
-
-    private void updateLockIcon() {
-        boolean visible = isShown() && KeyguardUpdateMonitor.getInstance(mContext).isScreenOn();
-        if (visible) {
-            mTrustDrawable.start();
-        } else {
-            mTrustDrawable.stop();
-        }
-        if (!visible) {
-            return;
-        }
-        // TODO: Real icon for facelock.
-        boolean isFingerprintIcon =
-                KeyguardUpdateMonitor.getInstance(mContext).isFingerprintDetectionRunning();
-        boolean anyFingerprintIcon = isFingerprintIcon || mTransientFpError;
-        int iconRes = mTransientFpError ? R.drawable.ic_fingerprint_error
-                : isFingerprintIcon ? R.drawable.ic_fingerprint
-                : mUnlockMethodCache.isFaceUnlockRunning()
-                        ? com.android.internal.R.drawable.ic_account_circle
-                : mUnlockMethodCache.isCurrentlyInsecure() ? R.drawable.ic_lock_open_24dp
-                : R.drawable.ic_lock_24dp;
-
-        if (mLastUnlockIconRes != iconRes) {
-            Drawable icon = mContext.getDrawable(iconRes);
-            int iconHeight = getResources().getDimensionPixelSize(
-                    R.dimen.keyguard_affordance_icon_height);
-            int iconWidth = getResources().getDimensionPixelSize(
-                    R.dimen.keyguard_affordance_icon_width);
-            if (!anyFingerprintIcon && (icon.getIntrinsicHeight() != iconHeight
-                    || icon.getIntrinsicWidth() != iconWidth)) {
-                icon = new IntrinsicSizeDrawable(icon, iconWidth, iconHeight);
-            }
-            mLockIcon.setImageDrawable(icon);
-            mLockIcon.setPaddingRelative(0, 0, 0, anyFingerprintIcon
-                    ? getResources().getDimensionPixelSize(
-                            R.dimen.fingerprint_icon_additional_padding)
-                    : 0);
-            mLockIcon.setRestingAlpha(
-                    anyFingerprintIcon ? 1f : KeyguardAffordanceHelper.SWIPE_RESTING_ALPHA_AMOUNT);
-        }
-
-        // Hide trust circle when fingerprint is running.
-        boolean trustManaged = mUnlockMethodCache.isTrustManaged() && !anyFingerprintIcon;
-        mTrustDrawable.setTrustManaged(trustManaged);
-        updateLockIconClickability();
-    }
-
     public KeyguardAffordanceView getPhoneView() {
         return mPhoneImageView;
     }
@@ -503,7 +428,7 @@
 
     @Override
     public void onUnlockMethodStateChanged() {
-        updateLockIcon();
+        mLockIcon.update();
         updateCameraVisibility();
     }
 
@@ -563,9 +488,8 @@
     private final Runnable mTransientFpErrorClearRunnable = new Runnable() {
         @Override
         public void run() {
-            mTransientFpError = false;
+            mLockIcon.setTransientFpError(false);
             mIndicationController.hideTransientIndication();
-            updateLockIcon();
         }
     };
 
@@ -578,17 +502,17 @@
 
         @Override
         public void onScreenTurnedOn() {
-            updateLockIcon();
+            mLockIcon.update();
         }
 
         @Override
         public void onScreenTurnedOff(int why) {
-            updateLockIcon();
+            mLockIcon.update();
         }
 
         @Override
         public void onKeyguardVisibilityChanged(boolean showing) {
-            updateLockIcon();
+            mLockIcon.update();
         }
 
         @Override
@@ -597,24 +521,21 @@
 
         @Override
         public void onFingerprintRunningStateChanged(boolean running) {
-            updateLockIcon();
+            mLockIcon.update();
         }
 
         @Override
         public void onFingerprintHelp(int msgId, String helpString) {
-            mTransientFpError = true;
+            mLockIcon.setTransientFpError(true);
             mIndicationController.showTransientIndication(helpString,
                     getResources().getColor(R.color.system_warning_color, null));
             removeCallbacks(mTransientFpErrorClearRunnable);
             postDelayed(mTransientFpErrorClearRunnable, TRANSIENT_FP_ERROR_TIMEOUT);
-            updateLockIcon();
         }
 
         @Override
         public void onFingerprintError(int msgId, String errString) {
             // TODO: Go to bouncer if this is "too many attempts" (lockout) error.
-            Log.i(TAG, "FP Error: " + errString);
-            updateLockIcon();
         }
     };
 
@@ -622,29 +543,4 @@
             KeyguardIndicationController keyguardIndicationController) {
         mIndicationController = keyguardIndicationController;
     }
-
-    /**
-     * A wrapper around another Drawable that overrides the intrinsic size.
-     */
-    private static class IntrinsicSizeDrawable extends InsetDrawable {
-
-        private final int mIntrinsicWidth;
-        private final int mIntrinsicHeight;
-
-        public IntrinsicSizeDrawable(Drawable drawable, int intrinsicWidth, int intrinsicHeight) {
-            super(drawable, 0);
-            mIntrinsicWidth = intrinsicWidth;
-            mIntrinsicHeight = intrinsicHeight;
-        }
-
-        @Override
-        public int getIntrinsicWidth() {
-            return mIntrinsicWidth;
-        }
-
-        @Override
-        public int getIntrinsicHeight() {
-            return mIntrinsicHeight;
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
new file mode 100644
index 0000000..66f3232
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.KeyguardAffordanceView;
+import com.android.systemui.statusbar.policy.AccessibilityController;
+
+/**
+ * Manages the different states and animations of the unlock icon.
+ */
+public class LockIcon extends KeyguardAffordanceView {
+
+
+    private static final int STATE_LOCKED = 0;
+    private static final int STATE_LOCK_OPEN = 1;
+    private static final int STATE_FACE_UNLOCK = 2;
+    private static final int STATE_FINGERPRINT = 3;
+    private static final int STATE_FINGERPRINT_ERROR = 4;
+
+    private int mLastState = 0;
+    private boolean mTransientFpError;
+    private final TrustDrawable mTrustDrawable;
+    private final UnlockMethodCache mUnlockMethodCache;
+    private AccessibilityController mAccessibilityController;
+
+    public LockIcon(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mTrustDrawable = new TrustDrawable(context);
+        setBackground(mTrustDrawable);
+        mUnlockMethodCache = UnlockMethodCache.getInstance(context);
+    }
+
+    @Override
+    protected void onVisibilityChanged(View changedView, int visibility) {
+        super.onVisibilityChanged(changedView, visibility);
+        if (isShown()) {
+            mTrustDrawable.start();
+        } else {
+            mTrustDrawable.stop();
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mTrustDrawable.stop();
+    }
+
+    public void setTransientFpError(boolean transientFpError) {
+        mTransientFpError = transientFpError;
+        update();
+    }
+
+    public void update() {
+        boolean visible = isShown() && KeyguardUpdateMonitor.getInstance(mContext).isScreenOn();
+        if (visible) {
+            mTrustDrawable.start();
+        } else {
+            mTrustDrawable.stop();
+        }
+        if (!visible) {
+            return;
+        }
+        // TODO: Real icon for facelock.
+        int state = getState();
+        boolean anyFingerprintIcon = state == STATE_FINGERPRINT || state == STATE_FINGERPRINT_ERROR;
+        if (state != mLastState) {
+            int iconRes = getAnimationResForTransition(mLastState, state);
+            if (iconRes == -1) {
+                iconRes = getIconForState(state);
+            }
+            Drawable icon = mContext.getDrawable(iconRes);
+            AnimatedVectorDrawable animation = null;
+            if (icon instanceof AnimatedVectorDrawable) {
+                animation = (AnimatedVectorDrawable) icon;
+            }
+            int iconHeight = getResources().getDimensionPixelSize(
+                    R.dimen.keyguard_affordance_icon_height);
+            int iconWidth = getResources().getDimensionPixelSize(
+                    R.dimen.keyguard_affordance_icon_width);
+            if (!anyFingerprintIcon && (icon.getIntrinsicHeight() != iconHeight
+                    || icon.getIntrinsicWidth() != iconWidth)) {
+                icon = new IntrinsicSizeDrawable(icon, iconWidth, iconHeight);
+            }
+            setPaddingRelative(0, 0, 0, anyFingerprintIcon
+                    ? getResources().getDimensionPixelSize(
+                    R.dimen.fingerprint_icon_additional_padding)
+                    : 0);
+            setRestingAlpha(
+                    anyFingerprintIcon ? 1f : KeyguardAffordanceHelper.SWIPE_RESTING_ALPHA_AMOUNT);
+            setImageDrawable(icon);
+            if (animation != null) {
+                animation.start();
+            }
+        }
+
+        // Hide trust circle when fingerprint is running.
+        boolean trustManaged = mUnlockMethodCache.isTrustManaged() && !anyFingerprintIcon;
+        mTrustDrawable.setTrustManaged(trustManaged);
+        mLastState = state;
+        updateClickability();
+    }
+
+    private void updateClickability() {
+        if (mAccessibilityController == null) {
+            return;
+        }
+        boolean clickToUnlock = mAccessibilityController.isTouchExplorationEnabled();
+        boolean clickToForceLock = mUnlockMethodCache.isTrustManaged()
+                && !mAccessibilityController.isAccessibilityEnabled();
+        boolean longClickToForceLock = mUnlockMethodCache.isTrustManaged()
+                && !clickToForceLock;
+        setClickable(clickToForceLock || clickToUnlock);
+        setLongClickable(longClickToForceLock);
+        setFocusable(mAccessibilityController.isAccessibilityEnabled());
+    }
+
+    public void setAccessibilityController(AccessibilityController accessibilityController) {
+        mAccessibilityController = accessibilityController;
+    }
+
+    private int getIconForState(int state) {
+        switch (state) {
+            case STATE_LOCKED:
+                return R.drawable.ic_lock_24dp;
+            case STATE_LOCK_OPEN:
+                return R.drawable.ic_lock_open_24dp;
+            case STATE_FACE_UNLOCK:
+                return com.android.internal.R.drawable.ic_account_circle;
+            case STATE_FINGERPRINT:
+                return R.drawable.ic_fingerprint;
+            case STATE_FINGERPRINT_ERROR:
+                return R.drawable.ic_fingerprint_error;
+            default:
+                throw new IllegalArgumentException();
+        }
+    }
+
+    private int getAnimationResForTransition(int oldState, int newState) {
+        if (oldState == STATE_FINGERPRINT && newState == STATE_FINGERPRINT_ERROR) {
+            return R.drawable.lockscreen_fingerprint_error_state_animation;
+        } else {
+            return -1;
+        }
+    }
+
+    private int getState() {
+        boolean fingerprintRunning =
+                KeyguardUpdateMonitor.getInstance(mContext).isFingerprintDetectionRunning();
+        if (mTransientFpError) {
+            return STATE_FINGERPRINT_ERROR;
+        } else if (fingerprintRunning) {
+            return STATE_FINGERPRINT;
+        } else if (mUnlockMethodCache.isFaceUnlockRunning()) {
+            return STATE_FACE_UNLOCK;
+        } else if (mUnlockMethodCache.isCurrentlyInsecure()) {
+            return STATE_LOCK_OPEN;
+        } else {
+            return STATE_LOCKED;
+        }
+    }
+
+    /**
+     * A wrapper around another Drawable that overrides the intrinsic size.
+     */
+    private static class IntrinsicSizeDrawable extends InsetDrawable {
+
+        private final int mIntrinsicWidth;
+        private final int mIntrinsicHeight;
+
+        public IntrinsicSizeDrawable(Drawable drawable, int intrinsicWidth, int intrinsicHeight) {
+            super(drawable, 0);
+            mIntrinsicWidth = intrinsicWidth;
+            mIntrinsicHeight = intrinsicHeight;
+        }
+
+        @Override
+        public int getIntrinsicWidth() {
+            return mIntrinsicWidth;
+        }
+
+        @Override
+        public int getIntrinsicHeight() {
+            return mIntrinsicHeight;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index b87c25b..8914fb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -182,11 +182,11 @@
 
     private float mKeyguardStatusBarAnimateAlpha = 1f;
     private int mOldLayoutDirection;
-    private HeadsUpTouchHelper mHeadsUpTouchHelper = new HeadsUpTouchHelper();
-    private boolean mPinnedHeadsUpExist;
-    private boolean mExpansionIsFromHeadsUp;
-    private int mBottomBarHeight;
+    private HeadsUpTouchHelper mHeadsUpTouchHelper;
+    private boolean mIsExpansionFromHeadsUp;
+    private int mNavigationBarBottomHeight;
     private boolean mExpandingFromHeadsUp;
+    private boolean mCollapsedOnDown;
     private int mPositionMinSideMargin;
     private int mLastOrientation = -1;
 
@@ -534,17 +534,16 @@
     }
 
     @Override
-    public boolean
-    onInterceptTouchEvent(MotionEvent event) {
+    public boolean onInterceptTouchEvent(MotionEvent event) {
         if (mBlockTouches) {
             return false;
         }
         initDownStates(event);
         if (mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
-            mExpansionIsFromHeadsUp = true;
+            mIsExpansionFromHeadsUp = true;
             return true;
         }
-        if (!isShadeCollapsed() && onQsIntercept(event)) {
+        if (!isFullyCollapsed() && onQsIntercept(event)) {
             return true;
         }
         return super.onInterceptTouchEvent(event);
@@ -641,6 +640,7 @@
             mOnlyAffordanceInThisMotion = false;
             mQsTouchAboveFalsingThreshold = mQsFullyExpanded;
             mDozingOnDown = isDozing();
+            mCollapsedOnDown = isFullyCollapsed();
         }
     }
 
@@ -695,7 +695,7 @@
             return true;
         }
         mHeadsUpTouchHelper.onTouchEvent(event);
-        if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && handleQSTouch(event)) {
+        if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && handleQsTouch(event)) {
             return true;
         }
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
@@ -705,7 +705,7 @@
         return true;
     }
 
-    private boolean handleQSTouch(MotionEvent event) {
+    private boolean handleQsTouch(MotionEvent event) {
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN && getExpandedFraction() == 1f
                 && mStatusBar.getBarState() != StatusBarState.KEYGUARD && !mQsExpanded
                 && mQsExpansionEnabled) {
@@ -718,7 +718,7 @@
             mInitialTouchY = event.getX();
             mInitialTouchX = event.getY();
         }
-        if (!isShadeCollapsed()) {
+        if (!isFullyCollapsed()) {
             handleQsDown(event);
         }
         if (!mQsExpandImmediate && mQsTracking) {
@@ -731,7 +731,7 @@
                 || event.getActionMasked() == MotionEvent.ACTION_UP) {
             mConflictingQsExpansionGesture = false;
         }
-        if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isShadeCollapsed()
+        if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()
                 && mQsExpansionEnabled) {
             mTwoFingerQsExpandPossible = true;
         }
@@ -1191,8 +1191,8 @@
         updateEmptyShadeView();
         mQsNavbarScrim.setVisibility(mStatusBarState == StatusBarState.SHADE && mQsExpanded
                 && !mStackScrollerOverscrolling && mQsScrimEnabled
-                ? View.VISIBLE
-                : View.INVISIBLE);
+                        ? View.VISIBLE
+                        : View.INVISIBLE);
         if (mKeyguardUserSwitcher != null && mQsExpanded && !mStackScrollerOverscrolling) {
             mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */);
         }
@@ -1386,7 +1386,7 @@
      * @return Whether we should intercept a gesture to open Quick Settings.
      */
     private boolean shouldQuickSettingsIntercept(float x, float y, float yDiff) {
-        if (!mQsExpansionEnabled) {
+        if (!mQsExpansionEnabled || mCollapsedOnDown) {
             return false;
         }
         View header = mKeyguardShowing ? mKeyguardStatusBar : mHeader;
@@ -1461,8 +1461,8 @@
         updateHeader();
         updateUnlockIcon();
         updateNotificationTranslucency();
-        mHeadsUpManager.setIsExpanded(!isShadeCollapsed());
-        mNotificationStackScroller.setShadeExpanded(!isShadeCollapsed());
+        mHeadsUpManager.setIsExpanded(!isFullyCollapsed());
+        mNotificationStackScroller.setShadeExpanded(!isFullyCollapsed());
         if (DEBUG) {
             invalidate();
         }
@@ -1535,21 +1535,19 @@
         float alpha;
         if (mExpandingFromHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()) {
             alpha = 1f;
-            if (mNotificationStackScroller.getLayerType() == LAYER_TYPE_HARDWARE) {
-                mNotificationStackScroller.setLayerType(LAYER_TYPE_NONE, null);
-            }
         } else {
             alpha = (getNotificationsTopY() + mNotificationStackScroller.getItemHeight())
                     / (mQsMinExpansionHeight + mNotificationStackScroller.getBottomStackPeekSize()
                     - mNotificationStackScroller.getCollapseSecondCardPadding());
             alpha = Math.max(0, Math.min(alpha, 1));
             alpha = (float) Math.pow(alpha, 0.75);
-            if (alpha != 1f && mNotificationStackScroller.getLayerType() != LAYER_TYPE_HARDWARE) {
-                mNotificationStackScroller.setLayerType(LAYER_TYPE_HARDWARE, null);
-            } else if (alpha == 1f
-                    && mNotificationStackScroller.getLayerType() == LAYER_TYPE_HARDWARE) {
-                mNotificationStackScroller.setLayerType(LAYER_TYPE_NONE, null);
-            }
+        }
+
+        if (alpha != 1f && mNotificationStackScroller.getLayerType() != LAYER_TYPE_HARDWARE) {
+            mNotificationStackScroller.setLayerType(LAYER_TYPE_HARDWARE, null);
+        } else if (alpha == 1f
+                && mNotificationStackScroller.getLayerType() == LAYER_TYPE_HARDWARE) {
+            mNotificationStackScroller.setLayerType(LAYER_TYPE_NONE, null);
         }
         mNotificationStackScroller.setAlpha(alpha);
     }
@@ -1615,7 +1613,7 @@
         }
         float stackTranslation = mNotificationStackScroller.getStackTranslation();
         float translation = stackTranslation / HEADER_RUBBERBAND_FACTOR;
-        if (mHeadsUpManager.hasPinnedHeadsUp() || mExpansionIsFromHeadsUp) {
+        if (mHeadsUpManager.hasPinnedHeadsUp() || mIsExpansionFromHeadsUp) {
             translation = mNotificationStackScroller.getTopPadding() + stackTranslation
                     - mNotificationTopPadding - mQsMinExpansionHeight;
         }
@@ -1683,16 +1681,16 @@
         mHeadsUpManager.onExpandingFinished();
         mIsExpanding = false;
         mScrollYOverride = -1;
-        if (isShadeCollapsed()) {
+        if (isFullyCollapsed()) {
             setListening(false);
         } else {
             setListening(true);
         }
         mQsExpandImmediate = false;
         mTwoFingerQsExpandPossible = false;
-        mExpansionIsFromHeadsUp = false;
-        mNotificationStackScroller.setTrackingHeadsUp(mHeadsUpTouchHelper.isTrackingHeadsUp());
-        mExpandingFromHeadsUp = mHeadsUpTouchHelper.isTrackingHeadsUp();
+        mIsExpansionFromHeadsUp = false;
+        mNotificationStackScroller.setTrackingHeadsUp(false);
+        mExpandingFromHeadsUp = false;
     }
 
     private void setListening(boolean listening) {
@@ -1793,13 +1791,13 @@
 
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-        mBottomBarHeight = insets.getSystemWindowInsetBottom();
+        mNavigationBarBottomHeight = insets.getSystemWindowInsetBottom();
         updateMaxHeadsUpTranslation();
         return insets;
     }
 
     private void updateMaxHeadsUpTranslation() {
-        mNotificationStackScroller.setHeadsUpBoundaries(getHeight(), mBottomBarHeight);
+        mNotificationStackScroller.setHeadsUpBoundaries(getHeight(), mNavigationBarBottomHeight);
     }
 
     @Override
@@ -2160,48 +2158,43 @@
     }
 
     @Override
-    public void OnPinnedHeadsUpExistChanged(final boolean exist, boolean changeImmediatly) {
-        if (exist != mPinnedHeadsUpExist) {
-            mPinnedHeadsUpExist = exist;
-            if (exist) {
-                mHeadsUpExistenceChangedRunnable.run();
-                updateNotificationTranslucency();
-            } else {
-                mNotificationStackScroller.performOnAnimationFinished(
-                        mHeadsUpExistenceChangedRunnable);
-            }
+    public void onPinnedModeChanged(final boolean inPinnedMode) {
+        if (inPinnedMode) {
+            mHeadsUpExistenceChangedRunnable.run();
+            updateNotificationTranslucency();
+        } else {
+            mNotificationStackScroller.runAfterAnimationFinished(
+                    mHeadsUpExistenceChangedRunnable);
         }
     }
 
     @Override
-    public void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp) {
-        if (isHeadsUp) {
-            mNotificationStackScroller.generateHeadsUpAnimation(headsUp, true);
-        }
+    public void onHeadsUpPinned(ExpandableNotificationRow headsUp) {
+        mNotificationStackScroller.generateHeadsUpAnimation(headsUp, true);
     }
 
     @Override
-    public void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) {
+    public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) {
+    }
+
+    @Override
+    public void onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) {
         mNotificationStackScroller.generateHeadsUpAnimation(entry.row, isHeadsUp);
     }
 
     @Override
-    protected boolean isShadeCollapsed() {
-        return mExpandedHeight == 0;
-    }
-
-    @Override
     public void setHeadsUpManager(HeadsUpManager headsUpManager) {
         super.setHeadsUpManager(headsUpManager);
-        mHeadsUpTouchHelper.bind(headsUpManager, mNotificationStackScroller, this);
+        mHeadsUpTouchHelper = new HeadsUpTouchHelper(headsUpManager, mNotificationStackScroller,
+                this);
     }
 
     public void setTrackingHeadsUp(boolean tracking) {
         if (tracking) {
-            // otherwise we update the state when the expansion is finished
             mNotificationStackScroller.setTrackingHeadsUp(true);
             mExpandingFromHeadsUp = true;
         }
+        // otherwise we update the state when the expansion is finished
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 4452dd7c..85f312c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -46,13 +46,13 @@
 public abstract class PanelView extends FrameLayout {
     public static final boolean DEBUG = PanelBar.DEBUG;
     public static final String TAG = PanelView.class.getSimpleName();
-    protected HeadsUpManager mHeadsUpManager;
-
     private final void logf(String fmt, Object... args) {
         Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
     }
 
     protected PhoneStatusBar mStatusBar;
+    protected HeadsUpManager mHeadsUpManager;
+
     private float mPeekHeight;
     private float mHintDistance;
     private int mEdgeTapAreaWidth;
@@ -242,15 +242,15 @@
         final float y = event.getY(pointerIndex);
 
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
-            mGestureWaitForTouchSlop = isShadeCollapsed() || hasConflictingGestures();
-            mIgnoreXTouchSlop = isShadeCollapsed() || shouldGestureIgnoreXTouchSlop(x, y);
+            mGestureWaitForTouchSlop = isFullyCollapsed() || hasConflictingGestures();
+            mIgnoreXTouchSlop = isFullyCollapsed() || shouldGestureIgnoreXTouchSlop(x, y);
         }
 
         switch (event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
                 startExpandMotion(x, y, false /* startTracking */, mExpandedHeight);
                 mJustPeeked = false;
-                mPanelClosedOnDown = isShadeCollapsed();
+                mPanelClosedOnDown = isFullyCollapsed();
                 mHasLayoutedSinceDown = false;
                 mUpdateFlingOnLayout = false;
                 mMotionAborted = false;
@@ -268,7 +268,7 @@
                             || mPeekPending || mPeekAnimator != null;
                     onTrackingStarted();
                 }
-                if (isShadeCollapsed()) {
+                if (isFullyCollapsed()) {
                     schedulePeek();
                 }
                 break;
@@ -472,7 +472,7 @@
                 mTouchSlopExceeded = false;
                 mJustPeeked = false;
                 mMotionAborted = false;
-                mPanelClosedOnDown = isShadeCollapsed();
+                mPanelClosedOnDown = isFullyCollapsed();
                 mHasLayoutedSinceDown = false;
                 mUpdateFlingOnLayout = false;
                 mTouchAboveFalsingThreshold = false;
@@ -707,7 +707,7 @@
         // If the user isn't actively poking us, let's update the height
         if ((!mTracking || isTrackingBlocked())
                 && mHeightAnimator == null
-                && !isShadeCollapsed()
+                && !isFullyCollapsed()
                 && currentMaxPanelHeight != mExpandedHeight
                 && !mPeekPending
                 && mPeekAnimator == null
@@ -1057,8 +1057,6 @@
      */
     protected abstract int getClearAllHeight();
 
-    protected abstract boolean isShadeCollapsed();
-
     public void setHeadsUpManager(HeadsUpManager headsUpManager) {
         mHeadsUpManager = headsUpManager;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 6b17589..b1d48f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1152,11 +1152,11 @@
 
     @Override
     public void removeNotification(String key, RankingMap ranking) {
-        boolean defferRemoval = false;
+        boolean deferRemoval = false;
         if (mHeadsUpManager.isHeadsUp(key)) {
-            defferRemoval = !mHeadsUpManager.removeNotification(key);
+            deferRemoval = !mHeadsUpManager.removeNotification(key);
         }
-        if (defferRemoval) {
+        if (deferRemoval) {
             mLatestRankingMap = ranking;
             mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key));
             return;
@@ -1838,8 +1838,8 @@
     }
 
     @Override
-    public void OnPinnedHeadsUpExistChanged(boolean exist, boolean changeImmediatly) {
-        if (exist) {
+    public void onPinnedModeChanged(boolean inPinnedMode) {
+        if (inPinnedMode) {
             mStatusBarWindowManager.setHeadsUpShowing(true);
         } else {
             Runnable endRunnable = new Runnable() {
@@ -1850,20 +1850,24 @@
                     }
                 }
             };
-            if (changeImmediatly) {
+            if (!mNotificationPanel.isFullyCollapsed()) {
                 endRunnable.run();
             } else {
-                mStackScroller.performOnAnimationFinished(endRunnable);
+                mStackScroller.runAfterAnimationFinished(endRunnable);
             }
         }
     }
 
     @Override
-    public void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp) {
+    public void onHeadsUpPinned(ExpandableNotificationRow headsUp) {
     }
 
     @Override
-    public void OnHeadsUpStateChanged(Entry entry, boolean isHeadsUp) {
+    public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) {
+    }
+
+    @Override
+    public void onHeadsUpStateChanged(Entry entry, boolean isHeadsUp) {
         if (!isHeadsUp && mHeadsUpEntriesToRemoveOnSwitch.contains(entry)) {
             removeNotification(entry.key, mLatestRankingMap);
             mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
@@ -1880,10 +1884,11 @@
             boolean alertAgain) {
         final boolean wasHeadsUp = isHeadsUp(key);
         if (wasHeadsUp) {
-            mHeadsUpManager.updateNotification(entry, alertAgain);
             if (!shouldInterrupt) {
                 // We don't want this to be interrupting anymore, lets remove it
                 mHeadsUpManager.removeNotification(key);
+            } else {
+                mHeadsUpManager.updateNotification(entry, alertAgain);
             }
         } else if (shouldInterrupt && alertAgain) {
             // This notification was updated to be a heads-up, show it!
@@ -1929,7 +1934,7 @@
     }
 
     @Override
-    public void escalateHeadsUp() {
+    public void maybeEscalateHeadsUp() {
         TreeSet<HeadsUpManager.HeadsUpEntry> entries = mHeadsUpManager.getSortedEntries();
         for (HeadsUpManager.HeadsUpEntry entry : entries) {
             final StatusBarNotification sbn = entry.entry.notification;
@@ -2852,6 +2857,7 @@
         } catch (RemoteException e) {
             // Ignore.
         }
+        setNotificationsShown(newlyVisibleAr);
     }
 
     // State logging
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index e701783..ae98e76 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -80,7 +80,7 @@
     private float mCurrentInFrontAlpha;
     private float mCurrentBehindAlpha;
     private float mCurrentHeadsUpAlpha = 1;
-    private int mAmountOfPinnedHeadsUps;
+    private int mPinnedHeadsUpCount;
     private float mTopHeadsUpDragAmount;
     private View mDraggedHeadsUpView;
 
@@ -347,25 +347,27 @@
     }
 
     @Override
-    public void OnPinnedHeadsUpExistChanged(boolean exist, boolean changeImmediatly) {
+    public void onPinnedModeChanged(boolean inPinnedMode) {
     }
 
     @Override
-    public void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp) {
-        if (isHeadsUp) {
-            mAmountOfPinnedHeadsUps++;
-        } else {
-            mAmountOfPinnedHeadsUps--;
-            if (headsUp == mDraggedHeadsUpView) {
-                mDraggedHeadsUpView = null;
-                mTopHeadsUpDragAmount = 0.0f;
-            }
+    public void onHeadsUpPinned(ExpandableNotificationRow headsUp) {
+        mPinnedHeadsUpCount++;
+        updateHeadsUpScrim(true);
+    }
+
+    @Override
+    public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) {
+        mPinnedHeadsUpCount--;
+        if (headsUp == mDraggedHeadsUpView) {
+            mDraggedHeadsUpView = null;
+            mTopHeadsUpDragAmount = 0.0f;
         }
         updateHeadsUpScrim(true);
     }
 
     @Override
-    public void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) {
+    public void onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) {
     }
 
     private void updateHeadsUpScrim(boolean animate) {
@@ -374,12 +376,10 @@
                 TAG_KEY_ANIM);
         float animEndValue = -1;
         if (previousAnimator != null) {
-            if ((animate || alpha == mCurrentHeadsUpAlpha)) {
-                // lets cancel any running animators
+            if (animate || alpha == mCurrentHeadsUpAlpha) {
                 previousAnimator.cancel();
             }
-            animEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim,
-                    TAG_HUN_START_ALPHA);
+            animEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim, TAG_HUN_START_ALPHA);
         }
         if (alpha != mCurrentHeadsUpAlpha && alpha != animEndValue) {
             if (animate) {
@@ -390,7 +390,7 @@
                 if (previousAnimator != null) {
                     float previousStartValue = StackStateAnimator.getChildTag(mHeadsUpScrim,
                             TAG_HUN_START_ALPHA);
-                   float previousEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim,
+                    float previousEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim,
                            TAG_HUN_END_ALPHA);
                     // we need to increase all animation keyframes of the previous animator by the
                     // relative change to the end value
@@ -410,6 +410,13 @@
         }
     }
 
+    /**
+     * Set the amount the current top heads up view is dragged. The range is from 0 to 1 and 0 means
+     * the heads up is in its resting space and 1 means it's fully dragged out.
+     *
+     * @param draggedHeadsUpView the dragged view
+     * @param topHeadsUpDragAmount how far is it dragged
+     */
     public void setTopHeadsUpDragAmount(View draggedHeadsUpView, float topHeadsUpDragAmount) {
         mTopHeadsUpDragAmount = topHeadsUpDragAmount;
         mDraggedHeadsUpView = draggedHeadsUpView;
@@ -417,9 +424,9 @@
     }
 
     private float calculateHeadsUpAlpha() {
-        if (mAmountOfPinnedHeadsUps >= 2) {
+        if (mPinnedHeadsUpCount >= 2) {
             return 1.0f;
-        } else if (mAmountOfPinnedHeadsUps == 0) {
+        } else if (mPinnedHeadsUpCount == 0) {
             return 0.0f;
         } else {
             return 1.0f - mTopHeadsUpDragAmount;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java
index 4a43c47..45c8938 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java
@@ -27,6 +27,7 @@
 import android.util.Log;
 
 import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
 
 import java.util.HashMap;
 import java.util.List;
@@ -228,7 +229,7 @@
 
         // Get the list of applications that can handle the intent.
         final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
-                intent, PackageManager.MATCH_DEFAULT_ONLY, mLockPatternUtils.getCurrentUser());
+                intent, PackageManager.MATCH_DEFAULT_ONLY, KeyguardUpdateMonitor.getCurrentUser());
         if (appList.size() == 0) {
             if (DEBUG) Log.d(TAG, "No targets found for secure camera intent");
             return false;
@@ -237,7 +238,7 @@
         // Get the application that the intent resolves to.
         ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
                 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
-                mLockPatternUtils.getCurrentUser());
+                KeyguardUpdateMonitor.getCurrentUser());
 
         if (resolved == null || resolved.activityInfo == null) {
             return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index 65cd268..66d71f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -80,8 +80,8 @@
     }
 
     private void update(boolean updateAlways) {
-        int user = mLockPatternUtils.getCurrentUser();
-        boolean secure = mLockPatternUtils.isSecure();
+        int user = KeyguardUpdateMonitor.getCurrentUser();
+        boolean secure = mLockPatternUtils.isSecure(user);
         boolean currentlyInsecure = !secure ||  mKeyguardUpdateMonitor.getUserHasTrust(user);
         boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
         boolean faceUnlockRunning = mKeyguardUpdateMonitor.isFaceUnlockRunning(user)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index b4e4773..8f83daa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -35,11 +35,16 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Stack;
 import java.util.TreeSet;
 
+/**
+ * A manager which handles heads up notifications which is a special mode where
+ * they simply peek from the top of the screen.
+ */
 public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsListener {
     private static final String TAG = "HeadsUpManager";
     private static final boolean DEBUG = false;
@@ -48,7 +53,7 @@
     private final int mHeadsUpNotificationDecay;
     private final int mMinimumDisplayTime;
 
-    private final int mTouchSensitivityDelay;
+    private final int mTouchAcceptanceDelay;
     private final ArrayMap<String, Long> mSnoozedPackages;
     private final HashSet<OnHeadsUpChangedListener> mListeners = new HashSet<>();
     private final int mDefaultSnoozeLengthMs;
@@ -67,13 +72,12 @@
 
         @Override
         public boolean release(HeadsUpEntry instance) {
-            instance.removeAutoCancelCallbacks();
+            instance.reset();
             mPoolObjects.push(instance);
             return true;
         }
     };
 
-
     private PhoneStatusBar mBar;
     private int mSnoozeLengthMs;
     private ContentObserver mSettingsObserver;
@@ -86,13 +90,12 @@
     private boolean mTrackingHeadsUp;
     private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>();
     private boolean mIsExpanded;
-    private boolean mHasPinnedHeadsUp;
+    private boolean mHasPinnedNotification;
     private int[] mTmpTwoArray = new int[2];
 
     public HeadsUpManager(final Context context, ViewTreeObserver observer) {
         Resources resources = context.getResources();
-        mTouchSensitivityDelay = resources.getInteger(R.integer.heads_up_sensitivity_delay);
-        if (DEBUG) Log.v(TAG, "create() " + mTouchSensitivityDelay);
+        mTouchAcceptanceDelay = resources.getInteger(R.integer.touch_acceptance_delay);
         mSnoozedPackages = new ArrayMap<>();
         mDefaultSnoozeLengthMs = resources.getInteger(R.integer.heads_up_default_snooze_length_ms);
         mSnoozeLengthMs = mDefaultSnoozeLengthMs;
@@ -116,7 +119,6 @@
         context.getContentResolver().registerContentObserver(
                 Settings.Global.getUriFor(SETTING_HEADS_UP_SNOOZE_LENGTH_MS), false,
                 mSettingsObserver);
-        if (DEBUG) Log.v(TAG, "mSnoozeLengthMs = " + mSnoozeLengthMs);
         observer.addOnComputeInternalInsetsListener(this);
     }
 
@@ -154,7 +156,7 @@
         if (alert) {
             HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(headsUp.key);
             headsUpEntry.updateEntry();
-            setEntryToShade(headsUpEntry, mIsExpanded, false /* justAdded */, false);
+            setEntryPinned(headsUpEntry, !mIsExpanded /* isPinned */);
         }
     }
 
@@ -165,22 +167,23 @@
         headsUpEntry.setEntry(entry);
         mHeadsUpEntries.put(entry.key, headsUpEntry);
         entry.row.setHeadsUp(true);
-        setEntryToShade(headsUpEntry, mIsExpanded /* inShade */, true /* justAdded */, false);
+        setEntryPinned(headsUpEntry, !mIsExpanded /* isPinned */);
         for (OnHeadsUpChangedListener listener : mListeners) {
-            listener.OnHeadsUpStateChanged(entry, true);
+            listener.onHeadsUpStateChanged(entry, true);
         }
         entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
     }
 
-    private void setEntryToShade(HeadsUpEntry headsUpEntry, boolean inShade, boolean justAdded,
-            boolean forceImmediate) {
+    private void setEntryPinned(HeadsUpEntry headsUpEntry, boolean isPinned) {
         ExpandableNotificationRow row = headsUpEntry.entry.row;
-        if (row.isInShade() != inShade || justAdded) {
-            row.setInShade(inShade);
-            if (!justAdded || !inShade) {
-                updatePinnedHeadsUpState(forceImmediate);
-                for (OnHeadsUpChangedListener listener : mListeners) {
-                    listener.OnHeadsUpPinnedChanged(row, !inShade);
+        if (row.isPinned() != isPinned) {
+            row.setPinned(isPinned);
+            updatePinnedMode();
+            for (OnHeadsUpChangedListener listener : mListeners) {
+                if (isPinned) {
+                    listener.onHeadsUpPinned(row);
+                } else {
+                    listener.onHeadsUpUnPinned(row);
                 }
             }
         }
@@ -189,24 +192,23 @@
     private void removeHeadsUpEntry(NotificationData.Entry entry) {
         HeadsUpEntry remove = mHeadsUpEntries.remove(entry.key);
         mSortedEntries.remove(remove);
-        mEntryPool.release(remove);
         entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
         entry.row.setHeadsUp(false);
-        setEntryToShade(remove, true /* inShade */, false /* justAdded */,
-                false /* forceImmediate */);
+        setEntryPinned(remove, false /* isPinned */);
         for (OnHeadsUpChangedListener listener : mListeners) {
-            listener.OnHeadsUpStateChanged(entry, false);
+            listener.onHeadsUpStateChanged(entry, false);
         }
+        mEntryPool.release(remove);
     }
 
-    private void updatePinnedHeadsUpState(boolean forceImmediate) {
-        boolean hasPinnedHeadsUp = hasPinnedHeadsUpInternal();
-        if (hasPinnedHeadsUp == mHasPinnedHeadsUp) {
+    private void updatePinnedMode() {
+        boolean hasPinnedNotification = hasPinnedNotificationInternal();
+        if (hasPinnedNotification == mHasPinnedNotification) {
             return;
         }
-        mHasPinnedHeadsUp = hasPinnedHeadsUp;
-        for (OnHeadsUpChangedListener listener :mListeners) {
-            listener.OnPinnedHeadsUpExistChanged(hasPinnedHeadsUp, forceImmediate);
+        mHasPinnedNotification = hasPinnedNotification;
+        for (OnHeadsUpChangedListener listener : mListeners) {
+            listener.onPinnedModeChanged(hasPinnedNotification);
         }
     }
 
@@ -222,7 +224,7 @@
             releaseImmediately(key);
             return true;
         } else {
-            getHeadsUpEntry(key).hideAsSoonAsPossible();
+            getHeadsUpEntry(key).removeAsSoonAsPossible();
             return false;
         }
     }
@@ -245,14 +247,13 @@
         return mHeadsUpEntries.containsKey(key);
     }
 
-
     /**
      * Push any current Heads Up notification down into the shade.
      */
     public void releaseAllImmediately() {
         if (DEBUG) Log.v(TAG, "releaseAllImmediately");
-        HashSet<String> keys = new HashSet<>(mHeadsUpEntries.keySet());
-        for (String key: keys) {
+        ArrayList<String> keys = new ArrayList<>(mHeadsUpEntries.keySet());
+        for (String key : keys) {
             releaseImmediately(key);
         }
     }
@@ -280,7 +281,7 @@
     }
 
     public void snooze() {
-        for (String key: mHeadsUpEntries.keySet()) {
+        for (String key : mHeadsUpEntries.keySet()) {
             HeadsUpEntry entry = mHeadsUpEntries.get(key);
             String packageName = entry.entry.notification.getPackageName();
             mSnoozedPackages.put(snoozeKey(packageName, mUser),
@@ -310,8 +311,11 @@
     }
 
     /**
+     * Decides whether a click is invalid for a notification, i.e it has not been shown long enough
+     * that a user might have consciously clicked on it.
+     *
      * @param key the key of the touched notification
-     * @return whether the touch is valid and should not be discarded
+     * @return whether the touch is invalid and should be discarded
      */
     public boolean shouldSwallowClick(String key) {
         HeadsUpEntry entry = mHeadsUpEntries.get(key);
@@ -322,14 +326,14 @@
     }
 
     public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
-        if (!mIsExpanded && mHasPinnedHeadsUp) {
+        if (!mIsExpanded && mHasPinnedNotification) {
             int minX = Integer.MAX_VALUE;
             int maxX = 0;
             int minY = Integer.MAX_VALUE;
             int maxY = 0;
-            for (HeadsUpEntry entry: mSortedEntries) {
+            for (HeadsUpEntry entry : mSortedEntries) {
                 ExpandableNotificationRow row = entry.entry.row;
-                if (!row.isInShade()) {
+                if (row.isPinned()) {
                     row.getLocationOnScreen(mTmpTwoArray);
                     minX = Math.min(minX, mTmpTwoArray[0]);
                     minY = Math.min(minY, 0);
@@ -349,7 +353,7 @@
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("HeadsUpManager state:");
-        pw.print("  mTouchSensitivityDelay="); pw.println(mTouchSensitivityDelay);
+        pw.print("  mTouchAcceptanceDelay="); pw.println(mTouchAcceptanceDelay);
         pw.print("  mSnoozeLengthMs="); pw.println(mSnoozeLengthMs);
         pw.print("  now="); pw.println(SystemClock.elapsedRealtime());
         pw.print("  mUser="); pw.println(mUser);
@@ -365,38 +369,32 @@
     }
 
     public boolean hasPinnedHeadsUp() {
-        return mHasPinnedHeadsUp;
+        return mHasPinnedNotification;
     }
 
-    private boolean hasPinnedHeadsUpInternal() {
-        for (String key: mHeadsUpEntries.keySet()) {
+    private boolean hasPinnedNotificationInternal() {
+        for (String key : mHeadsUpEntries.keySet()) {
             HeadsUpEntry entry = mHeadsUpEntries.get(key);
-            if (!entry.entry.row.isInShade()) {
+            if (entry.entry.row.isPinned()) {
                 return true;
             }
         }
         return false;
     }
 
-    public void addSwipedOutKey(String key) {
+    /**
+     * Notifies that a notification was swiped out and will be removed.
+     *
+     * @param key the notification key
+     */
+    public void addSwipedOutNotification(String key) {
         mSwipedOutKeys.add(key);
     }
 
-    public float getHighestPinnedHeadsUp() {
-        float max = 0;
-        for (HeadsUpEntry entry: mSortedEntries) {
-            if (!entry.entry.row.isInShade()) {
-                max = Math.max(max, entry.entry.row.getActualHeight());
-            }
-        }
-        return max;
-    }
-
-    public void releaseAllToShade() {
-        for (String key: mHeadsUpEntries.keySet()) {
+    public void unpinAll() {
+        for (String key : mHeadsUpEntries.keySet()) {
             HeadsUpEntry entry = mHeadsUpEntries.get(key);
-            setEntryToShade(entry, true /* toShade */, false /* justAdded */,
-                    true /* forceImmediate */);
+            setEntryPinned(entry, false /* isPinned */);
         }
     }
 
@@ -420,7 +418,7 @@
         if (isExpanded != mIsExpanded) {
             mIsExpanded = isExpanded;
             if (isExpanded) {
-                releaseAllToShade();
+                unpinAll();
             }
         }
     }
@@ -430,6 +428,12 @@
         return topEntry != null ? topEntry.entry.row.getHeadsUpHeight() : 0;
     }
 
+    /**
+     * Compare two entries and decide how they should be ranked.
+     *
+     * @return -1 if the first argument should be ranked higher than the second, 1 if the second
+     * one should be ranked higher and 0 if they are equal.
+     */
     public int compare(NotificationData.Entry a, NotificationData.Entry b) {
         HeadsUpEntry aEntry = getHeadsUpEntry(a.key);
         HeadsUpEntry bEntry = getHeadsUpEntry(b.key);
@@ -439,6 +443,11 @@
         return aEntry.compareTo(bEntry);
     }
 
+
+    /**
+     * This represents a notification and how long it is in a heads up mode. It also manages its
+     * lifecycle automatically when created.
+     */
     public class HeadsUpEntry implements Comparable<HeadsUpEntry> {
         public NotificationData.Entry entry;
         public long postTime;
@@ -449,7 +458,7 @@
             this.entry = entry;
 
             // The actual post time will be just after the heads-up really slided in
-            postTime = mClock.currentTimeMillis() + mTouchSensitivityDelay;
+            postTime = mClock.currentTimeMillis() + mTouchAcceptanceDelay;
             mRemoveHeadsUpRunnable = new Runnable() {
                 @Override
                 public void run() {
@@ -467,7 +476,7 @@
             long currentTime = mClock.currentTimeMillis();
             earliestRemovaltime = currentTime + mMinimumDisplayTime;
             postTime = Math.max(postTime, currentTime);
-            removeAutoCancelCallbacks();
+            removeAutoRemovalCallbacks();
             if (canEntryDecay()) {
                 long finishTime = postTime + mHeadsUpNotificationDecay;
                 long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime);
@@ -487,7 +496,7 @@
                             : -1;
         }
 
-        public void removeAutoCancelCallbacks() {
+        public void removeAutoRemovalCallbacks() {
             mHandler.removeCallbacks(mRemoveHeadsUpRunnable);
         }
 
@@ -495,11 +504,17 @@
             return earliestRemovaltime < mClock.currentTimeMillis();
         }
 
-        public void hideAsSoonAsPossible() {
-            removeAutoCancelCallbacks();
+        public void removeAsSoonAsPossible() {
+            removeAutoRemovalCallbacks();
             mHandler.postDelayed(mRemoveHeadsUpRunnable,
                     earliestRemovaltime - mClock.currentTimeMillis());
         }
+
+        public void reset() {
+            removeAutoRemovalCallbacks();
+            entry = null;
+            mRemoveHeadsUpRunnable = null;
+        }
     }
 
     /**
@@ -519,8 +534,29 @@
     }
 
     public interface OnHeadsUpChangedListener {
-        void OnPinnedHeadsUpExistChanged(boolean exist, boolean changeImmediatly);
-        void OnHeadsUpPinnedChanged(ExpandableNotificationRow headsUp, boolean isHeadsUp);
-        void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp);
+        /**
+         * The state whether there exist pinned heads-ups or not changed.
+         *
+         * @param inPinnedMode whether there are any pinned heads-ups
+         */
+        void onPinnedModeChanged(boolean inPinnedMode);
+
+        /**
+         * A notification was just pinned to the top.
+         */
+        void onHeadsUpPinned(ExpandableNotificationRow headsUp);
+
+        /**
+         * A notification was just unpinned from the top.
+         */
+        void onHeadsUpUnPinned(ExpandableNotificationRow headsUp);
+
+        /**
+         * A notification just became a heads up or turned back to its normal state.
+         *
+         * @param entry the entry of the changed notification
+         * @param isHeadsUp whether the notification is now a headsUp notification
+         */
+        void onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
index 0dce82f..5d89e2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
@@ -26,6 +26,7 @@
 import android.view.View;
 
 import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.statusbar.phone.KeyguardPreviewContainer;
 
 import java.util.List;
@@ -80,13 +81,13 @@
         WidgetInfo info = new WidgetInfo();
         PackageManager packageManager = mContext.getPackageManager();
         final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
-                intent, PackageManager.MATCH_DEFAULT_ONLY, mLockPatternUtils.getCurrentUser());
+                intent, PackageManager.MATCH_DEFAULT_ONLY, KeyguardUpdateMonitor.getCurrentUser());
         if (appList.size() == 0) {
             return null;
         }
         ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
                 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
-                mLockPatternUtils.getCurrentUser());
+                KeyguardUpdateMonitor.getCurrentUser());
         if (wouldLaunchResolverActivity(resolved, appList)) {
             return null;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/HeadsUpAppearInterpolator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/HeadsUpAppearInterpolator.java
new file mode 100644
index 0000000..05c0099
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/HeadsUpAppearInterpolator.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.stack;
+
+import android.graphics.Path;
+import android.view.animation.PathInterpolator;
+
+/**
+ * An interpolator specifically designed for the appear animation of heads up notifications.
+ */
+public class HeadsUpAppearInterpolator extends PathInterpolator {
+    public HeadsUpAppearInterpolator() {
+        super(getAppearPath());
+    }
+
+    private static Path getAppearPath() {
+        Path path = new Path();
+        path.moveTo(0, 0);
+        float x1 = 250f;
+        float x2 = 150f;
+        float x3 = 100f;
+        float y1 = 90f;
+        float y2 = 78f;
+        float y3 = 80f;
+        float xTot = (x1 + x2 + x3);
+        path.cubicTo(x1 * 0.9f / xTot, 0f,
+                x1 * 0.8f / xTot, y1 / y3,
+                x1 / xTot , y1 / y3);
+        path.cubicTo((x1 + x2 * 0.4f) / xTot, y1 / y3,
+                (x1 + x2 * 0.2f) / xTot, y2 / y3,
+                (x1 + x2) / xTot, y2 / y3);
+        path.cubicTo((x1 + x2 + x3 * 0.4f) / xTot, y2 / y3,
+                (x1 + x2 + x3 * 0.2f) / xTot, 1f,
+                1f, 1f);
+        return path;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 88fc602..a1b0cae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -204,7 +204,6 @@
     private ViewGroup mScrollView;
     private boolean mInterceptDelegateEnabled;
     private boolean mDelegateToScrollView;
-
     private boolean mDisallowScrollingInThisMotion;
     private long mGoToFullShadeDelay;
     private ViewTreeObserver.OnPreDrawListener mChildrenUpdater
@@ -487,9 +486,9 @@
         int stackHeight;
         float paddingOffset;
         boolean trackingHeadsUp = mTrackingHeadsUp;
-        int normalExpandPositionStart = trackingHeadsUp ? mHeadsUpManager.getTopHeadsUpHeight()
+        int normalUnfoldPositionStart = trackingHeadsUp ? mHeadsUpManager.getTopHeadsUpHeight()
                 : minStackHeight;
-        if (newStackHeight - mTopPadding - mTopPaddingOverflow >= normalExpandPositionStart
+        if (newStackHeight - mTopPadding - mTopPaddingOverflow >= normalUnfoldPositionStart
                 || getNotGoneChildCount() == 0) {
             paddingOffset = mTopPaddingOverflow;
             stackHeight = newStackHeight;
@@ -582,7 +581,7 @@
         if (v instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) v;
             if (row.isHeadsUp()) {
-                mHeadsUpManager.addSwipedOutKey(row.getStatusBarNotification().getKey());
+                mHeadsUpManager.addSwipedOutNotification(row.getStatusBarNotification().getKey());
             }
         }
         final View veto = v.findViewById(R.id.veto);
@@ -626,10 +625,10 @@
         requestChildrenUpdate();
     }
 
-    public boolean isPinnedHeadsUp(View v) {
+    public static boolean isPinnedHeadsUp(View v) {
         if (v instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-            return row.isHeadsUp() && !row.isInShade();
+            return row.isHeadsUp() && row.isPinned();
         }
         return false;
     }
@@ -711,7 +710,7 @@
             if (touchY >= top && touchY <= bottom && touchX >= left && touchX <= right) {
                 if (slidingChild instanceof ExpandableNotificationRow) {
                     ExpandableNotificationRow row = (ExpandableNotificationRow) slidingChild;
-                    if (row.isHeadsUp() && !row.isInShade()
+                    if (row.isHeadsUp() && row.isPinned()
                             && mHeadsUpManager.getTopEntry().entry.row != row) {
                         continue;
                     }
@@ -812,7 +811,8 @@
         }
         handleEmptySpaceClick(ev);
         boolean expandWantsIt = false;
-        if (!mSwipingInProgress && !mOnlyScrollingInThisMotion && isScrollingEnabled()) {
+        if (mIsExpanded && !mSwipingInProgress && !mOnlyScrollingInThisMotion
+                && isScrollingEnabled()) {
             if (isCancelOrUp) {
                 mExpandHelper.onlyObserveMovements(false);
             }
@@ -824,7 +824,8 @@
             }
         }
         boolean scrollerWantsIt = false;
-        if (!mSwipingInProgress && !mExpandingNotification && !mDisallowScrollingInThisMotion) {
+        if (mIsExpanded && !mSwipingInProgress && !mExpandingNotification
+                && !mDisallowScrollingInThisMotion) {
             scrollerWantsIt = onScrollTouch(ev);
         }
         boolean horizontalSwipeWantsIt = false;
@@ -1872,15 +1873,15 @@
             boolean onBottom = false;
             if (!mIsExpanded && !isHeadsUp) {
                 type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
-            } else if (mAddedHeadsUpChildren.contains(row) || (!row.isInShade() && !mIsExpanded)) {
-                if (!row.isInShade() || shouldHunAppearFromBottom(row)) {
+            } else if (mAddedHeadsUpChildren.contains(row) || (row.isPinned() && !mIsExpanded)) {
+                if (row.isPinned() || shouldHunAppearFromBottom(row)) {
                     // Our custom add animation
                     type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR;
                 } else {
                     // Normal add animation
                     type = AnimationEvent.ANIMATION_TYPE_ADD;
                 }
-                onBottom = row.isInShade();
+                onBottom = !row.isPinned();
             }
             AnimationEvent event = new AnimationEvent(row, type);
             event.headsUpFromBottom = onBottom;
@@ -2670,7 +2671,7 @@
         }
     }
 
-    public void performOnAnimationFinished(Runnable runnable) {
+    public void runAfterAnimationFinished(Runnable runnable) {
         mAnimationFinishedRunnables.add(runnable);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 2a49a4c..202063a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -311,7 +311,8 @@
                     StackViewState viewState = resultState.getViewStateForView(
                             nextChild);
                     // The child below the dragged one must be fully visible
-                    if (!isPinnedHeadsUpView(draggedView) || isPinnedHeadsUpView(nextChild)) {
+                    if (!NotificationStackScrollLayout.isPinnedHeadsUp(draggedView)
+                            || NotificationStackScrollLayout.isPinnedHeadsUp(nextChild)) {
                         viewState.alpha = 1;
                     }
                 }
@@ -324,14 +325,6 @@
         }
     }
 
-    private boolean isPinnedHeadsUpView(View view) {
-        if (view instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-            return row.isHeadsUp() && !row.isInShade();
-        }
-        return false;
-    }
-
     /**
      * Update the visible children on the state.
      */
@@ -380,7 +373,7 @@
     /**
      * Determine the positions for the views. This is the main part of the algorithm.
      *
-     *  @param resultState The result state to update if a change to the properties of a child occurs
+     * @param resultState The result state to update if a change to the properties of a child occurs
      * @param algorithmState The state in which the current pass of the algorithm is currently in
      * @param ambientState The current ambient state
      */
@@ -515,11 +508,12 @@
             }
             StackViewState childState = resultState.getViewStateForView(row);
             boolean isTopEntry = topHeadsUpEntry == row;
-            if (!row.isInShade()) {
+            if (row.isPinned()) {
                 childState.yTranslation = 0;
                 childState.height = row.getHeadsUpHeight();
                 if (!isTopEntry) {
-                    // Ensure that a headsUp is never below the topmost headsUp
+                    // Ensure that a headsUp doesn't vertically extend further than the heads-up at
+                    // the top most z-position
                     StackViewState topState = resultState.getViewStateForView(topHeadsUpEntry);
                     childState.height = row.getHeadsUpHeight();
                     childState.yTranslation = topState.yTranslation + topState.height
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index f5d94c8..b9466d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -21,11 +21,9 @@
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.ValueAnimator;
-import android.graphics.Path;
 import android.view.View;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
-import android.view.animation.PathInterpolator;
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -78,6 +76,7 @@
     private final Interpolator mFastOutSlowInInterpolator;
     private final Interpolator mHeadsUpAppearInterpolator;
     private final int mGoToFullShadeAppearingTranslation;
+    private final StackViewState mTmpState = new StackViewState();
     public NotificationStackScrollLayout mHostLayout;
     private ArrayList<NotificationStackScrollLayout.AnimationEvent> mNewEvents =
             new ArrayList<>();
@@ -95,7 +94,6 @@
     private ValueAnimator mTopOverScrollAnimator;
     private ValueAnimator mBottomOverScrollAnimator;
     private ExpandableNotificationRow mChildExpandingView;
-    private StackViewState mTmpState = new StackViewState();
     private int mHeadsUpAppearHeightBottom;
     private boolean mShadeExpanded;
 
@@ -106,25 +104,7 @@
         mGoToFullShadeAppearingTranslation =
                 hostLayout.getContext().getResources().getDimensionPixelSize(
                         R.dimen.go_to_full_shade_appearing_translation);
-        Path path = new Path();
-        path.moveTo(0, 0);
-        float x1 = 250f;
-        float x2 = 150f;
-        float x3 = 100f;
-        float y1 = 90f;
-        float y2 = 78f;
-        float y3 = 80f;
-        float xTot = (x1 + x2 + x3);
-        path.cubicTo(x1 * 0.9f / xTot, 0f,
-                x1 * 0.8f / xTot, y1 / y3,
-                x1 / xTot , y1 / y3);
-        path.cubicTo((x1 + x2 * 0.4f) / xTot, y1 / y3,
-                (x1 + x2 * 0.2f) / xTot, y2 / y3,
-                (x1 + x2) / xTot, y2 / y3);
-        path.cubicTo((x1 + x2 + x3 * 0.4f) / xTot, y2 / y3,
-                (x1 + x2 + x3 * 0.2f) / xTot, 1f,
-                1f, 1f);
-        mHeadsUpAppearInterpolator = new PathInterpolator(path);
+        mHeadsUpAppearInterpolator = new HeadsUpAppearInterpolator();
     }
 
     public boolean isRunning() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index dda40d3..a5684a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -121,7 +121,7 @@
     }
 
     @Override
-    public void escalateHeadsUp() {
+    public void maybeEscalateHeadsUp() {
     }
 
     @Override
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index abd2ca0..ef9d0c3 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -180,6 +180,11 @@
 34001 device_idle_step
 34002 device_idle_wake_from_idle (is_idle|1|5), (reason|3)
 
+# ---------------------------
+# DisplayManagerService.java
+# ---------------------------
+# Auto-brightness adjustments by the user.
+35000 auto_brightness_adj (old_adj|5),(old_lux|5),(old_brightness|5),(old_gamma|5),(new_adj|5),(new_lux|5),(new_brightness|5),(new_gamma|5)
 
 # ---------------------------
 # ConnectivityService.java
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 7172ab7..643ff5f 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -580,7 +580,9 @@
                 case H_FSTRIM: {
                     if (!isReady()) {
                         Slog.i(TAG, "fstrim requested, but no daemon connection yet; trying again");
-                        sendMessageDelayed(obtainMessage(H_FSTRIM), DateUtils.SECOND_IN_MILLIS);
+                        sendMessageDelayed(obtainMessage(H_FSTRIM, msg.obj),
+                                DateUtils.SECOND_IN_MILLIS);
+                        break;
                     }
 
                     Slog.i(TAG, "Running fstrim idle maintenance");
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 4ee6657..8c6e290 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -759,47 +759,50 @@
     }
 
     public void notifySignalStrengthForSubscriber(int subId, SignalStrength signalStrength) {
-        log("notifySignalStrengthForSubscriber: subId=" + subId
-                + " signalStrength=" + signalStrength);
         if (!checkNotifyPermission("notifySignalStrength()")) {
-            log("notifySignalStrengthForSubscriber: permission check failure");
             return;
         }
-        toStringLogSSC("notifySignalStrengthForSubscriber");
+        if (VDBG) {
+            log("notifySignalStrengthForSubscriber: subId=" + subId
+                + " signalStrength=" + signalStrength);
+            toStringLogSSC("notifySignalStrengthForSubscriber");
+        }
         synchronized (mRecords) {
             int phoneId = SubscriptionManager.getPhoneId(subId);
             if (validatePhoneId(phoneId)) {
-                log("notifySignalStrengthForSubscriber: valid phoneId=" + phoneId);
+                if (VDBG) log("notifySignalStrengthForSubscriber: valid phoneId=" + phoneId);
                 mSignalStrength[phoneId] = signalStrength;
                 for (Record r : mRecords) {
-                    log("notifySignalStrengthForSubscriber: r=" + r + " subId=" + subId
-                            + " phoneId=" + phoneId + " ss=" + signalStrength);
+                    if (VDBG) {
+                        log("notifySignalStrengthForSubscriber: r=" + r + " subId=" + subId
+                                + " phoneId=" + phoneId + " ss=" + signalStrength);
+                    }
                     if (r.matchPhoneStateListenerEvent(
                                 PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) &&
                             idMatch(r.subId, subId, phoneId)) {
                         try {
-                            log("notifySignalStrengthForSubscriber: callback.onSsS r=" + r
-                                    + " subId=" + subId + " phoneId=" + phoneId
-                                    + " ss=" + signalStrength);
+                            if (DBG) {
+                                log("notifySignalStrengthForSubscriber: callback.onSsS r=" + r
+                                        + " subId=" + subId + " phoneId=" + phoneId
+                                        + " ss=" + signalStrength);
+                            }
                             r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
                         } catch (RemoteException ex) {
-                            log("notifySignalStrengthForSubscriber: Exception while calling callback!!");
                             mRemoveList.add(r.binder);
                         }
-                    } else {
-                        log("notifySignalStrengthForSubscriber: no match for LISTEN_SIGNAL_STRENGTHS");
                     }
                     if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SIGNAL_STRENGTH) &&
                             idMatch(r.subId, subId, phoneId)){
                         try {
                             int gsmSignalStrength = signalStrength.getGsmSignalStrength();
                             int ss = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
-                            log("notifySignalStrengthForSubscriber: callback.onSS r=" + r
-                                    + " subId=" + subId + " phoneId=" + phoneId
-                                    + " gsmSS=" + gsmSignalStrength + " ss=" + ss);
+                            if (DBG) {
+                                log("notifySignalStrengthForSubscriber: callback.onSS r=" + r
+                                        + " subId=" + subId + " phoneId=" + phoneId
+                                        + " gsmSS=" + gsmSignalStrength + " ss=" + ss);
+                            }
                             r.callback.onSignalStrengthChanged(ss);
                         } catch (RemoteException ex) {
-                            log("notifySignalStrengthForSubscriber: Exception in deprecated LISTEN_SIGNAL_STRENGTH");
                             mRemoveList.add(r.binder);
                         }
                     }
@@ -807,7 +810,6 @@
             } else {
                 log("notifySignalStrengthForSubscriber: invalid phoneId=" + phoneId);
             }
-            log("notifySignalStrengthForSubscriber: done with all records");
             handleRemoveListLocked();
         }
         broadcastSignalStrengthChanged(signalStrength, subId);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 999e91b..ac2f5b0 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -54,6 +54,7 @@
 import android.database.DatabaseUtils;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteStatement;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
@@ -83,9 +84,12 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -109,7 +113,9 @@
 
     private static final int TIMEOUT_DELAY_MS = 1000 * 60;
     private static final String DATABASE_NAME = "accounts.db";
-    private static final int DATABASE_VERSION = 7;
+    private static final int DATABASE_VERSION = 8;
+
+    private static final int MAX_DEBUG_DB_SIZE = 64;
 
     private final Context mContext;
 
@@ -214,6 +220,9 @@
         private final HashMap<Account, AtomicReference<String>> previousNameCache =
                 new HashMap<Account, AtomicReference<String>>();
 
+        private int debugDbInsertionPoint = -1;
+        private SQLiteStatement statementForLogging;
+
         UserAccounts(Context context, int userId) {
             this.userId = userId;
             synchronized (cacheLock) {
@@ -320,6 +329,8 @@
         UserAccounts accounts = mUsers.get(userId);
         if (accounts == null) {
             accounts = new UserAccounts(mContext, userId);
+            initializeDebugDbSizeAndCompileSqlStatementForLogging(
+                    accounts.openHelper.getWritableDatabase(), accounts);
             mUsers.append(userId, accounts);
             purgeOldGrants(accounts);
             validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
@@ -407,6 +418,10 @@
                                 + accountType + " no longer has a registered authenticator");
                         db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null);
                         accountDeleted = true;
+
+                        logRecord(db, DebugDbHelper.ACTION_AUTHENTICATOR_REMOVE, TABLE_ACCOUNTS,
+                                accountId, accounts);
+
                         final Account account = new Account(accountName, accountType);
                         accounts.userDataCache.remove(account);
                         accounts.authTokenCache.remove(account);
@@ -666,9 +681,10 @@
 
         UserAccounts accounts = getUserAccountsForCaller();
         // fails if the account already exists
+        int uid = getCallingUid();
         long identityToken = clearCallingIdentity();
         try {
-            return addAccountInternal(accounts, account, password, extras, false);
+            return addAccountInternal(accounts, account, password, extras, false, uid);
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -811,7 +827,7 @@
     }
 
     private boolean addAccountInternal(UserAccounts accounts, Account account, String password,
-            Bundle extras, boolean restricted) {
+            Bundle extras, boolean restricted, int callingUid) {
         if (account == null) {
             return false;
         }
@@ -850,6 +866,10 @@
                     }
                 }
                 db.setTransactionSuccessful();
+
+                logRecord(db, DebugDbHelper.ACTION_ACCOUNT_ADD, TABLE_ACCOUNTS, accountId,
+                        accounts, callingUid);
+
                 insertAccountIntoCacheLocked(accounts, account);
             } finally {
                 db.endTransaction();
@@ -983,9 +1003,12 @@
         if (accountToRename == null) throw new IllegalArgumentException("account is null");
         checkAuthenticateAccountsPermission(accountToRename);
         UserAccounts accounts = getUserAccountsForCaller();
+
+        int callingUid = getCallingUid();
         long identityToken = clearCallingIdentity();
         try {
-            Account resultingAccount = renameAccountInternal(accounts, accountToRename, newName);
+            Account resultingAccount = renameAccountInternal(accounts, accountToRename, newName,
+                    callingUid);
             Bundle result = new Bundle();
             result.putString(AccountManager.KEY_ACCOUNT_NAME, resultingAccount.name);
             result.putString(AccountManager.KEY_ACCOUNT_TYPE, resultingAccount.type);
@@ -1000,7 +1023,7 @@
     }
 
     private Account renameAccountInternal(
-            UserAccounts accounts, Account accountToRename, String newName) {
+            UserAccounts accounts, Account accountToRename, String newName, int callingUid) {
         Account resultAccount = null;
         /*
          * Cancel existing notifications. Let authenticators
@@ -1038,6 +1061,8 @@
                     db.update(TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId);
                     db.setTransactionSuccessful();
                     isSuccessful = true;
+                    logRecord(db, DebugDbHelper.ACTION_ACCOUNT_RENAME, TABLE_ACCOUNTS, accountId,
+                            accounts);
                 }
             } finally {
                 db.endTransaction();
@@ -1131,6 +1156,8 @@
             }
         }
 
+        logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_REMOVE, TABLE_ACCOUNTS);
+
         try {
             new RemoveAccountSession(accounts, response, account, expectActivityLaunch).bind();
         } finally {
@@ -1188,6 +1215,8 @@
             }
         }
 
+        logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_REMOVE, TABLE_ACCOUNTS);
+
         try {
             new RemoveAccountSession(accounts, response, account, expectActivityLaunch).bind();
         } finally {
@@ -1210,6 +1239,9 @@
         if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) {
             return false;
         }
+
+        logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_REMOVE, TABLE_ACCOUNTS);
+
         long identityToken = clearCallingIdentity();
         try {
             return removeAccountInternal(accounts, account);
@@ -1275,21 +1307,25 @@
         int deleted;
         synchronized (accounts.cacheLock) {
             final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
+            final long accountId = getAccountIdLocked(db, account);
             deleted = db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE
                     + "=?",
                     new String[]{account.name, account.type});
             removeAccountFromCacheLocked(accounts, account);
             sendAccountsChangedBroadcast(accounts.userId);
+
+            logRecord(db, DebugDbHelper.ACTION_ACCOUNT_REMOVE, TABLE_ACCOUNTS, accountId, accounts);
         }
         if (accounts.userId == UserHandle.USER_OWNER) {
             // Owner's account was removed, remove from any users that are sharing
             // this account.
+            int callingUid = getCallingUid();
             long id = Binder.clearCallingIdentity();
             try {
                 List<UserInfo> users = mUserManager.getUsers(true);
                 for (UserInfo user : users) {
                     if (!user.isPrimary() && user.isRestricted()) {
-                        removeSharedAccountAsUser(account, user.id);
+                        removeSharedAccountAsUser(account, user.id, callingUid);
                     }
                 }
             } finally {
@@ -1441,15 +1477,17 @@
         if (account == null) throw new IllegalArgumentException("account is null");
         checkAuthenticateAccountsPermission(account);
         UserAccounts accounts = getUserAccountsForCaller();
+        int callingUid = getCallingUid();
         long identityToken = clearCallingIdentity();
         try {
-            setPasswordInternal(accounts, account, password);
+            setPasswordInternal(accounts, account, password, callingUid);
         } finally {
             restoreCallingIdentity(identityToken);
         }
     }
 
-    private void setPasswordInternal(UserAccounts accounts, Account account, String password) {
+    private void setPasswordInternal(UserAccounts accounts, Account account, String password,
+            int callingUid) {
         if (account == null) {
             return;
         }
@@ -1473,6 +1511,11 @@
                     db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId);
                     accounts.authTokenCache.remove(account);
                     db.setTransactionSuccessful();
+
+                    String action = (password == null || password.length() == 0) ?
+                            DebugDbHelper.ACTION_CLEAR_PASSWORD
+                            : DebugDbHelper.ACTION_SET_PASSWORD;
+                    logRecord(db, action, TABLE_ACCOUNTS, accountId, accounts, callingUid);
                 }
             } finally {
                 db.endTransaction();
@@ -1497,9 +1540,11 @@
         if (account == null) throw new IllegalArgumentException("account is null");
         checkManageAccountsPermission();
         UserAccounts accounts = getUserAccountsForCaller();
+
+        int callingUid = getCallingUid();
         long identityToken = clearCallingIdentity();
         try {
-            setPasswordInternal(accounts, account, null);
+            setPasswordInternal(accounts, account, null, callingUid);
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -1888,6 +1933,8 @@
         options.putInt(AccountManager.KEY_CALLER_UID, uid);
         options.putInt(AccountManager.KEY_CALLER_PID, pid);
 
+        logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_ADD, TABLE_ACCOUNTS);
+
         long identityToken = clearCallingIdentity();
         try {
             new Session(accounts, response, accountType, expectActivityLaunch,
@@ -1964,6 +2011,8 @@
         options.putInt(AccountManager.KEY_CALLER_UID, uid);
         options.putInt(AccountManager.KEY_CALLER_PID, pid);
 
+        logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_ADD, TABLE_ACCOUNTS);
+
         long identityToken = clearCallingIdentity();
         try {
             new Session(accounts, response, accountType, expectActivityLaunch,
@@ -2320,7 +2369,8 @@
     @Override
     public boolean addSharedAccountAsUser(Account account, int userId) {
         userId = handleIncomingUser(userId);
-        SQLiteDatabase db = getUserAccounts(userId).openHelper.getWritableDatabase();
+        UserAccounts accounts = getUserAccounts(userId);
+        SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
         ContentValues values = new ContentValues();
         values.put(ACCOUNTS_NAME, account.name);
         values.put(ACCOUNTS_TYPE, account.type);
@@ -2332,6 +2382,7 @@
                     + ", skipping the DB insert failed");
             return false;
         }
+        logRecord(db, DebugDbHelper.ACTION_ACCOUNT_ADD, TABLE_SHARED_ACCOUNTS, accountId, accounts);
         return true;
     }
 
@@ -2340,6 +2391,7 @@
         userId = handleIncomingUser(userId);
         UserAccounts accounts = getUserAccounts(userId);
         SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
+        long sharedTableAccountId = getAccountIdFromSharedTable(db, account);
         final ContentValues values = new ContentValues();
         values.put(ACCOUNTS_NAME, newName);
         values.put(ACCOUNTS_PREVIOUS_NAME, account.name);
@@ -2349,20 +2401,30 @@
                 ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
                 new String[] { account.name, account.type });
         if (r > 0) {
+            int callingUid = getCallingUid();
+            logRecord(db, DebugDbHelper.ACTION_ACCOUNT_RENAME, TABLE_SHARED_ACCOUNTS,
+                    sharedTableAccountId, accounts, callingUid);
             // Recursively rename the account.
-            renameAccountInternal(accounts, account, newName);
+            renameAccountInternal(accounts, account, newName, callingUid);
         }
         return r > 0;
     }
 
     @Override
     public boolean removeSharedAccountAsUser(Account account, int userId) {
+        return removeSharedAccountAsUser(account, userId, getCallingUid());
+    }
+
+    private boolean removeSharedAccountAsUser(Account account, int userId, int callingUid) {
         userId = handleIncomingUser(userId);
         UserAccounts accounts = getUserAccounts(userId);
         SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
+        long sharedTableAccountId = getAccountIdFromSharedTable(db, account);
         int r = db.delete(TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
                 new String[] {account.name, account.type});
         if (r > 0) {
+            logRecord(db, DebugDbHelper.ACTION_ACCOUNT_REMOVE, TABLE_SHARED_ACCOUNTS,
+                    sharedTableAccountId, accounts, callingUid);
             removeAccountInternal(accounts, account);
         }
         return r > 0;
@@ -2459,6 +2521,19 @@
         }
     }
 
+    private long getAccountIdFromSharedTable(SQLiteDatabase db, Account account) {
+        Cursor cursor = db.query(TABLE_SHARED_ACCOUNTS, new String[]{ACCOUNTS_ID},
+                "name=? AND type=?", new String[]{account.name, account.type}, null, null, null);
+        try {
+            if (cursor.moveToNext()) {
+                return cursor.getLong(0);
+            }
+            return -1;
+        } finally {
+            cursor.close();
+        }
+    }
+
     private long getAccountIdLocked(SQLiteDatabase db, Account account) {
         Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_ID},
                 "name=? AND type=?", new String[]{account.name, account.type}, null, null, null);
@@ -2904,6 +2979,130 @@
         return databaseFile.getPath();
     }
 
+    private static class DebugDbHelper{
+        private DebugDbHelper() {
+        }
+
+        private static String TABLE_DEBUG = "debug_table";
+
+        // Columns for the table
+        private static String ACTION_TYPE = "action_type";
+        private static String TIMESTAMP = "time";
+        private static String CALLER_UID = "caller_uid";
+        private static String TABLE_NAME = "table_name";
+        private static String KEY = "primary_key";
+
+        // These actions correspond to the occurrence of real actions. Since
+        // these are called by the authenticators, the uid associated will be
+        // of the authenticator.
+        private static String ACTION_SET_PASSWORD = "action_set_password";
+        private static String ACTION_CLEAR_PASSWORD = "action_clear_password";
+        private static String ACTION_ACCOUNT_ADD = "action_account_add";
+        private static String ACTION_ACCOUNT_REMOVE = "action_account_remove";
+        private static String ACTION_AUTHENTICATOR_REMOVE = "action_authenticator_remove";
+        private static String ACTION_ACCOUNT_RENAME = "action_account_rename";
+
+        // These actions don't necessarily correspond to any action on
+        // accountDb taking place. As an example, there might be a request for
+        // addingAccount, which might not lead to addition of account on grounds
+        // of bad authentication. We will still be logging it to keep track of
+        // who called.
+        private static String ACTION_CALLED_ACCOUNT_ADD = "action_called_account_add";
+        private static String ACTION_CALLED_ACCOUNT_REMOVE = "action_called_account_remove";
+        private static String ACTION_CALLED_ACCOUNT_RENAME = "action_called_account_rename";
+
+        private static SimpleDateFormat dateFromat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+        private static String UPDATE_WHERE_CLAUSE = KEY + "=?";
+
+        private static void createDebugTable(SQLiteDatabase db) {
+            db.execSQL("CREATE TABLE " + TABLE_DEBUG + " ( "
+                    + ACCOUNTS_ID + " INTEGER,"
+                    + ACTION_TYPE + " TEXT NOT NULL, "
+                    + TIMESTAMP + " DATETIME,"
+                    + CALLER_UID + " INTEGER NOT NULL,"
+                    + TABLE_NAME + " TEXT NOT NULL,"
+                    + KEY + " INTEGER PRIMARY KEY)");
+            db.execSQL("CREATE INDEX timestamp_index ON " + TABLE_DEBUG + " (" + TIMESTAMP + ")");
+        }
+    }
+
+    private void logRecord(UserAccounts accounts, String action, String tableName) {
+        SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
+        logRecord(db, action, tableName, -1, accounts);
+    }
+
+    /*
+     * This function receives an opened writable database.
+     */
+    private void logRecord(SQLiteDatabase db, String action, String tableName, long accountId,
+            UserAccounts userAccount) {
+        logRecord(db, action, tableName, accountId, userAccount, getCallingUid());
+    }
+
+    /*
+     * This function receives an opened writable database.
+     */
+    private void logRecord(SQLiteDatabase db, String action, String tableName, long accountId,
+            UserAccounts userAccount, int callingUid) {
+        SQLiteStatement logStatement = userAccount.statementForLogging;
+        logStatement.bindLong(1, accountId);
+        logStatement.bindString(2, action);
+        logStatement.bindString(3, DebugDbHelper.dateFromat.format(new Date()));
+        logStatement.bindLong(4, callingUid);
+        logStatement.bindString(5, tableName);
+        logStatement.bindLong(6, userAccount.debugDbInsertionPoint);
+        logStatement.execute();
+        logStatement.clearBindings();
+        userAccount.debugDbInsertionPoint = (userAccount.debugDbInsertionPoint + 1)
+                % MAX_DEBUG_DB_SIZE;
+    }
+
+    /*
+     * This should only be called once to compile the sql statement for logging
+     * and to find the insertion point.
+     */
+    private void initializeDebugDbSizeAndCompileSqlStatementForLogging(SQLiteDatabase db,
+            UserAccounts userAccount) {
+        // Initialize the count if not done earlier.
+        int size = (int) getDebugTableRowCount(db);
+        if (size >= MAX_DEBUG_DB_SIZE) {
+            // Table is full, and we need to find the point where to insert.
+            userAccount.debugDbInsertionPoint = (int) getDebugTableInsertionPoint(db);
+        } else {
+            userAccount.debugDbInsertionPoint = size;
+        }
+        compileSqlStatementForLogging(db, userAccount);
+    }
+
+    private void compileSqlStatementForLogging(SQLiteDatabase db, UserAccounts userAccount) {
+        String sql = "INSERT OR REPLACE INTO " + DebugDbHelper.TABLE_DEBUG
+                + " VALUES (?,?,?,?,?,?)";
+        userAccount.statementForLogging = db.compileStatement(sql);
+    }
+
+    private long getDebugTableRowCount(SQLiteDatabase db) {
+        String queryCountDebugDbRows = "SELECT COUNT(*) FROM " + DebugDbHelper.TABLE_DEBUG;
+        return DatabaseUtils.longForQuery(db, queryCountDebugDbRows, null);
+    }
+
+    /*
+     * Finds the row key where the next insertion should take place. This should
+     * be invoked only if the table has reached its full capacity.
+     */
+    private long getDebugTableInsertionPoint(SQLiteDatabase db) {
+        // This query finds the smallest timestamp value (and if 2 records have
+        // same timestamp, the choose the lower id).
+        String queryCountDebugDbRows = new StringBuilder()
+                .append("SELECT ").append(DebugDbHelper.KEY)
+                .append(" FROM ").append(DebugDbHelper.TABLE_DEBUG)
+                .append(" ORDER BY ")
+                .append(DebugDbHelper.TIMESTAMP).append(",").append(DebugDbHelper.KEY)
+                .append(" LIMIT 1")
+                .toString();
+        return DatabaseUtils.longForQuery(db, queryCountDebugDbRows, null);
+    }
+
     static class DatabaseHelper extends SQLiteOpenHelper {
 
         public DatabaseHelper(Context context, int userId) {
@@ -2949,6 +3148,8 @@
             createSharedAccountsTable(db);
 
             createAccountsDeletionTrigger(db);
+
+            DebugDbHelper.createDebugTable(db);
         }
 
         private void createSharedAccountsTable(SQLiteDatabase db) {
@@ -2968,6 +3169,10 @@
             db.execSQL("ALTER TABLE " + TABLE_ACCOUNTS + " ADD COLUMN " + ACCOUNTS_PREVIOUS_NAME);
         }
 
+        private void addDebugTable(SQLiteDatabase db) {
+            DebugDbHelper.createDebugTable(db);
+        }
+
         private void createAccountsDeletionTrigger(SQLiteDatabase db) {
             db.execSQL(""
                     + " CREATE TRIGGER " + TABLE_ACCOUNTS + "Delete DELETE ON " + TABLE_ACCOUNTS
@@ -3028,6 +3233,11 @@
                 oldVersion++;
             }
 
+            if (oldVersion == 7) {
+                addDebugTable(db);
+                oldVersion++;
+            }
+
             if (oldVersion != newVersion) {
                 Log.e(TAG, "failed to upgrade version " + oldVersion + " to version " + newVersion);
             }
@@ -3109,6 +3319,23 @@
                     fout.println("  " + account);
                 }
 
+                // Add debug information.
+                fout.println();
+                Cursor cursor = db.query(DebugDbHelper.TABLE_DEBUG, null,
+                        null, null, null, null, DebugDbHelper.TIMESTAMP);
+                fout.println("AccountId, Action_Type, timestamp, UID, TableName, Key");
+                fout.println("Accounts History");
+                try {
+                    while (cursor.moveToNext()) {
+                        // print type,count
+                        fout.println(cursor.getString(0) + "," + cursor.getString(1) + "," +
+                                cursor.getString(2) + "," + cursor.getString(3) + ","
+                                + cursor.getString(4) + "," + cursor.getString(5));
+                    }
+                } finally {
+                    cursor.close();
+                }
+
                 fout.println();
                 synchronized (mSessions) {
                     final long now = SystemClock.elapsedRealtime();
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 33f915f..62d70d2 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1331,6 +1331,9 @@
                             }
                         } catch(RemoteException e) {
                         }
+                        if (r.state == ActivityState.RESUMED) {
+                            noStackActivityResumed = false;
+                        }
                     } else {
                         // This activity is not currently visible, but is running.
                         // Tell it to become visible.
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 93d37f1..e15bca6 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -16,6 +16,7 @@
 
 package com.android.server.display;
 
+import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
 import com.android.server.twilight.TwilightListener;
 import com.android.server.twilight.TwilightManager;
@@ -31,13 +32,13 @@
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.text.format.DateUtils;
+import android.util.EventLog;
 import android.util.MathUtils;
 import android.util.Spline;
 import android.util.Slog;
 import android.util.TimeUtils;
 
 import java.io.PrintWriter;
-import java.util.Arrays;
 
 class AutomaticBrightnessController {
     private static final String TAG = "AutomaticBrightnessController";
@@ -87,7 +88,12 @@
     // well after dusk.
     private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2;
 
+    // Debounce for sampling user-initiated changes in display brightness to ensure
+    // the user is satisfied with the result before storing the sample.
+    private static final int BRIGHTNESS_ADJUSTMENT_SAMPLE_DEBOUNCE_MILLIS = 10000;
+
     private static final int MSG_UPDATE_AMBIENT_LUX = 1;
+    private static final int MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE = 2;
 
     // Callbacks for requesting updates to the the display's power state
     private final Callbacks mCallbacks;
@@ -179,6 +185,14 @@
     // Are we going to adjust brightness while dozing.
     private boolean mDozing;
 
+    // True if we are collecting a brightness adjustment sample, along with some data
+    // for the initial state of the sample.
+    private boolean mBrightnessAdjustmentSamplePending;
+    private float mBrightnessAdjustmentSampleOldAdjustment;
+    private float mBrightnessAdjustmentSampleOldLux;
+    private int mBrightnessAdjustmentSampleOldBrightness;
+    private float mBrightnessAdjustmentSampleOldGamma;
+
     public AutomaticBrightnessController(Callbacks callbacks, Looper looper,
             SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime,
             int brightnessMin, int brightnessMax, float dozeScaleFactor,
@@ -216,7 +230,8 @@
         return mScreenAutoBrightness;
     }
 
-    public void configure(boolean enable, float adjustment, boolean dozing) {
+    public void configure(boolean enable, float adjustment, boolean dozing,
+            boolean userInitiatedChange) {
         // While dozing, the application processor may be suspended which will prevent us from
         // receiving new information from the light sensor. On some devices, we may be able to
         // switch to a wake-up light sensor instead but for now we will simply disable the sensor
@@ -228,6 +243,9 @@
         if (changed) {
             updateAutoBrightness(false /*sendUpdate*/);
         }
+        if (enable && !dozing && userInitiatedChange) {
+            prepareBrightnessAdjustmentSample();
+        }
     }
 
     public void dump(PrintWriter pw) {
@@ -486,7 +504,7 @@
         }
 
         int newScreenAutoBrightness =
-            clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON));
+                clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON));
         if (mScreenAutoBrightness != newScreenAutoBrightness) {
             if (DEBUG) {
                 Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness="
@@ -507,6 +525,54 @@
                 mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
     }
 
+    private void prepareBrightnessAdjustmentSample() {
+        if (!mBrightnessAdjustmentSamplePending) {
+            mBrightnessAdjustmentSamplePending = true;
+            mBrightnessAdjustmentSampleOldAdjustment = mScreenAutoBrightnessAdjustment;
+            mBrightnessAdjustmentSampleOldLux = mAmbientLuxValid ? mAmbientLux : -1;
+            mBrightnessAdjustmentSampleOldBrightness = mScreenAutoBrightness;
+            mBrightnessAdjustmentSampleOldGamma = mLastScreenAutoBrightnessGamma;
+        } else {
+            mHandler.removeMessages(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE);
+        }
+
+        mHandler.sendEmptyMessageDelayed(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE,
+                BRIGHTNESS_ADJUSTMENT_SAMPLE_DEBOUNCE_MILLIS);
+    }
+
+    private void cancelBrightnessAdjustmentSample() {
+        if (mBrightnessAdjustmentSamplePending) {
+            mBrightnessAdjustmentSamplePending = false;
+            mHandler.removeMessages(MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE);
+        }
+    }
+
+    private void collectBrightnessAdjustmentSample() {
+        if (mBrightnessAdjustmentSamplePending) {
+            mBrightnessAdjustmentSamplePending = false;
+            if (mAmbientLuxValid && mScreenAutoBrightness >= 0) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Auto-brightness adjustment changed by user: "
+                            + "adj=" + mScreenAutoBrightnessAdjustment
+                            + ", lux=" + mAmbientLux
+                            + ", brightness=" + mScreenAutoBrightness
+                            + ", gamma=" + mLastScreenAutoBrightnessGamma
+                            + ", ring=" + mAmbientLightRingBuffer);
+                }
+
+                EventLog.writeEvent(EventLogTags.AUTO_BRIGHTNESS_ADJ,
+                        mBrightnessAdjustmentSampleOldAdjustment,
+                        mBrightnessAdjustmentSampleOldLux,
+                        mBrightnessAdjustmentSampleOldBrightness,
+                        mBrightnessAdjustmentSampleOldGamma,
+                        mScreenAutoBrightnessAdjustment,
+                        mAmbientLux,
+                        mScreenAutoBrightness,
+                        mLastScreenAutoBrightnessGamma);
+            }
+        }
+    }
+
     private static float getTwilightGamma(long now, long lastSunset, long nextSunrise) {
         if (lastSunset < 0 || nextSunrise < 0
                 || now < lastSunset || now > nextSunrise) {
@@ -537,6 +603,10 @@
                 case MSG_UPDATE_AMBIENT_LUX:
                     updateAmbientLux();
                     break;
+
+                case MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE:
+                    collectBrightnessAdjustmentSample();
+                    break;
             }
         }
     }
@@ -584,11 +654,7 @@
         private int mCount;
 
         public AmbientLightRingBuffer(long lightSensorRate) {
-            this((int) Math.ceil(AMBIENT_LIGHT_HORIZON * BUFFER_SLACK / lightSensorRate));
-        }
-
-        public AmbientLightRingBuffer(int initialCapacity) {
-            mCapacity = initialCapacity;
+            mCapacity = (int) Math.ceil(AMBIENT_LIGHT_HORIZON * BUFFER_SLACK / lightSensorRate);
             mRingLux = new float[mCapacity];
             mRingTime = new long[mCapacity];
         }
@@ -664,10 +730,6 @@
             return mCount;
         }
 
-        public boolean isEmpty() {
-            return mCount == 0;
-        }
-
         public void clear() {
             mStart = 0;
             mEnd = 0;
@@ -676,27 +738,20 @@
 
         @Override
         public String toString() {
-            final int length = mCapacity - mStart;
-            float[] lux = new float[mCount];
-            long[] time = new long[mCount];
-
-            if (mCount <= length) {
-                System.arraycopy(mRingLux, mStart, lux, 0, mCount);
-                System.arraycopy(mRingTime, mStart, time, 0, mCount);
-            } else {
-                System.arraycopy(mRingLux, mStart, lux, 0, length);
-                System.arraycopy(mRingLux, 0, lux, length, mCount - length);
-
-                System.arraycopy(mRingTime, mStart, time, 0, length);
-                System.arraycopy(mRingTime, 0, time, length, mCount - length);
+            StringBuffer buf = new StringBuffer();
+            buf.append('[');
+            for (int i = 0; i < mCount; i++) {
+                final long next = i + 1 < mCount ? getTime(i + 1) : SystemClock.uptimeMillis();
+                if (i != 0) {
+                    buf.append(", ");
+                }
+                buf.append(getLux(i));
+                buf.append(" / ");
+                buf.append(next - getTime(i));
+                buf.append("ms");
             }
-            return "AmbientLightRingBuffer{mCapacity=" + mCapacity
-                + ", mStart=" + mStart
-                + ", mEnd=" + mEnd
-                + ", mCount=" + mCount
-                + ", mRingLux=" + Arrays.toString(lux)
-                + ", mRingTime=" + Arrays.toString(time)
-                + "}";
+            buf.append(']');
+            return buf.toString();
         }
 
         private int offsetOf(int index) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index f74601e..35fbef6 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -70,12 +70,11 @@
  */
 final class DisplayPowerController implements AutomaticBrightnessController.Callbacks {
     private static final String TAG = "DisplayPowerController";
+    private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
 
     private static boolean DEBUG = false;
     private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
 
-    private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
-
     // If true, uses the color fade on animation.
     // We might want to turn this off if we cannot get a guarantee that the screen
     // actually turns on and starts showing new content after the call to set the
@@ -599,8 +598,11 @@
             autoBrightnessEnabled = mPowerRequest.useAutoBrightness
                     && (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
                     && brightness < 0;
+            final boolean userInitiatedChange = autoBrightnessAdjustmentChanged
+                    && mPowerRequest.brightnessSetByUser;
             mAutomaticBrightnessController.configure(autoBrightnessEnabled,
-                    mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON);
+                    mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,
+                    userInitiatedChange);
         }
 
         // Apply brightness boost.
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 53ceb2e..b066d6b 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -68,7 +68,7 @@
     private static final int defaultMaxActiveJobsPerService =
             ActivityManager.isLowRamDeviceStatic() ? 1 : 3;
     /** Amount of time a job is allowed to execute for before being considered timed-out. */
-    private static final long EXECUTING_TIMESLICE_MILLIS = 60 * 1000;
+    private static final long EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000;
     /** Amount of time the JobScheduler will wait for a response from an app for a message. */
     private static final long OP_TIMEOUT_MILLIS = 8 * 1000;
 
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index e106a4a..c9f5bdf 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -112,6 +112,7 @@
                 + " / " + idDebugString(baseContext, sbn.getPackageName(), notification.icon));
         pw.println(prefix + "  pri=" + notification.priority + " score=" + sbn.getScore());
         pw.println(prefix + "  key=" + sbn.getKey());
+        pw.println(prefix + "  seen=" + mIsSeen);
         pw.println(prefix + "  groupKey=" + getGroupKey());
         pw.println(prefix + "  contentIntent=" + notification.contentIntent);
         pw.println(prefix + "  deleteIntent=" + notification.deleteIntent);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f087c33..6c18e25 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -49,6 +49,7 @@
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+import static android.content.pm.PackageManager.MATCH_ALL;
 import static android.content.pm.PackageManager.MOVE_FAILED_DOESNT_EXIST;
 import static android.content.pm.PackageManager.MOVE_FAILED_INTERNAL_ERROR;
 import static android.content.pm.PackageManager.MOVE_FAILED_OPERATION_PENDING;
@@ -2274,6 +2275,13 @@
                 }
                 continue;
             }
+            if (!pkg.isSystemApp()) {
+                if (logging) {
+                    Slog.d(TAG, "No priming domain verifications for a non system package : " +
+                            packageName);
+                }
+                continue;
+            }
             for (PackageParser.Activity a : pkg.activities) {
                 for (ActivityIntentInfo filter : a.intents) {
                     if (hasValidDomains(filter, false)) {
@@ -2281,7 +2289,7 @@
                     }
                 }
             }
-            if (allHosts.size() > 0) {
+            if (allHosts.size() == 0) {
                 allHosts.add("*");
             }
             IntentFilterVerificationInfo ivi =
@@ -3939,7 +3947,7 @@
                 }
                 result = filterIfNotPrimaryUser(result, userId);
                 if (result.size() > 1 && hasWebURI(intent)) {
-                    return filterCandidatesWithDomainPreferedActivitiesLPr(result);
+                    return filterCandidatesWithDomainPreferedActivitiesLPr(flags, result);
                 }
                 return result;
             }
@@ -3984,7 +3992,7 @@
     }
 
     private List<ResolveInfo> filterCandidatesWithDomainPreferedActivitiesLPr(
-            List<ResolveInfo> candidates) {
+            int flags, List<ResolveInfo> candidates) {
         if (DEBUG_PREFERRED) {
             Slog.v("TAG", "Filtering results with prefered activities. Candidates count: " +
                     candidates.size());
@@ -4004,6 +4012,11 @@
                 String packageName = info.activityInfo.packageName;
                 PackageSetting ps = mSettings.mPackages.get(packageName);
                 if (ps != null) {
+                    // Add to the special match all list (Browser use case)
+                    if (info.handleAllWebDataURI) {
+                        matchAllList.add(info);
+                        continue;
+                    }
                     // Try to get the status from User settings first
                     int status = getDomainVerificationStatusLPr(ps, userId);
                     if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) {
@@ -4013,10 +4026,6 @@
                     } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) {
                         undefinedList.add(info);
                     }
-                    // Add to the special match all list (Browser use case)
-                    if (info.handleAllWebDataURI) {
-                        matchAllList.add(info);
-                    }
                 }
             }
             // If there is nothing selected, add all candidates and remove the ones that the User
@@ -4031,7 +4040,30 @@
             result.removeAll(matchAllList);
             if (result.size() == 0) {
                 result.addAll(undefinedList);
-                result.addAll(matchAllList);
+                if ((flags & MATCH_ALL) != 0) {
+                    result.addAll(matchAllList);
+                } else {
+                    // Try to add the Default Browser if we can
+                    final String defaultBrowserPackageName = getDefaultBrowserPackageName(
+                            UserHandle.myUserId());
+                    if (!TextUtils.isEmpty(defaultBrowserPackageName)) {
+                        boolean defaultBrowserFound = false;
+                        final int browserCount = matchAllList.size();
+                        for (int n=0; n<browserCount; n++) {
+                            ResolveInfo browser = matchAllList.get(n);
+                            if (browser.activityInfo.packageName.equals(defaultBrowserPackageName)) {
+                                result.add(browser);
+                                defaultBrowserFound = true;
+                                break;
+                            }
+                        }
+                        if (!defaultBrowserFound) {
+                            result.addAll(matchAllList);
+                        }
+                    } else {
+                        result.addAll(matchAllList);
+                    }
+                }
             }
         }
         if (DEBUG_PREFERRED) {
@@ -11331,10 +11363,16 @@
                                 verifierUid, userId, verificationId, filter, packageName);
                         count++;
                     } else if (!needsFilterVerification) {
-                        Slog.d(TAG, "No verification needed for IntentFilter:"
-                                + filter.toString());
+                        Slog.d(TAG, "No verification needed for IntentFilter:" + filter.toString());
                         if (hasValidDomains(filter)) {
-                            allHosts.addAll(filter.getHostsList());
+                            ArrayList<String> hosts = filter.getHostsList();
+                            if (hosts.size() > 0) {
+                                allHosts.addAll(hosts);
+                            } else {
+                                if (allHosts.isEmpty()) {
+                                    allHosts.add("*");
+                                }
+                            }
                         }
                     } else {
                         Slog.d(TAG, "Verification already done for IntentFilter:"
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index 926090e..01c110f 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -41,11 +41,13 @@
     private volatile boolean mSimSecure;
     private volatile boolean mInputRestricted;
 
+    private int mCurrentUserId;
+
     private final LockPatternUtils mLockPatternUtils;
 
     public KeyguardStateMonitor(Context context, IKeyguardService service) {
         mLockPatternUtils = new LockPatternUtils(context);
-        mLockPatternUtils.setCurrentUser(ActivityManager.getCurrentUser());
+        mCurrentUserId = ActivityManager.getCurrentUser();
         try {
             service.addStateMonitorCallback(this);
         } catch (RemoteException e) {
@@ -58,7 +60,7 @@
     }
 
     public boolean isSecure() {
-        return mLockPatternUtils.isSecure() || mSimSecure;
+        return mLockPatternUtils.isSecure(getCurrentUser()) || mSimSecure;
     }
 
     public boolean isInputRestricted() {
@@ -75,8 +77,12 @@
         mSimSecure = simSecure;
     }
 
-    public void setCurrentUser(int userId) {
-        mLockPatternUtils.setCurrentUser(userId);
+    public synchronized void setCurrentUser(int userId) {
+        mCurrentUserId = userId;
+    }
+
+    private synchronized int getCurrentUser() {
+        return mCurrentUserId;
     }
 
     @Override // Binder interface
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 6c8959c..f790f75 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -1819,6 +1819,7 @@
             mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
 
             // Determine appropriate screen brightness and auto-brightness adjustments.
+            boolean brightnessSetByUser = true;
             int screenBrightness = mScreenBrightnessSettingDefault;
             float screenAutoBrightnessAdjustment = 0.0f;
             boolean autoBrightness = (mScreenBrightnessModeSetting ==
@@ -1826,6 +1827,7 @@
             if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
                 screenBrightness = mScreenBrightnessOverrideFromWindowManager;
                 autoBrightness = false;
+                brightnessSetByUser = false;
             } else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) {
                 screenBrightness = mTemporaryScreenBrightnessSettingOverride;
             } else if (isValidBrightness(mScreenBrightnessSetting)) {
@@ -1851,6 +1853,7 @@
             mDisplayPowerRequest.screenBrightness = screenBrightness;
             mDisplayPowerRequest.screenAutoBrightnessAdjustment =
                     screenAutoBrightnessAdjustment;
+            mDisplayPowerRequest.brightnessSetByUser = brightnessSetByUser;
             mDisplayPowerRequest.useAutoBrightness = autoBrightness;
             mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
             mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
diff --git a/services/core/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java
index e226e3d..ba3ce36 100644
--- a/services/core/java/com/android/server/wm/Watermark.java
+++ b/services/core/java/com/android/server/wm/Watermark.java
@@ -84,7 +84,7 @@
         int fontSize = WindowManagerService.getPropertyInt(tokens, 1,
                 TypedValue.COMPLEX_UNIT_DIP, 20, dm);
 
-        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mTextPaint = new Paint();
         mTextPaint.setTextSize(fontSize);
         mTextPaint.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD));
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index c5bdbb0..d4b3dab 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2345,7 +2345,6 @@
 
         boolean reportNewConfig = false;
         WindowState attachedWindow = null;
-        WindowState win = null;
         long origId;
         final int type = attrs.type;
 
@@ -2482,7 +2481,7 @@
                 addToken = true;
             }
 
-            win = new WindowState(this, session, client, token,
+            WindowState win = new WindowState(this, session, client, token,
                     attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
             if (win.mDeathRecipient == null) {
                 // Client has apparently died, so there is no reason to
@@ -9941,18 +9940,20 @@
 
                     final WindowStateAnimator winAnimator = w.mWinAnimator;
 
-                    // If the window has moved due to its containing
-                    // content frame changing, then we'd like to animate
-                    // it.
-                    if (w.mHasSurface && w.shouldAnimateMove()) {
-                        // Frame has moved, containing content frame
-                        // has also moved, and we're not currently animating...
-                        // let's do something.
-                        Animation a = AnimationUtils.loadAnimation(mContext,
-                                com.android.internal.R.anim.window_move_from_decor);
-                        winAnimator.setAnimation(a);
-                        winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
-                        winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
+                    // If the window has moved due to its containing content frame changing, then
+                    // notify the listeners and optionally animate it.
+                    if (w.hasMoved()) {
+                        // Frame has moved, containing content frame has also moved, and we're not
+                        // currently animating... let's do something.
+                        final int left = w.mFrame.left;
+                        final int top = w.mFrame.top;
+                        if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0) {
+                            Animation a = AnimationUtils.loadAnimation(mContext,
+                                    com.android.internal.R.anim.window_move_from_decor);
+                            winAnimator.setAnimation(a);
+                            winAnimator.mAnimDw = w.mLastFrame.left - left;
+                            winAnimator.mAnimDh = w.mLastFrame.top - top;
+                        }
 
                         //TODO (multidisplay): Accessibility supported only for the default display.
                         if (mAccessibilityController != null
@@ -9961,7 +9962,7 @@
                         }
 
                         try {
-                            w.mClient.moved(w.mFrame.left, w.mFrame.top);
+                            w.mClient.moved(left, top);
                         } catch (RemoteException e) {
                         }
                     }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index ec70879..ad25462 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -20,7 +20,6 @@
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -1081,16 +1080,14 @@
     }
 
     /**
-     * Return whether this window is wanting to have a translation
-     * animation applied to it for an in-progress move.  (Only makes
+     * Return whether this window has moved. (Only makes
      * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
      */
-    boolean shouldAnimateMove() {
-        return mContentChanged && !mExiting && !mWinAnimator.mLastHidden && mService.okToDisplay()
-                && (mFrame.top != mLastFrame.top
+    boolean hasMoved() {
+        return mHasSurface && mContentChanged && !mExiting && !mWinAnimator.mLastHidden
+                && mService.okToDisplay() && (mFrame.top != mLastFrame.top
                         || mFrame.left != mLastFrame.left)
-                && (mAttrs.privateFlags&PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
-                && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove());
+                && (mAttachedWindow == null || !mAttachedWindow.hasMoved());
     }
 
     boolean isFullscreen(int screenWidth, int screenHeight) {
@@ -1709,7 +1706,7 @@
                     pw.println(mWallpaperDisplayOffsetY);
         }
         if (mDrawLock != null) {
-            pw.println("mDrawLock=" + mDrawLock);
+            pw.print(prefix); pw.println("mDrawLock=" + mDrawLock);
         }
     }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 31d7f74..1d00de9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -182,6 +182,7 @@
     private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
     private static final String ATTR_SETUP_COMPLETE = "setup-complete";
     private static final String ATTR_PREFERRED_SETUP_ACTIVITY = "setup-activity";
+    private static final String ATTR_PERMISSION_POLICY = "permission-policy";
 
     private static final String ATTR_DELEGATED_CERT_INSTALLER = "delegated-cert-installer";
 
@@ -300,6 +301,7 @@
         int mPasswordOwner = -1;
         long mLastMaximumTimeToLock = -1;
         boolean mUserSetupComplete = false;
+        int mPermissionPolicy;
 
         final HashMap<ComponentName, ActiveAdmin> mAdminMap = new HashMap<>();
         final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>();
@@ -1409,6 +1411,10 @@
                 out.attribute(null, ATTR_SETUP_COMPLETE,
                         Boolean.toString(true));
             }
+            if (policy.mPermissionPolicy != DevicePolicyManager.PERMISSION_POLICY_PROMPT) {
+                out.attribute(null, ATTR_PERMISSION_POLICY,
+                        Integer.toString(policy.mPermissionPolicy));
+            }
             if (policy.mDelegatedCertInstallerPackage != null) {
                 out.attribute(null, ATTR_DELEGATED_CERT_INSTALLER,
                         policy.mDelegatedCertInstallerPackage);
@@ -1537,6 +1543,10 @@
             if (userSetupComplete != null && Boolean.toString(true).equals(userSetupComplete)) {
                 policy.mUserSetupComplete = true;
             }
+            String permissionPolicy = parser.getAttributeValue(null, ATTR_PERMISSION_POLICY);
+            if (!TextUtils.isEmpty(permissionPolicy)) {
+                policy.mPermissionPolicy = Integer.parseInt(permissionPolicy);
+            }
             policy.mDelegatedCertInstallerPackage = parser.getAttributeValue(null,
                     ATTR_DELEGATED_CERT_INSTALLER);
             String preferredSetupActivity =
@@ -4253,14 +4263,22 @@
             return;
         }
         UserHandle callingUser = Binder.getCallingUserHandle();
+        int userId = callingUser.getIdentifier();
         // Check if this is the profile owner who is calling
         getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
         synchronized (this) {
+            // Reset some of the profile-owner policies
+            DevicePolicyData policy = getUserData(userId);
+            policy.mPermissionPolicy = DevicePolicyManager.PERMISSION_POLICY_PROMPT;
+            policy.mDelegatedCertInstallerPackage = null;
+            policy.mStatusBarEnabledState = true;
+            saveSettingsLocked(userId);
+
             long ident = Binder.clearCallingIdentity();
             try {
                 clearUserRestrictions(callingUser);
                 if (mDeviceOwner != null) {
-                    mDeviceOwner.removeProfileOwner(callingUser.getIdentifier());
+                    mDeviceOwner.removeProfileOwner(userId);
                     mDeviceOwner.writeOwnerFile();
                 }
             } finally {
@@ -6261,4 +6279,48 @@
             }
         }
     }
+
+    @Override
+    public void setPermissionPolicy(ComponentName admin, int policy) throws RemoteException {
+        int userId = UserHandle.getCallingUserId();
+        synchronized (this) {
+            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            DevicePolicyData userPolicy = getUserData(userId);
+            if (userPolicy.mPermissionPolicy != policy) {
+                userPolicy.mPermissionPolicy = policy;
+                saveSettingsLocked(userId);
+            }
+        }
+    }
+
+    @Override
+    public int getPermissionPolicy(ComponentName admin) throws RemoteException {
+        int userId = UserHandle.getCallingUserId();
+        synchronized (this) {
+            DevicePolicyData userPolicy = getUserData(userId);
+            return userPolicy.mPermissionPolicy;
+        }
+    }
+
+    @Override
+    public boolean setPermissionGranted(ComponentName admin, String packageName,
+            String permission, boolean granted) throws RemoteException {
+        UserHandle user = Binder.getCallingUserHandle();
+        synchronized (this) {
+            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            long ident = Binder.clearCallingIdentity();
+            try {
+                if (granted) {
+                    mContext.getPackageManager().grantPermission(packageName, permission, user);
+                } else {
+                    mContext.getPackageManager().revokePermission(packageName, permission, user);
+                }
+                return true;
+            } catch (SecurityException se) {
+                return false;
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
index fbdb20b..2557974 100644
--- a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
@@ -24,7 +24,6 @@
 import android.util.LongSparseArray;
 import com.android.internal.util.ArrayUtils;
 
-import java.lang.reflect.Field;
 import java.io.File;
 import java.io.IOException;
 import java.security.cert.CertificateException;
@@ -43,53 +42,6 @@
                 "", 1, 0, 0);
     }
 
-    public PublicKey getPubKey(long pkId) throws NoSuchFieldException, IllegalAccessException {
-        Field pkField = mKsms.getClass().getDeclaredField("mPublicKeys");
-        pkField.setAccessible(true);
-        LongSparseArray<KeySetManagerService.PublicKeyHandle> mPublicKeys =
-            (LongSparseArray<KeySetManagerService.PublicKeyHandle>) pkField.get(mKsms);
-        KeySetManagerService.PublicKeyHandle pkh = mPublicKeys.get(pkId);
-        if (pkh == null) {
-            return null;
-        } else {
-            return pkh.getKey();
-        }
-    }
-
-    public int getPubKeyRefCount(long pkId) throws NoSuchFieldException, IllegalAccessException {
-        Field pkField = mKsms.getClass().getDeclaredField("mPublicKeys");
-        pkField.setAccessible(true);
-        LongSparseArray<KeySetManagerService.PublicKeyHandle> mPublicKeys =
-            (LongSparseArray<KeySetManagerService.PublicKeyHandle>) pkField.get(mKsms);
-        KeySetManagerService.PublicKeyHandle pkh = mPublicKeys.get(pkId);
-        if (pkh == null) {
-            return 0;
-        } else {
-            return pkh.getRefCountLPr();
-        }
-    }
-
-    public int getKeySetRefCount(long keysetId) throws NoSuchFieldException, IllegalAccessException {
-        Field ksField = mKsms.getClass().getDeclaredField("mKeySets");
-        ksField.setAccessible(true);
-        LongSparseArray<KeySetHandle> mKeySets =
-            (LongSparseArray<KeySetHandle>) ksField.get(mKsms);
-        KeySetHandle ksh = mKeySets.get(keysetId);
-        if (ksh == null) {
-            return 0;
-        } else {
-            return ksh.getRefCountLPr();
-        }
-    }
-
-    public LongSparseArray<ArraySet<Long>> getKeySetMapping()
-            throws NoSuchFieldException, IllegalAccessException {
-        Field ksField = mKsms.getClass().getDeclaredField("mKeySetMapping");
-        ksField.setAccessible(true);
-        return (LongSparseArray<ArraySet<Long>>) ksField.get(mKsms);
-    }
-
-
     @Override
     public void setUp() throws Exception {
         super.setUp();
@@ -168,10 +120,10 @@
         signingKeys.add(keyA);
         mKsms.addSigningKeySetToPackageLPw(ps.name, signingKeys);
 
-        assertEquals(1, getKeySetRefCount(1));
-        assertEquals(1, getPubKeyRefCount(1));
-        assertEquals(keyA, getPubKey(1));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(1, ksMapping.size());
         ArraySet<Long> mapping = ksMapping.get(1);
         assertEquals(1, mapping.size());
@@ -198,10 +150,10 @@
         /* add again, to represent upgrade of package */
         mKsms.addSigningKeySetToPackageLPw(ps.name, signingKeys);
 
-        assertEquals(1, getKeySetRefCount(1));
-        assertEquals(1, getPubKeyRefCount(1));
-        assertEquals(keyA, getPubKey(1));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(1, ksMapping.size());
         ArraySet<Long> mapping = ksMapping.get(1);
         assertEquals(1, mapping.size());
@@ -231,12 +183,12 @@
         signingKeys.add(keyB);
         mKsms.addSigningKeySetToPackageLPw(ps.name, signingKeys);
 
-        assertEquals(0, getKeySetRefCount(1));
-        assertEquals(1, getKeySetRefCount(2));
-        assertEquals(0, getPubKeyRefCount(1));
-        assertEquals(1, getPubKeyRefCount(2));
-        assertEquals(keyB, getPubKey(2));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
+        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
+        assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(1, ksMapping.size());
         ArraySet<Long> mapping = ksMapping.get(2);
         assertEquals(1, mapping.size());
@@ -269,13 +221,13 @@
         signingKeys.add(keyB);
         mKsms.addSigningKeySetToPackageLPw(ps1.name, signingKeys);
 
-        assertEquals(1, getKeySetRefCount(1));
-        assertEquals(1, getKeySetRefCount(2));
-        assertEquals(1, getPubKeyRefCount(1));
-        assertEquals(1, getPubKeyRefCount(2));
-        assertEquals(keyA, getPubKey(1));
-        assertEquals(keyB, getPubKey(2));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
+        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
+        assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(2, ksMapping.size());
         ArraySet<Long> mapping = ksMapping.get(1);
         assertEquals(1, mapping.size());
@@ -312,10 +264,10 @@
         mKsms.addSigningKeySetToPackageLPw(ps2.name, signingKeys2);
 
         /* verify first is unchanged */
-        assertEquals(1, getKeySetRefCount(1));
-        assertEquals(1, getPubKeyRefCount(1));
-        assertEquals(keyA, getPubKey(1));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(2, ksMapping.size());
         ArraySet<Long> mapping = ksMapping.get(1);
         assertEquals(1, mapping.size());
@@ -323,9 +275,9 @@
         assertEquals(1, ps1.keySetData.getProperSigningKeySet());
 
         /* verify second */
-        assertEquals(1, getKeySetRefCount(2));
-        assertEquals(1, getPubKeyRefCount(2));
-        assertEquals(keyB, getPubKey(2));
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
+        assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
         mapping = ksMapping.get(2);
         assertEquals(1, mapping.size());
         assertTrue(mapping.contains(new  Long(2)));
@@ -353,10 +305,10 @@
         /* add again for second package */
         mKsms.addSigningKeySetToPackageLPw(ps2.name, signingKeys);
 
-        assertEquals(2, getKeySetRefCount(1));
-        assertEquals(1, getPubKeyRefCount(1));
-        assertEquals(keyA, getPubKey(1));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(2, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(1, ksMapping.size());
         ArraySet<Long> mapping = ksMapping.get(1);
         assertEquals(1, mapping.size());
@@ -388,13 +340,13 @@
         signingKeys.add(keyB);
         mKsms.addSigningKeySetToPackageLPw(ps2.name, signingKeys);
 
-        assertEquals(1, getKeySetRefCount(1));
-        assertEquals(1, getKeySetRefCount(2));
-        assertEquals(2, getPubKeyRefCount(1));
-        assertEquals(1, getPubKeyRefCount(2));
-        assertEquals(keyA, getPubKey(1));
-        assertEquals(keyB, getPubKey(2));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
+        assertEquals(2, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
+        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
+        assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(2, ksMapping.size());
         ArraySet<Long> mapping = ksMapping.get(1);
         assertEquals(1, mapping.size());
@@ -429,16 +381,17 @@
         signingKeys.add(keyB);
         mKsms.addSigningKeySetToPackageLPw(ps.name, signingKeys);
 
-        assertEquals(0, getKeySetRefCount(1));
-        assertEquals(1, getKeySetRefCount(2));
-        assertEquals(0, getPubKeyRefCount(1));
-        assertEquals(1, getPubKeyRefCount(2));
-        assertEquals(1, getPubKeyRefCount(3));
+        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
+        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 3));
 
         /* the pub key is removed w/prev keyset and may be either 2 or 3 */
-        assertTrue(keyA.equals(getPubKey(2)) && keyB.equals(getPubKey(3))
-                   || keyA.equals(getPubKey(3)) && keyB.equals(getPubKey(2)));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertTrue(keyA.equals(KeySetUtils.getPubKey(mKsms, 2)) || keyA.equals(KeySetUtils.getPubKey(mKsms, 3)));
+        assertTrue(keyB.equals(KeySetUtils.getPubKey(mKsms, 2)) || keyB.equals(KeySetUtils.getPubKey(mKsms, 3)));
+        assertFalse(KeySetUtils.getPubKey(mKsms, 2).equals(KeySetUtils.getPubKey(mKsms, 3)));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(1, ksMapping.size());
         ArraySet<Long> mapping = ksMapping.get(2);
         assertEquals(2, mapping.size());
@@ -462,10 +415,10 @@
         definedKS.put("aliasA", keys);
         mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS);
 
-        assertEquals(1, getKeySetRefCount(1));
-        assertEquals(1, getPubKeyRefCount(1));
-        assertEquals(keyA, getPubKey(1));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(1, ksMapping.size());
         ArraySet<Long> mapping = ksMapping.get(1);
         assertEquals(1, mapping.size());
@@ -490,10 +443,10 @@
         definedKS.put("aliasA2", keys);
         mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS);
 
-        assertEquals(2, getKeySetRefCount(1));
-        assertEquals(1, getPubKeyRefCount(1));
-        assertEquals(keyA, getPubKey(1));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(2, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 1));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(1, ksMapping.size());
         ArraySet<Long> mapping = ksMapping.get(1);
         assertEquals(1, mapping.size());
@@ -527,12 +480,12 @@
         definedKS.put("aliasB", keys);
         mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS);
 
-        assertEquals(0, getKeySetRefCount(1));
-        assertEquals(0, getPubKeyRefCount(1));
-        assertEquals(1, getKeySetRefCount(2));
-        assertEquals(1, getPubKeyRefCount(2));
-        assertEquals(keyB, getPubKey(2));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
+        assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(1, ksMapping.size());
         ArraySet<Long> mapping = ksMapping.get(2);
         assertEquals(1, mapping.size());
@@ -566,12 +519,12 @@
         definedKS.put("aliasA", keys);
         mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS);
 
-        assertEquals(0, getKeySetRefCount(1));
-        assertEquals(0, getPubKeyRefCount(1));
-        assertEquals(1, getKeySetRefCount(2));
-        assertEquals(1, getPubKeyRefCount(2));
-        assertEquals(keyB, getPubKey(2));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
+        assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(1, ksMapping.size());
         ArraySet<Long> mapping = ksMapping.get(2);
         assertEquals(1, mapping.size());
@@ -608,10 +561,10 @@
         definedKS.put("aliasC", keys1);
         mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS);
 
-        assertEquals(1, getKeySetRefCount(3));
-        assertEquals(1, getPubKeyRefCount(3));
-        assertEquals(keyC, getPubKey(3));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 3));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 3));
+        assertEquals(keyC, KeySetUtils.getPubKey(mKsms, 3));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(2, ksMapping.size());
         ArraySet<Long> mapping = ksMapping.get(3);
         assertEquals(1, mapping.size());
@@ -619,13 +572,13 @@
         assertEquals(new Long(3), ps.keySetData.getAliases().get("aliasC"));
 
         /* either keyset w/keyA or w/keyB was added first, address both cases */
-        if (1 == getKeySetRefCount(1)) {
+        if (1 == KeySetUtils.getKeySetRefCount(mKsms, 1)) {
 
             /* keyB was added first and should have keyset 1 and pub-key 1 */
-            assertEquals(1, getPubKeyRefCount(1));
-            assertEquals(0, getKeySetRefCount(2));
-            assertEquals(0, getPubKeyRefCount(2));
-            assertEquals(keyB, getPubKey(1));
+            assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+            assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 2));
+            assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 2));
+            assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 1));
             mapping = ksMapping.get(1);
             assertEquals(1, mapping.size());
             assertTrue(mapping.contains(new Long(1)));
@@ -633,11 +586,11 @@
         } else {
 
             /* keyA was added first and keyB has id 2 */
-            assertEquals(1, getKeySetRefCount(2));
-            assertEquals(1, getPubKeyRefCount(2));
-            assertEquals(0, getKeySetRefCount(1));
-            assertEquals(0, getPubKeyRefCount(1));
-            assertEquals(keyB, getPubKey(2));
+            assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 2));
+            assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 2));
+            assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
+            assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+            assertEquals(keyB, KeySetUtils.getPubKey(mKsms, 2));
             mapping = ksMapping.get(2);
             assertEquals(1, mapping.size());
             assertTrue(mapping.contains(new Long(2)));
@@ -674,14 +627,14 @@
         definedKS.put("aliasA", keys1);
         mKsms.addDefinedKeySetsToPackageLPw(ps.name, definedKS);
 
-        assertEquals(0, getKeySetRefCount(1));
-        assertEquals(0, getKeySetRefCount(2));
-        assertEquals(1, getKeySetRefCount(3));
-        assertEquals(0, getPubKeyRefCount(1));
-        assertEquals(0, getPubKeyRefCount(2));
-        assertEquals(1, getPubKeyRefCount(3));
-        assertEquals(keyA, getPubKey(3));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 2));
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 3));
+        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 2));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 3));
+        assertEquals(keyA, KeySetUtils.getPubKey(mKsms, 3));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(1, ksMapping.size());
         ArraySet<Long> mapping = ksMapping.get(3);
         assertEquals(1, mapping.size());
@@ -780,9 +733,9 @@
 
         /* remove its references */
         mKsms.removeAppKeySetDataLPw(ps.name);
-        assertEquals(0, getKeySetRefCount(1));
-        assertEquals(0, getPubKeyRefCount(1));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(0, ksMapping.size());
         assertEquals(PackageKeySetData.KEYSET_UNASSIGNED, ps.keySetData.getProperSigningKeySet());
     }
@@ -807,9 +760,9 @@
         /* remove references from first package */
         mKsms.removeAppKeySetDataLPw(ps1.name);
 
-        assertEquals(1, getKeySetRefCount(1));
-        assertEquals(1, getPubKeyRefCount(1));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(1, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(1, ksMapping.size());
         assertEquals(PackageKeySetData.KEYSET_UNASSIGNED, ps1.keySetData.getProperSigningKeySet());
         assertEquals(1, ps2.keySetData.getProperSigningKeySet());
@@ -840,9 +793,9 @@
         mKsms.addUpgradeKeySetsToPackageLPw(ps.name, upgradeKS);
         mKsms.removeAppKeySetDataLPw(ps.name);
 
-        assertEquals(0, getKeySetRefCount(1));
-        assertEquals(0, getPubKeyRefCount(1));
-        LongSparseArray<ArraySet<Long>> ksMapping = getKeySetMapping();
+        assertEquals(0, KeySetUtils.getKeySetRefCount(mKsms, 1));
+        assertEquals(0, KeySetUtils.getPubKeyRefCount(mKsms, 1));
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(mKsms);
         assertEquals(0, ksMapping.size());
         assertEquals(PackageKeySetData.KEYSET_UNASSIGNED, ps.keySetData.getProperSigningKeySet());
         assertEquals(0, ps.keySetData.getAliases().size());
diff --git a/services/tests/servicestests/src/com/android/server/pm/KeySetUtils.java b/services/tests/servicestests/src/com/android/server/pm/KeySetUtils.java
new file mode 100644
index 0000000..9e1a366
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/KeySetUtils.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.util.ArraySet;
+import android.util.LongSparseArray;
+
+import java.lang.reflect.Field;
+import java.security.PublicKey;
+
+public class KeySetUtils {
+
+    public static PublicKey getPubKey(KeySetManagerService ksms, long pkId)
+            throws NoSuchFieldException, IllegalAccessException {
+        Field pkField = ksms.getClass().getDeclaredField("mPublicKeys");
+        pkField.setAccessible(true);
+        LongSparseArray<KeySetManagerService.PublicKeyHandle> mPublicKeys =
+            (LongSparseArray<KeySetManagerService.PublicKeyHandle>) pkField.get(ksms);
+        KeySetManagerService.PublicKeyHandle pkh = mPublicKeys.get(pkId);
+        if (pkh == null) {
+            return null;
+        } else {
+            return pkh.getKey();
+        }
+    }
+
+    public static int getPubKeyRefCount(KeySetManagerService ksms, long pkId)
+            throws NoSuchFieldException, IllegalAccessException {
+        Field pkField = ksms.getClass().getDeclaredField("mPublicKeys");
+        pkField.setAccessible(true);
+        LongSparseArray<KeySetManagerService.PublicKeyHandle> mPublicKeys =
+            (LongSparseArray<KeySetManagerService.PublicKeyHandle>) pkField.get(ksms);
+        KeySetManagerService.PublicKeyHandle pkh = mPublicKeys.get(pkId);
+        if (pkh == null) {
+            return 0;
+        } else {
+            return pkh.getRefCountLPr();
+        }
+    }
+
+    public static int getKeySetRefCount(KeySetManagerService ksms, long keysetId)
+            throws NoSuchFieldException, IllegalAccessException {
+        Field ksField = ksms.getClass().getDeclaredField("mKeySets");
+        ksField.setAccessible(true);
+        LongSparseArray<KeySetHandle> mKeySets =
+            (LongSparseArray<KeySetHandle>) ksField.get(ksms);
+        KeySetHandle ksh = mKeySets.get(keysetId);
+        if (ksh == null) {
+            return 0;
+        } else {
+            return ksh.getRefCountLPr();
+        }
+    }
+
+    public static LongSparseArray<ArraySet<Long>> getKeySetMapping(KeySetManagerService ksms)
+            throws NoSuchFieldException, IllegalAccessException {
+        Field ksField = ksms.getClass().getDeclaredField("mKeySetMapping");
+        ksField.setAccessible(true);
+        return (LongSparseArray<ArraySet<Long>>) ksField.get(ksms);
+    }
+
+    public static Long getLastIssuedKeyId(KeySetManagerService ksms)
+            throws NoSuchFieldException, IllegalAccessException {
+        Field ksField = ksms.getClass().getDeclaredField("lastIssuedKeyId");
+        ksField.setAccessible(true);
+        return (Long) ksField.get(ksms);
+    }
+
+    public static Long getLastIssuedKeySetId(KeySetManagerService ksms)
+            throws NoSuchFieldException, IllegalAccessException {
+        Field ksField = ksms.getClass().getDeclaredField("lastIssuedKeySetId");
+        ksField.setAccessible(true);
+        return (Long) ksField.get(ksms);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index a3f3a5d..ed1db6f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -21,15 +21,21 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 
+import android.content.Context;
+import android.content.pm.PackageParser;
 import android.test.AndroidTestCase;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.LongSparseArray;
 
 import com.android.internal.os.AtomicFile;
 
+import java.lang.reflect.Constructor;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.security.PublicKey;
 
 public class PackageManagerSettingsTests extends AndroidTestCase {
     private static final String PACKAGE_NAME_2 = "com.google.app2";
@@ -67,18 +73,24 @@
                 + "</permissions>"
                 + "<package name=\"com.google.app1\" codePath=\"/system/app/app1.apk\" nativeLibraryPath=\"/data/data/com.google.app1/lib\" flags=\"1\" ft=\"1360e2caa70\" it=\"135f2f80d08\" ut=\"1360e2caa70\" version=\"1109\" sharedUserId=\"11000\">"
                 + "<sigs count=\"1\">"
-                + "<cert index=\"0\" key=\"308886\" />"
+                + "<cert index=\"0\" key=\"" + KeySetStrings.ctsKeySetCertA + "\" />"
                 + "</sigs>"
+                + "<proper-signing-keyset identifier=\"1\" />"
                 + "</package>"
                 + "<package name=\"com.google.app2\" codePath=\"/system/app/app2.apk\" nativeLibraryPath=\"/data/data/com.google.app2/lib\" flags=\"1\" ft=\"1360e578718\" it=\"135f2f80d08\" ut=\"1360e578718\" version=\"15\" enabled=\"3\" userId=\"11001\">"
                 + "<sigs count=\"1\">"
                 + "<cert index=\"0\" />"
                 + "</sigs>"
+                + "<proper-signing-keyset identifier=\"1\" />"
+                + "<defined-keyset alias=\"AB\" identifier=\"4\" />"
                 + "</package>"
                 + "<package name=\"com.android.app3\" codePath=\"/system/app/app3.apk\" nativeLibraryPath=\"/data/data/com.android.app3/lib\" flags=\"1\" ft=\"1360e577b60\" it=\"135f2f80d08\" ut=\"1360e577b60\" version=\"15\" userId=\"11030\">"
                 + "<sigs count=\"1\">"
-                + "<cert index=\"1\" key=\"308366\" />"
+                + "<cert index=\"1\" key=\"" + KeySetStrings.ctsKeySetCertB + "\" />"
                 + "</sigs>"
+                + "<proper-signing-keyset identifier=\"2\" />"
+                + "<upgrade-keyset identifier=\"3\" />"
+                + "<defined-keyset alias=\"C\" identifier=\"3\" />"
                 + "</package>"
                 + "<shared-user name=\"com.android.shared1\" userId=\"11000\">"
                 + "<sigs count=\"1\">"
@@ -88,6 +100,30 @@
                 + "<item name=\"android.permission.REBOOT\" />"
                 + "</perms>"
                 + "</shared-user>"
+                + "<keyset-settings version=\"1\">"
+                + "<keys>"
+                + "<public-key identifier=\"1\" value=\"" + KeySetStrings.ctsKeySetPublicKeyA + "\" />"
+                + "<public-key identifier=\"2\" value=\"" + KeySetStrings.ctsKeySetPublicKeyB + "\" />"
+                + "<public-key identifier=\"3\" value=\"" + KeySetStrings.ctsKeySetPublicKeyC + "\" />"
+                + "</keys>"
+                + "<keysets>"
+                + "<keyset identifier=\"1\">"
+                + "<key-id identifier=\"1\" />"
+                + "</keyset>"
+                + "<keyset identifier=\"2\">"
+                + "<key-id identifier=\"2\" />"
+                + "</keyset>"
+                + "<keyset identifier=\"3\">"
+                + "<key-id identifier=\"3\" />"
+                + "</keyset>"
+                + "<keyset identifier=\"4\">"
+                + "<key-id identifier=\"1\" />"
+                + "<key-id identifier=\"2\" />"
+                + "</keyset>"
+                + "</keysets>"
+                + "<lastIssuedKeyId value=\"3\" />"
+                + "<lastIssuedKeySetId value=\"4\" />"
+                + "</keyset-settings>"
                 + "</packages>").getBytes());
     }
 
@@ -131,6 +167,104 @@
         writePackagesList();
     }
 
+    private void createUserManagerServiceRef() throws ReflectiveOperationException {
+        Constructor<UserManagerService> umsc =
+                UserManagerService.class.getDeclaredConstructor(
+                        Context.class,
+                        PackageManagerService.class,
+                        Object.class,
+                        Object.class,
+                        File.class,
+                        File.class);
+        umsc.setAccessible(true);
+        UserManagerService ums = umsc.newInstance(getContext(), null,
+                new Object(), new Object(), getContext().getFilesDir(),
+                new File(getContext().getFilesDir(), "user"));
+    }
+
+    private void verifyKeySetMetaData(Settings settings)
+            throws ReflectiveOperationException, IllegalAccessException {
+        ArrayMap<String, PackageSetting> packages = settings.mPackages;
+        KeySetManagerService ksms = settings.mKeySetManagerService;
+
+        /* verify keyset and public key ref counts */
+        assertEquals(2, KeySetUtils.getKeySetRefCount(ksms, 1));
+        assertEquals(1, KeySetUtils.getKeySetRefCount(ksms, 2));
+        assertEquals(1, KeySetUtils.getKeySetRefCount(ksms, 3));
+        assertEquals(1, KeySetUtils.getKeySetRefCount(ksms, 4));
+        assertEquals(2, KeySetUtils.getPubKeyRefCount(ksms, 1));
+        assertEquals(2, KeySetUtils.getPubKeyRefCount(ksms, 2));
+        assertEquals(1, KeySetUtils.getPubKeyRefCount(ksms, 3));
+
+        /* verify public keys properly read */
+        PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
+        PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
+        PublicKey keyC = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyC);
+        assertEquals(keyA, KeySetUtils.getPubKey(ksms, 1));
+        assertEquals(keyB, KeySetUtils.getPubKey(ksms, 2));
+        assertEquals(keyC, KeySetUtils.getPubKey(ksms, 3));
+
+        /* verify mapping is correct (ks -> pub keys) */
+        LongSparseArray<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(ksms);
+        ArraySet<Long> mapping = ksMapping.get(1);
+        assertEquals(1, mapping.size());
+        assertTrue(mapping.contains(new Long(1)));
+        mapping = ksMapping.get(2);
+        assertEquals(1, mapping.size());
+        assertTrue(mapping.contains(new Long(2)));
+        mapping = ksMapping.get(3);
+        assertEquals(1, mapping.size());
+        assertTrue(mapping.contains(new Long(3)));
+        mapping = ksMapping.get(4);
+        assertEquals(2, mapping.size());
+        assertTrue(mapping.contains(new Long(1)));
+        assertTrue(mapping.contains(new Long(2)));
+
+        /* verify lastIssuedIds are consistent */
+        assertEquals(new Long(3), KeySetUtils.getLastIssuedKeyId(ksms));
+        assertEquals(new Long(4), KeySetUtils.getLastIssuedKeySetId(ksms));
+
+        /* verify packages have been given the appropriat information */
+        PackageSetting ps = packages.get("com.google.app1");
+        assertEquals(1, ps.keySetData.getProperSigningKeySet());
+        ps = packages.get("com.google.app2");
+        assertEquals(1, ps.keySetData.getProperSigningKeySet());
+        assertEquals(new Long(4), ps.keySetData.getAliases().get("AB"));
+        ps = packages.get("com.android.app3");
+        assertEquals(2, ps.keySetData.getProperSigningKeySet());
+        assertEquals(new Long(3), ps.keySetData.getAliases().get("C"));
+        assertEquals(1, ps.keySetData.getUpgradeKeySets().length);
+        assertEquals(3, ps.keySetData.getUpgradeKeySets()[0]);
+    }
+
+    /* make sure our initialized keysetmanagerservice metadata matches packages.xml */
+    public void testReadKeySetSettings()
+            throws ReflectiveOperationException, IllegalAccessException {
+
+        /* write out files and read */
+        writeOldFiles();
+        createUserManagerServiceRef();
+        Settings settings = new Settings(getContext().getFilesDir(), new Object());
+        assertEquals(true, settings.readLPw(null, null, 0, false));
+        verifyKeySetMetaData(settings);
+    }
+
+    /* read in data, write it out, and read it back in.  Verify same. */
+    public void testWriteKeySetSettings()
+            throws ReflectiveOperationException, IllegalAccessException {
+
+        /* write out files and read */
+        writeOldFiles();
+        createUserManagerServiceRef();
+        Settings settings = new Settings(getContext().getFilesDir(), new Object());
+        assertEquals(true, settings.readLPw(null, null, 0, false));
+
+        /* write out, read back in and verify the same */
+        settings.writeLPr();
+        assertEquals(true, settings.readLPw(null, null, 0, false));
+        verifyKeySetMetaData(settings);
+    }
+
     public void testSettingsReadOld() {
         // Write the package files and make sure they're parsed properly the first time
         writeOldFiles();
@@ -149,9 +283,11 @@
         assertEquals(COMPONENT_ENABLED_STATE_DEFAULT, ps.getEnabled(1));
     }
 
-    public void testNewPackageRestrictionsFile() {
+    public void testNewPackageRestrictionsFile() throws ReflectiveOperationException {
+
         // Write the package files and make sure they're parsed properly the first time
         writeOldFiles();
+        createUserManagerServiceRef();
         Settings settings = new Settings(getContext().getFilesDir(), new Object());
         assertEquals(true, settings.readLPw(null, null, 0, false));
         settings.writeLPr();
diff --git a/telecomm/java/android/telecom/DefaultDialerManager.java b/telecomm/java/android/telecom/DefaultDialerManager.java
index 93823d1..b5d566a 100644
--- a/telecomm/java/android/telecom/DefaultDialerManager.java
+++ b/telecomm/java/android/telecom/DefaultDialerManager.java
@@ -14,7 +14,6 @@
 
 package android.telecom;
 
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -52,13 +51,12 @@
         }
 
         // Only make the change if the new package belongs to a valid phone application
-        List<ComponentName> componentNames = getInstalledDialerApplications(context);
-        final ComponentName foundComponent = getComponentName(componentNames, packageName);
+        List<String> packageNames = getInstalledDialerApplications(context);
 
-        if (foundComponent != null) {
+        if (packageNames.contains(packageName)) {
             // Update the secure setting.
             Settings.Secure.putString(context.getContentResolver(),
-                    Settings.Secure.DIALER_DEFAULT_APPLICATION, foundComponent.getPackageName());
+                    Settings.Secure.DIALER_DEFAULT_APPLICATION, packageName);
         }
     }
 
@@ -73,29 +71,31 @@
      *
      * @hide
      * */
-    public static ComponentName getDefaultDialerApplication(Context context) {
+    public static String getDefaultDialerApplication(Context context) {
         String defaultPackageName = Settings.Secure.getString(context.getContentResolver(),
                 Settings.Secure.DIALER_DEFAULT_APPLICATION);
 
-        final List<ComponentName> componentNames = getInstalledDialerApplications(context);
-        if (!TextUtils.isEmpty(defaultPackageName)) {
-            final ComponentName defaultDialer =
-                    getComponentName(componentNames, defaultPackageName);
-            if (defaultDialer != null) {
-                return defaultDialer;
-            }
+
+        final List<String> packageNames = getInstalledDialerApplications(context);
+
+        // Verify that the default dialer has not been disabled or uninstalled.
+        if (packageNames.contains(defaultPackageName)) {
+            return defaultPackageName;
         }
 
         // No user-set dialer found, fallback to system dialer
-        String systemDialer = getTelecomManager(context).getSystemDialerPackage();
+        String systemDialerPackageName = getTelecomManager(context).getSystemDialerPackage();
 
-        if (TextUtils.isEmpty(systemDialer)) {
+        if (TextUtils.isEmpty(systemDialerPackageName)) {
             // No system dialer configured at build time
             return null;
         }
 
-        // Verify that the system dialer has not been disabled.
-        return getComponentName(componentNames, systemDialer);
+        if (packageNames.contains(systemDialerPackageName)) {
+            return systemDialerPackageName;
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -109,44 +109,25 @@
      *
      * @hide
      **/
-    public static List<ComponentName> getInstalledDialerApplications(Context context) {
+    public static List<String> getInstalledDialerApplications(Context context) {
         PackageManager packageManager = context.getPackageManager();
 
         // Get the list of apps registered for the DIAL intent with empty scheme
         Intent intent = new Intent(Intent.ACTION_DIAL);
         List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(intent, 0);
 
-        List<ComponentName> componentNames = new ArrayList<ComponentName> ();
+        List<String> packageNames = new ArrayList<>();
 
         for (ResolveInfo resolveInfo : resolveInfoList) {
             final ActivityInfo activityInfo = resolveInfo.activityInfo;
             if (activityInfo == null) {
                 continue;
             }
-            final ComponentName componentName =
-                    new ComponentName(activityInfo.packageName, activityInfo.name);
-            componentNames.add(componentName);
+            packageNames.add(activityInfo.packageName);
         }
 
         // TODO: Filter for apps that don't handle DIAL intent with tel scheme
-        return componentNames;
-    }
-
-    /**
-     * Returns the {@link ComponentName} for the installed dialer application for a given package
-     * name.
-     *
-     * @param context A valid context.
-     * @param packageName to retrieve the {@link ComponentName} for.
-     *
-     * @return The {@link ComponentName} for the installed dialer application corresponding to the
-     * package name, or null if none is found.
-     *
-     * @hide
-     */
-    public static ComponentName getDialerApplicationForPackageName(Context context,
-            String packageName) {
-        return getComponentName(getInstalledDialerApplications(context), packageName);
+        return packageNames;
     }
 
     /**
@@ -170,25 +151,6 @@
                 || packageName.equals(tm.getSystemDialerPackage());
     }
 
-    /**
-     * Returns the component from a list of application components that corresponds to the package
-     * name.
-     *
-     * @param componentNames A list of component names
-     * @param packageName The package name to look for
-     * @return The {@link ComponentName} that matches the provided packageName, or null if not
-     *         found.
-     */
-    private static ComponentName getComponentName(List<ComponentName> componentNames,
-            String packageName) {
-        for (ComponentName componentName : componentNames) {
-            if (TextUtils.equals(packageName, componentName.getPackageName())) {
-                return componentName;
-            }
-        }
-        return null;
-    }
-
     private static TelecomManager getTelecomManager(Context context) {
         return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
     }