Merge "Textfield search items updated thickness on vertical bars Bug: 5076695"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 3cec66f..0dba18b 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -106,6 +106,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/R/com/android/systemui/R.java)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IAudioService.P)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IAudioService.P)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/api/current.txt b/api/current.txt
index 9758433..b962234 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -184,21 +184,21 @@
   public static final class R.attr {
     ctor public R.attr();
     field public static final int absListViewStyle = 16842858; // 0x101006a
-    field public static final int accessibilityEventTypes = 16843644; // 0x101037c
-    field public static final int accessibilityFeedbackType = 16843646; // 0x101037e
-    field public static final int accessibilityFlags = 16843648; // 0x1010380
+    field public static final int accessibilityEventTypes = 16843643; // 0x101037b
+    field public static final int accessibilityFeedbackType = 16843645; // 0x101037d
+    field public static final int accessibilityFlags = 16843647; // 0x101037f
     field public static final int accountPreferences = 16843423; // 0x101029f
     field public static final int accountType = 16843407; // 0x101028f
     field public static final int action = 16842797; // 0x101002d
-    field public static final int actionBarDivider = 16843685; // 0x10103a5
-    field public static final int actionBarItemBackground = 16843686; // 0x10103a6
+    field public static final int actionBarDivider = 16843684; // 0x10103a4
+    field public static final int actionBarItemBackground = 16843685; // 0x10103a5
     field public static final int actionBarSize = 16843499; // 0x10102eb
-    field public static final int actionBarSplitStyle = 16843666; // 0x1010392
+    field public static final int actionBarSplitStyle = 16843665; // 0x1010391
     field public static final int actionBarStyle = 16843470; // 0x10102ce
     field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4
     field public static final int actionBarTabStyle = 16843507; // 0x10102f3
     field public static final int actionBarTabTextStyle = 16843509; // 0x10102f5
-    field public static final int actionBarWidgetTheme = 16843681; // 0x10103a1
+    field public static final int actionBarWidgetTheme = 16843680; // 0x10103a0
     field public static final int actionButtonStyle = 16843480; // 0x10102d8
     field public static final int actionDropDownStyle = 16843479; // 0x10102d7
     field public static final int actionLayout = 16843515; // 0x10102fb
@@ -210,11 +210,11 @@
     field public static final int actionModeCopyDrawable = 16843538; // 0x1010312
     field public static final int actionModeCutDrawable = 16843537; // 0x1010311
     field public static final int actionModePasteDrawable = 16843539; // 0x1010313
-    field public static final int actionModeSelectAllDrawable = 16843642; // 0x101037a
-    field public static final int actionModeSplitBackground = 16843687; // 0x10103a7
-    field public static final int actionModeStyle = 16843678; // 0x101039e
+    field public static final int actionModeSelectAllDrawable = 16843641; // 0x1010379
+    field public static final int actionModeSplitBackground = 16843686; // 0x10103a6
+    field public static final int actionModeStyle = 16843677; // 0x101039d
     field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
-    field public static final int actionProviderClass = 16843667; // 0x1010393
+    field public static final int actionProviderClass = 16843666; // 0x1010392
     field public static final int actionViewClass = 16843516; // 0x10102fc
     field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
     field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
@@ -226,7 +226,7 @@
     field public static final int alertDialogIcon = 16843605; // 0x1010355
     field public static final int alertDialogStyle = 16842845; // 0x101005d
     field public static final int alertDialogTheme = 16843529; // 0x1010309
-    field public static final int alignmentMode = 16843638; // 0x1010376
+    field public static final int alignmentMode = 16843637; // 0x1010375
     field public static final int allContactsName = 16843468; // 0x10102cc
     field public static final int allowBackup = 16843392; // 0x1010280
     field public static final int allowClearUserData = 16842757; // 0x1010005
@@ -260,8 +260,8 @@
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
-    field public static final int backgroundSplit = 16843669; // 0x1010395
-    field public static final int backgroundStacked = 16843668; // 0x1010394
+    field public static final int backgroundSplit = 16843668; // 0x1010394
+    field public static final int backgroundStacked = 16843667; // 0x1010393
     field public static final int backupAgent = 16843391; // 0x101027f
     field public static final int baseline = 16843548; // 0x101031c
     field public static final int baselineAlignBottom = 16843042; // 0x1010122
@@ -270,7 +270,7 @@
     field public static final int borderlessButtonStyle = 16843563; // 0x101032b
     field public static final int bottom = 16843184; // 0x10101b0
     field public static final int bottomBright = 16842957; // 0x10100cd
-    field public static final int bottomChevronDrawable = 16843655; // 0x1010387
+    field public static final int bottomChevronDrawable = 16843654; // 0x1010386
     field public static final int bottomDark = 16842953; // 0x10100c9
     field public static final int bottomLeftRadius = 16843179; // 0x10101ab
     field public static final int bottomMedium = 16842958; // 0x10100ce
@@ -289,7 +289,7 @@
     field public static final int cacheColorHint = 16843009; // 0x1010101
     field public static final int calendarViewShown = 16843596; // 0x101034c
     field public static final int calendarViewStyle = 16843613; // 0x101035d
-    field public static final int canRetrieveWindowContent = 16843649; // 0x1010381
+    field public static final int canRetrieveWindowContent = 16843648; // 0x1010380
     field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
     field public static final deprecated int capitalize = 16843113; // 0x1010169
     field public static final int centerBright = 16842956; // 0x10100cc
@@ -318,18 +318,18 @@
     field public static final int codes = 16843330; // 0x1010242
     field public static final int collapseColumns = 16843083; // 0x101014b
     field public static final int color = 16843173; // 0x10101a5
-    field public static final int colorActivatedHighlight = 16843674; // 0x101039a
+    field public static final int colorActivatedHighlight = 16843673; // 0x1010399
     field public static final int colorBackground = 16842801; // 0x1010031
     field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
-    field public static final int colorFocusedHighlight = 16843673; // 0x1010399
+    field public static final int colorFocusedHighlight = 16843672; // 0x1010398
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
-    field public static final int colorLongPressedHighlight = 16843672; // 0x1010398
-    field public static final int colorMultiSelectHighlight = 16843675; // 0x101039b
-    field public static final int colorPressedHighlight = 16843671; // 0x1010397
-    field public static final int columnCount = 16843635; // 0x1010373
+    field public static final int colorLongPressedHighlight = 16843671; // 0x1010397
+    field public static final int colorMultiSelectHighlight = 16843674; // 0x101039a
+    field public static final int colorPressedHighlight = 16843670; // 0x1010396
+    field public static final int columnCount = 16843634; // 0x1010372
     field public static final int columnDelay = 16843215; // 0x10101cf
-    field public static final int columnOrderPreserved = 16843636; // 0x1010374
+    field public static final int columnOrderPreserved = 16843635; // 0x1010373
     field public static final int columnWidth = 16843031; // 0x1010117
     field public static final int compatibleWidthLimitDp = 16843621; // 0x1010365
     field public static final int completionHint = 16843122; // 0x1010172
@@ -383,11 +383,11 @@
     field public static final int drawSelectorOnTop = 16843004; // 0x10100fc
     field public static final int drawable = 16843161; // 0x1010199
     field public static final int drawableBottom = 16843118; // 0x101016e
-    field public static final int drawableEnd = 16843677; // 0x101039d
+    field public static final int drawableEnd = 16843676; // 0x101039c
     field public static final int drawableLeft = 16843119; // 0x101016f
     field public static final int drawablePadding = 16843121; // 0x1010171
     field public static final int drawableRight = 16843120; // 0x1010170
-    field public static final int drawableStart = 16843676; // 0x101039c
+    field public static final int drawableStart = 16843675; // 0x101039b
     field public static final int drawableTop = 16843117; // 0x101016d
     field public static final int drawingCacheQuality = 16842984; // 0x10100e8
     field public static final int dropDownAnchor = 16843363; // 0x1010263
@@ -444,7 +444,7 @@
     field public static final int fastScrollTextColor = 16843609; // 0x1010359
     field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336
     field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339
-    field public static final int feedbackCount = 16843661; // 0x101038d
+    field public static final int feedbackCount = 16843660; // 0x101038c
     field public static final int fillAfter = 16843197; // 0x10101bd
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillEnabled = 16843343; // 0x101024f
@@ -497,7 +497,7 @@
     field public static final int hand_hour = 16843011; // 0x1010103
     field public static final int hand_minute = 16843012; // 0x1010104
     field public static final int handle = 16843354; // 0x101025a
-    field public static final int handleDrawable = 16843651; // 0x1010383
+    field public static final int handleDrawable = 16843650; // 0x1010382
     field public static final int handleProfiling = 16842786; // 0x1010022
     field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
     field public static final int hardwareAccelerated = 16843475; // 0x10102d3
@@ -506,12 +506,12 @@
     field public static final int headerDividersEnabled = 16843310; // 0x101022e
     field public static final int height = 16843093; // 0x1010155
     field public static final int hint = 16843088; // 0x1010150
-    field public static final int hitRadius = 16843658; // 0x101038a
+    field public static final int hitRadius = 16843657; // 0x1010389
     field public static final int homeAsUpIndicator = 16843531; // 0x101030b
     field public static final int homeLayout = 16843549; // 0x101031d
     field public static final int horizontalDivider = 16843053; // 0x101012d
     field public static final int horizontalGap = 16843327; // 0x101023f
-    field public static final int horizontalOffset = 16843663; // 0x101038f
+    field public static final int horizontalOffset = 16843662; // 0x101038e
     field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
     field public static final int horizontalSpacing = 16843028; // 0x1010114
     field public static final int host = 16842792; // 0x1010028
@@ -557,7 +557,7 @@
     field public static final int installLocation = 16843447; // 0x10102b7
     field public static final int interpolator = 16843073; // 0x1010141
     field public static final int isAlwaysSyncable = 16843571; // 0x1010333
-    field public static final int isAuxiliary = 16843643; // 0x101037b
+    field public static final int isAuxiliary = 16843642; // 0x101037a
     field public static final int isDefault = 16843297; // 0x1010221
     field public static final int isIndicator = 16843079; // 0x1010147
     field public static final int isModifier = 16843334; // 0x1010246
@@ -610,7 +610,7 @@
     field public static final int layout_centerInParent = 16843151; // 0x101018f
     field public static final int layout_centerVertical = 16843153; // 0x1010191
     field public static final int layout_column = 16843084; // 0x101014c
-    field public static final int layout_columnSpan = 16843641; // 0x1010379
+    field public static final int layout_columnSpan = 16843640; // 0x1010378
     field public static final int layout_gravity = 16842931; // 0x10100b3
     field public static final int layout_height = 16842997; // 0x10100f5
     field public static final int layout_margin = 16842998; // 0x10100f6
@@ -618,8 +618,8 @@
     field public static final int layout_marginLeft = 16842999; // 0x10100f7
     field public static final int layout_marginRight = 16843001; // 0x10100f9
     field public static final int layout_marginTop = 16843000; // 0x10100f8
-    field public static final int layout_row = 16843639; // 0x1010377
-    field public static final int layout_rowSpan = 16843640; // 0x1010378
+    field public static final int layout_row = 16843638; // 0x1010376
+    field public static final int layout_rowSpan = 16843639; // 0x1010377
     field public static final int layout_scale = 16843155; // 0x1010193
     field public static final int layout_span = 16843085; // 0x101014d
     field public static final int layout_toLeftOf = 16843138; // 0x1010182
@@ -629,7 +629,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 leftChevronDrawable = 16843652; // 0x1010384
+    field public static final int leftChevronDrawable = 16843651; // 0x1010383
     field public static final int lineSpacingExtra = 16843287; // 0x1010217
     field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
     field public static final int lines = 16843092; // 0x1010154
@@ -641,8 +641,8 @@
     field public static final int listDividerAlertDialog = 16843525; // 0x1010305
     field public static final int listPopupWindowStyle = 16843519; // 0x10102ff
     field public static final int listPreferredItemHeight = 16842829; // 0x101004d
-    field public static final int listPreferredItemHeightLarge = 16843664; // 0x1010390
-    field public static final int listPreferredItemHeightSmall = 16843665; // 0x1010391
+    field public static final int listPreferredItemHeightLarge = 16843663; // 0x101038f
+    field public static final int listPreferredItemHeightSmall = 16843664; // 0x1010390
     field public static final int listSelector = 16843003; // 0x10100fb
     field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208
     field public static final int listViewStyle = 16842868; // 0x1010074
@@ -673,8 +673,8 @@
     field public static final int minHeight = 16843072; // 0x1010140
     field public static final int minLevel = 16843185; // 0x10101b1
     field public static final int minLines = 16843094; // 0x1010156
-    field public static final int minResizeHeight = 16843680; // 0x10103a0
-    field public static final int minResizeWidth = 16843679; // 0x101039f
+    field public static final int minResizeHeight = 16843679; // 0x101039f
+    field public static final int minResizeWidth = 16843678; // 0x101039e
     field public static final int minSdkVersion = 16843276; // 0x101020c
     field public static final int minWidth = 16843071; // 0x101013f
     field public static final int mode = 16843134; // 0x101017e
@@ -690,7 +690,7 @@
     field public static final int nextFocusUp = 16842979; // 0x10100e3
     field public static final int noHistory = 16843309; // 0x101022d
     field public static final int normalScreens = 16843397; // 0x1010285
-    field public static final int notificationTimeout = 16843647; // 0x101037f
+    field public static final int notificationTimeout = 16843646; // 0x101037e
     field public static final int numColumns = 16843032; // 0x1010118
     field public static final int numStars = 16843076; // 0x1010144
     field public static final deprecated int numeric = 16843109; // 0x1010165
@@ -704,11 +704,11 @@
     field public static final int orderingFromXml = 16843239; // 0x10101e7
     field public static final int orientation = 16842948; // 0x10100c4
     field public static final int outAnimation = 16843128; // 0x1010178
-    field public static final int outerRadius = 16843657; // 0x1010389
+    field public static final int outerRadius = 16843656; // 0x1010388
     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 packageNames = 16843645; // 0x101037d
+    field public static final int packageNames = 16843644; // 0x101037c
     field public static final int padding = 16842965; // 0x10100d5
     field public static final int paddingBottom = 16842969; // 0x10100d9
     field public static final int paddingLeft = 16842966; // 0x10100d6
@@ -793,17 +793,17 @@
     field public static final int restoreAnyVersion = 16843450; // 0x10102ba
     field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
     field public static final int right = 16843183; // 0x10101af
-    field public static final int rightChevronDrawable = 16843653; // 0x1010385
+    field public static final int rightChevronDrawable = 16843652; // 0x1010384
     field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
     field public static final int ringtoneType = 16843257; // 0x10101f9
     field public static final int rotation = 16843558; // 0x1010326
     field public static final int rotationX = 16843559; // 0x1010327
     field public static final int rotationY = 16843560; // 0x1010328
-    field public static final int rowCount = 16843633; // 0x1010371
+    field public static final int rowCount = 16843632; // 0x1010370
     field public static final int rowDelay = 16843216; // 0x10101d0
     field public static final int rowEdgeFlags = 16843329; // 0x1010241
     field public static final int rowHeight = 16843058; // 0x1010132
-    field public static final int rowOrderPreserved = 16843634; // 0x1010372
+    field public static final int rowOrderPreserved = 16843633; // 0x1010371
     field public static final int saveEnabled = 16842983; // 0x10100e7
     field public static final int scaleGravity = 16843262; // 0x10101fe
     field public static final int scaleHeight = 16843261; // 0x10101fd
@@ -869,7 +869,7 @@
     field public static final int smallIcon = 16843422; // 0x101029e
     field public static final int smallScreens = 16843396; // 0x1010284
     field public static final int smoothScrollbar = 16843313; // 0x1010231
-    field public static final int snapMargin = 16843660; // 0x101038c
+    field public static final int snapMargin = 16843659; // 0x101038b
     field public static final int soundEffectsEnabled = 16843285; // 0x1010215
     field public static final int spacing = 16843027; // 0x1010113
     field public static final int spinnerDropDownItemStyle = 16842887; // 0x1010087
@@ -915,11 +915,10 @@
     field public static final int stretchMode = 16843030; // 0x1010116
     field public static final int subtitle = 16843473; // 0x10102d1
     field public static final int subtitleTextStyle = 16843513; // 0x10102f9
-    field public static final int subtypeExtraValue = 16843684; // 0x10103a4
-    field public static final int subtypeLocale = 16843683; // 0x10103a3
+    field public static final int subtypeExtraValue = 16843683; // 0x10103a3
+    field public static final int subtypeLocale = 16843682; // 0x10103a2
     field public static final int suggestActionMsg = 16843228; // 0x10101dc
     field public static final int suggestActionMsgColumn = 16843229; // 0x10101dd
-    field public static final int suggestionsEnabled = 16843632; // 0x1010370
     field public static final int summary = 16843241; // 0x10101e9
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
@@ -936,7 +935,7 @@
     field public static final int tag = 16842961; // 0x10100d1
     field public static final int targetActivity = 16843266; // 0x1010202
     field public static final int targetClass = 16842799; // 0x101002f
-    field public static final int targetDrawables = 16843650; // 0x1010382
+    field public static final int targetDrawables = 16843649; // 0x1010381
     field public static final int targetPackage = 16842785; // 0x1010021
     field public static final int targetSdkVersion = 16843376; // 0x1010270
     field public static final int taskAffinity = 16842770; // 0x1010012
@@ -951,15 +950,15 @@
     field public static final int tension = 16843370; // 0x101026a
     field public static final int testOnly = 16843378; // 0x1010272
     field public static final int text = 16843087; // 0x101014f
-    field public static final int textAllCaps = 16843670; // 0x1010396
+    field public static final int textAllCaps = 16843669; // 0x1010395
     field public static final int textAppearance = 16842804; // 0x1010034
     field public static final int textAppearanceButton = 16843271; // 0x1010207
     field public static final int textAppearanceInverse = 16842805; // 0x1010035
     field public static final int textAppearanceLarge = 16842816; // 0x1010040
     field public static final int textAppearanceLargeInverse = 16842819; // 0x1010043
     field public static final int textAppearanceLargePopupMenu = 16843521; // 0x1010301
-    field public static final int textAppearanceListItem = 16843688; // 0x10103a8
-    field public static final int textAppearanceListItemSmall = 16843689; // 0x10103a9
+    field public static final int textAppearanceListItem = 16843687; // 0x10103a7
+    field public static final int textAppearanceListItemSmall = 16843688; // 0x10103a8
     field public static final int textAppearanceMedium = 16842817; // 0x1010041
     field public static final int textAppearanceMediumInverse = 16842820; // 0x1010044
     field public static final int textAppearanceSearchResultSubtitle = 16843424; // 0x10102a0
@@ -1027,7 +1026,7 @@
     field public static final int toYScale = 16843205; // 0x10101c5
     field public static final int top = 16843182; // 0x10101ae
     field public static final int topBright = 16842955; // 0x10100cb
-    field public static final int topChevronDrawable = 16843654; // 0x1010386
+    field public static final int topChevronDrawable = 16843653; // 0x1010385
     field public static final int topDark = 16842951; // 0x10100c7
     field public static final int topLeftRadius = 16843177; // 0x10101a9
     field public static final int topOffset = 16843352; // 0x1010258
@@ -1039,12 +1038,12 @@
     field public static final int translationY = 16843555; // 0x1010323
     field public static final int type = 16843169; // 0x10101a1
     field public static final int typeface = 16842902; // 0x1010096
-    field public static final int uiOptions = 16843682; // 0x10103a2
+    field public static final int uiOptions = 16843681; // 0x10103a1
     field public static final int uncertainGestureColor = 16843382; // 0x1010276
     field public static final int unfocusedMonthDateColor = 16843588; // 0x1010344
     field public static final int unselectedAlpha = 16843278; // 0x101020e
     field public static final int updatePeriodMillis = 16843344; // 0x1010250
-    field public static final int useDefaultMargins = 16843637; // 0x1010375
+    field public static final int useDefaultMargins = 16843636; // 0x1010374
     field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
     field public static final int useLevel = 16843167; // 0x101019f
     field public static final int userVisible = 16843409; // 0x1010291
@@ -1058,10 +1057,10 @@
     field public static final int verticalCorrection = 16843322; // 0x101023a
     field public static final int verticalDivider = 16843054; // 0x101012e
     field public static final int verticalGap = 16843328; // 0x1010240
-    field public static final int verticalOffset = 16843662; // 0x101038e
+    field public static final int verticalOffset = 16843661; // 0x101038d
     field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
     field public static final int verticalSpacing = 16843029; // 0x1010115
-    field public static final int vibrationDuration = 16843659; // 0x101038b
+    field public static final int vibrationDuration = 16843658; // 0x101038a
     field public static final int visibility = 16842972; // 0x10100dc
     field public static final int visible = 16843156; // 0x1010194
     field public static final int vmSafeMode = 16843448; // 0x10102b8
@@ -1078,7 +1077,7 @@
     field public static final int wallpaperIntraOpenExitAnimation = 16843416; // 0x1010298
     field public static final int wallpaperOpenEnterAnimation = 16843411; // 0x1010293
     field public static final int wallpaperOpenExitAnimation = 16843412; // 0x1010294
-    field public static final int waveDrawable = 16843656; // 0x1010388
+    field public static final int waveDrawable = 16843655; // 0x1010387
     field public static final int webTextViewStyle = 16843449; // 0x10102b9
     field public static final int webViewStyle = 16842885; // 0x1010085
     field public static final int weekDayTextAppearance = 16843592; // 0x1010348
@@ -5771,6 +5770,7 @@
     ctor public SyncAdapterType(android.os.Parcel);
     method public boolean allowParallelSyncs();
     method public int describeContents();
+    method public java.lang.String getSettingsActivity();
     method public boolean isAlwaysSyncable();
     method public boolean isUserVisible();
     method public static android.content.SyncAdapterType newKey(java.lang.String, java.lang.String);
@@ -8721,7 +8721,6 @@
 
   public class SurfaceTexture {
     ctor public SurfaceTexture(int);
-    ctor public SurfaceTexture(int, boolean);
     method public long getTimestamp();
     method public void getTransformMatrix(float[]);
     method public void release();
@@ -11691,6 +11690,7 @@
     method public static long getUidUdpRxPackets(int);
     method public static long getUidUdpTxBytes(int);
     method public static long getUidUdpTxPackets(int);
+    method public static void incrementOperationCount(int);
     method public static void incrementOperationCount(int, int);
     method public static void setThreadStatsTag(int);
     method public static deprecated void setThreadStatsTag(java.lang.String);
@@ -13975,6 +13975,7 @@
   }
 
   public final class GLUtils {
+    method public static java.lang.String getEGLErrorString(int);
     method public static int getInternalFormat(android.graphics.Bitmap);
     method public static int getType(android.graphics.Bitmap);
     method public static void texImage2D(int, int, int, android.graphics.Bitmap, int);
@@ -15459,6 +15460,7 @@
     field public static final java.lang.String AUTHORITY = "com.android.calendar";
     field public static final java.lang.String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
     field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String EXTRA_EVENT_ALL_DAY = "allDay";
     field public static final java.lang.String EXTRA_EVENT_BEGIN_TIME = "beginTime";
     field public static final java.lang.String EXTRA_EVENT_END_TIME = "endTime";
   }
@@ -16685,6 +16687,7 @@
     field public static final java.lang.String ACCOUNT_NAME = "account_name";
     field public static final java.lang.String ACCOUNT_TYPE = "account_type";
     field public static final java.lang.String COMMENTS = "comments";
+    field public static final java.lang.String CONTACT_ID = "contact_id";
     field public static final java.lang.String DATA_SET = "data_set";
     field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id";
     field public static final java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id";
@@ -17144,14 +17147,14 @@
     field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname";
     field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version";
     field public static final java.lang.String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
-    field public static final java.lang.String TTS_DEFAULT_COUNTRY = "tts_default_country";
-    field public static final java.lang.String TTS_DEFAULT_LANG = "tts_default_lang";
+    field public static final deprecated java.lang.String TTS_DEFAULT_COUNTRY = "tts_default_country";
+    field public static final deprecated java.lang.String TTS_DEFAULT_LANG = "tts_default_lang";
     field public static final java.lang.String TTS_DEFAULT_PITCH = "tts_default_pitch";
     field public static final java.lang.String TTS_DEFAULT_RATE = "tts_default_rate";
     field public static final java.lang.String TTS_DEFAULT_SYNTH = "tts_default_synth";
-    field public static final java.lang.String TTS_DEFAULT_VARIANT = "tts_default_variant";
+    field public static final deprecated java.lang.String TTS_DEFAULT_VARIANT = "tts_default_variant";
     field public static final java.lang.String TTS_ENABLED_PLUGINS = "tts_enabled_plugins";
-    field public static final java.lang.String TTS_USE_DEFAULTS = "tts_use_defaults";
+    field public static final deprecated java.lang.String TTS_USE_DEFAULTS = "tts_use_defaults";
     field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
     field public static final java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
     field public static final java.lang.String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
@@ -20811,6 +20814,7 @@
     method public java.lang.String getLocale();
     method public int getSpanTypeId();
     method public java.lang.String[] getSuggestions();
+    method public void setFlags(int);
     method public void updateDrawState(android.text.TextPaint);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final java.lang.String ACTION_SUGGESTION_PICKED = "android.text.style.SUGGESTION_PICKED";
@@ -24490,6 +24494,7 @@
     method public android.content.ComponentName getComponent();
     method public java.lang.String getId();
     method public java.lang.String getPackageName();
+    method public android.content.pm.ServiceInfo getServiceInfo();
     method public java.lang.String getSettingsActivity();
     method public android.view.textservice.SpellCheckerSubtype getSubtypeAt(int);
     method public int getSubtypeCount();
@@ -24515,6 +24520,7 @@
   public final class SpellCheckerSubtype implements android.os.Parcelable {
     ctor public SpellCheckerSubtype(int, java.lang.String, java.lang.String);
     method public int describeContents();
+    method public java.lang.CharSequence getDisplayName(android.content.Context, java.lang.String, android.content.pm.ApplicationInfo);
     method public java.lang.String getExtraValue();
     method public java.lang.String getLocale();
     method public int getNameResId();
@@ -27131,7 +27137,6 @@
     method public void setSingleLine();
     method public void setSingleLine(boolean);
     method public final void setSpannableFactory(android.text.Spannable.Factory);
-    method public void setSuggestionsEnabled(boolean);
     method public final void setText(java.lang.CharSequence);
     method public void setText(java.lang.CharSequence, android.widget.TextView.BufferType);
     method public final void setText(char[], int, int);
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 836cf15..0b08c5e 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -80,6 +80,9 @@
     dump_file("SLAB INFO", "/proc/slabinfo");
     dump_file("ZONEINFO", "/proc/zoneinfo");
     dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
+    dump_file("BUDDYINFO", "/proc/buddyinfo");
+    dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
+    run_command("QTAGUID STATS INFO", 10, "su", "root", "cat", "/proc/net/xt_qtaguid/stats", NULL);
 
     if (screenshot_path[0]) {
         LOGI("taking screenshot\n");
@@ -114,8 +117,10 @@
     dump_file("NETWORK ROUTES", "/proc/net/route");
     dump_file("NETWORK ROUTES IPV6", "/proc/net/ipv6_route");
     dump_file("ARP CACHE", "/proc/net/arp");
-    run_command("IPTABLES", 10, "su", "root", "iptables", "-L", "-n", NULL);
+    run_command("IPTABLES", 10, "su", "root", "iptables", "-L", "-nvx", NULL);
+    run_command("IP6TABLES", 10, "su", "root", "ip6tables", "-L", "-nvx", NULL);
     run_command("IPTABLE NAT", 10, "su", "root", "iptables", "-t", "nat", "-L", "-n", NULL);
+    run_command("IPT6ABLE NAT", 10, "su", "root", "ip6tables", "-t", "nat", "-L", "-n", NULL);
 
     run_command("WIFI NETWORKS", 20,
             "su", "root", "wpa_cli", "list_networks", NULL);
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index ee91c29..aa3bc03 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "stream"
+#include "utils/Log.h"
+
 #include <binder/ProcessState.h>
 
 #include <media/IStreamSource.h>
@@ -50,7 +54,7 @@
 private:
     int mFd;
     off64_t mFileSize;
-    int64_t mNextSeekTimeUs;
+    uint64_t mNumPacketsSent;
 
     sp<IStreamListener> mListener;
     Vector<sp<IMemory> > mBuffers;
@@ -61,7 +65,7 @@
 MyStreamSource::MyStreamSource(int fd)
     : mFd(fd),
       mFileSize(0),
-      mNextSeekTimeUs(-1) {  // ALooper::GetNowUs() + 5000000ll) {
+      mNumPacketsSent(0) {
     CHECK_GE(fd, 0);
 
     mFileSize = lseek64(fd, 0, SEEK_END);
@@ -84,18 +88,24 @@
 void MyStreamSource::onBufferAvailable(size_t index) {
     CHECK_LT(index, mBuffers.size());
 
-    if (mNextSeekTimeUs >= 0 && mNextSeekTimeUs <= ALooper::GetNowUs()) {
-        off64_t offset = (off64_t)(((float)rand() / RAND_MAX) * mFileSize * 0.8);
-        offset = (offset / 188) * 188;
+#if 0
+    if (mNumPacketsSent >= 20000) {
+        LOGI("signalling discontinuity now");
+
+        off64_t offset = 0;
+        CHECK((offset % 188) == 0);
 
         lseek(mFd, offset, SEEK_SET);
 
-        mListener->issueCommand(
-                IStreamListener::DISCONTINUITY, false /* synchronous */);
+        sp<AMessage> extra = new AMessage;
+        extra->setInt32(IStreamListener::kKeyFormatChange, 0);
 
-        mNextSeekTimeUs = -1;
-        mNextSeekTimeUs = ALooper::GetNowUs() + 5000000ll;
+        mListener->issueCommand(
+                IStreamListener::DISCONTINUITY, false /* synchronous */, extra);
+
+        mNumPacketsSent = 0;
     }
+#endif
 
     sp<IMemory> mem = mBuffers.itemAt(index);
 
@@ -104,6 +114,8 @@
         mListener->issueCommand(IStreamListener::EOS, false /* synchronous */);
     } else {
         mListener->queueBuffer(index, n);
+
+        mNumPacketsSent += n / 188;
     }
 }
 ////////////////////////////////////////////////////////////////////////////////
@@ -293,12 +305,17 @@
     sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
     CHECK_EQ(composerClient->initCheck(), (status_t)OK);
 
+    ssize_t displayWidth = composerClient->getDisplayWidth(0);
+    ssize_t displayHeight = composerClient->getDisplayHeight(0);
+
+    LOGV("display is %d x %d\n", displayWidth, displayHeight);
+
     sp<SurfaceControl> control =
         composerClient->createSurface(
                 String8("A Surface"),
                 0,
-                1280,
-                800,
+                displayWidth,
+                displayHeight,
                 PIXEL_FORMAT_RGB_565,
                 0);
 
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 8b4e7aee..7c41082 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -18,6 +18,7 @@
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
 
 /**
  * Interface given to an AccessibilitySerivce to talk to the AccessibilityManagerService.
@@ -30,84 +31,79 @@
 
     /**
      * Finds an {@link AccessibilityNodeInfo} by accessibility id.
-     * <p>
-     *   <strong>
-     *     It is a client responsibility to recycle the received info by
-     *     calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
-     *     of multiple instances.
-     *   </strong>
-     * </p>
      *
      * @param accessibilityWindowId A unique window id.
      * @param accessibilityViewId A unique View accessibility id.
-     * @return The node info.
+     * @param interactionId The id of the interaction for matching with the callback result.
+     * @param callback Callback which to receive the result.
+     * @param threadId The id of the calling thread.
+     * @return The current window scale, where zero means a failure.
      */
-    AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
-        int accessibilityViewId);
+    float findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
+        int accessibilityViewId, int interactionId,
+        IAccessibilityInteractionConnectionCallback callback, long threadId);
 
     /**
      * Finds {@link AccessibilityNodeInfo}s by View text. The match is case
      * insensitive containment. The search is performed in the window whose
      * id is specified and starts from the View whose accessibility id is
      * specified.
-     * <p>
-     *   <strong>
-     *     It is a client responsibility to recycle the received infos by
-     *     calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
-     *     of multiple instances.
-     *   </strong>
-     * </p>
      *
      * @param text The searched text.
-     * @param accessibilityId The id of the view from which to start searching.
+     * @param accessibilityWindowId A unique window id.
+     * @param accessibilityViewId A unique View accessibility id from where to start the search.
      *        Use {@link android.view.View#NO_ID} to start from the root.
-     * @return A list of node info.
+     * @param interactionId The id of the interaction for matching with the callback result.
+     * @param callback Callback which to receive the result.
+     * @param threadId The id of the calling thread.
+     * @return The current window scale, where zero means a failure.
      */
-    List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(String text,
-        int accessibilityWindowId, int accessibilityViewId);
+    float findAccessibilityNodeInfosByViewText(String text, int accessibilityWindowId,
+        int accessibilityViewId, int interractionId,
+        IAccessibilityInteractionConnectionCallback callback, long threadId);
 
     /**
      * Finds {@link AccessibilityNodeInfo}s by View text. The match is case
      * insensitive containment. The search is performed in the currently
      * active window and start from the root View in the window.
-     * <p>
-     *   <strong>
-     *     It is a client responsibility to recycle the received infos by
-     *     calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
-     *     of multiple instances.
-     *   </strong>
-     * </p>
      *
      * @param text The searched text.
      * @param accessibilityId The id of the view from which to start searching.
      *        Use {@link android.view.View#NO_ID} to start from the root.
-     * @return A list of node info.
+     * @param interactionId The id of the interaction for matching with the callback result.
+     * @param callback Callback which to receive the result.
+     * @param threadId The id of the calling thread.
+     * @return The current window scale, where zero means a failure.
      */
-    List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewTextInActiveWindow(String text);
+    float findAccessibilityNodeInfosByViewTextInActiveWindow(String text,
+        int interactionId, IAccessibilityInteractionConnectionCallback callback,
+        long threadId);
 
     /**
      * Finds an {@link AccessibilityNodeInfo} by View id. The search is performed
-     * in the currently active window and start from the root View in the window.
-     * <p>
-     *   <strong>
-     *     It is a client responsibility to recycle the received info by
-     *     calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
-     *     of multiple instances.
-     *   </strong>
-     * </p>
+     * in the currently active window and starts from the root View in the window.
      *
      * @param id The id of the node.
-     * @return The node info.
+     * @param interactionId The id of the interaction for matching with the callback result.
+     * @param callback Callback which to receive the result.
+     * @param threadId The id of the calling thread.
+     * @return The current window scale, where zero means a failure.
      */
-    AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int viewId);
+    float findAccessibilityNodeInfoByViewIdInActiveWindow(int viewId, int interactionId,
+        IAccessibilityInteractionConnectionCallback callback, long threadId);
 
     /**
      * Performs an accessibility action on an {@link AccessibilityNodeInfo}.
      *
      * @param accessibilityWindowId The id of the window.
-     * @param accessibilityViewId The of a view in the .
+     * @param accessibilityViewId A unique View accessibility id.
+     * @param action The action to perform.
+     * @param interactionId The id of the interaction for matching with the callback result.
+     * @param callback Callback which to receive the result.
+     * @param threadId The id of the calling thread.
      * @return Whether the action was performed.
      */
     boolean performAccessibilityAction(int accessibilityWindowId, int accessibilityViewId,
-        int action);
+        int action, int interactionId, IAccessibilityInteractionConnectionCallback callback,
+        long threadId);
 }
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 93e30af..102fac1 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -235,6 +235,24 @@
     }
 
     /**
+     * Use to decide whether the running device can be considered a "large
+     * RAM" device.  Exactly what memory limit large RAM is will vary, but
+     * it essentially means there is plenty of RAM to have lots of background
+     * processes running under decent loads.
+     * @hide
+     */
+    static public boolean isLargeRAM() {
+        MemInfoReader reader = new MemInfoReader();
+        reader.readMemInfo();
+        if (reader.getTotalSize() >= (640*1024*1024)) {
+            // Currently 640MB RAM available to the kernel is the point at
+            // which we have plenty of RAM to spare.
+            return true;
+        }
+        return false;
+    }
+
+    /**
      * Information you can retrieve about tasks that the user has most recently
      * started or visited.
      */
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 6fb7965..e3075d7 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1943,7 +1943,6 @@
         // we are back active so skip it.
         unscheduleGcIdler();
 
-        Slog.i(TAG, "Launch: profileFd=" + r.profileFile + " stop=" + r.autoStopProfiler);
         if (r.profileFd != null) {
             mBoundApplication.setProfiler(r.profileFile, r.profileFd);
             mBoundApplication.startProfiling();
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index ff04757..f81ea81 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -107,19 +107,22 @@
         private final int mHeight;
         private int mDrawLeft;
         private int mDrawTop;
+        private final Paint mPaint;
 
         private FastBitmapDrawable(Bitmap bitmap) {
             mBitmap = bitmap;
             mWidth = bitmap.getWidth();
             mHeight = bitmap.getHeight();
+
             setBounds(0, 0, mWidth, mHeight);
+
+            mPaint = new Paint();
+            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
         }
 
         @Override
         public void draw(Canvas canvas) {
-            Paint paint = new Paint();
-            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
-            canvas.drawBitmap(mBitmap, mDrawLeft, mDrawTop, paint);
+            canvas.drawBitmap(mBitmap, mDrawLeft, mDrawTop, mPaint);
         }
 
         @Override
@@ -134,33 +137,23 @@
         }
 
         @Override
-        public void setBounds(Rect bounds) {
-            // TODO Auto-generated method stub
-            super.setBounds(bounds);
-        }
-
-        @Override
         public void setAlpha(int alpha) {
-            throw new UnsupportedOperationException(
-                    "Not supported with this drawable");
+            throw new UnsupportedOperationException("Not supported with this drawable");
         }
 
         @Override
         public void setColorFilter(ColorFilter cf) {
-            throw new UnsupportedOperationException(
-                    "Not supported with this drawable");
+            throw new UnsupportedOperationException("Not supported with this drawable");
         }
 
         @Override
         public void setDither(boolean dither) {
-            throw new UnsupportedOperationException(
-                    "Not supported with this drawable");
+            throw new UnsupportedOperationException("Not supported with this drawable");
         }
 
         @Override
         public void setFilterBitmap(boolean filter) {
-            throw new UnsupportedOperationException(
-                    "Not supported with this drawable");
+            throw new UnsupportedOperationException("Not supported with this drawable");
         }
 
         @Override
@@ -230,7 +223,7 @@
                 }
                 mWallpaper = null;
                 try {
-                    mWallpaper = getCurrentWallpaperLocked(context);
+                    mWallpaper = getCurrentWallpaperLocked();
                 } catch (OutOfMemoryError e) {
                     Log.w(TAG, "No memory load current wallpaper", e);
                 }
@@ -253,7 +246,7 @@
             }
         }
 
-        private Bitmap getCurrentWallpaperLocked(Context context) {
+        private Bitmap getCurrentWallpaperLocked() {
             try {
                 Bundle params = new Bundle();
                 ParcelFileDescriptor fd = mService.getWallpaper(this, params);
@@ -265,17 +258,19 @@
                         BitmapFactory.Options options = new BitmapFactory.Options();
                         Bitmap bm = BitmapFactory.decodeFileDescriptor(
                                 fd.getFileDescriptor(), null, options);
-                        return generateBitmap(context, bm, width, height);
+                        return generateBitmap(bm, width, height);
                     } catch (OutOfMemoryError e) {
                         Log.w(TAG, "Can't decode file", e);
                     } finally {
                         try {
                             fd.close();
                         } catch (IOException e) {
+                            // Ignore
                         }
                     }
                 }
             } catch (RemoteException e) {
+                // Ignore
             }
             return null;
         }
@@ -291,27 +286,29 @@
                     try {
                         BitmapFactory.Options options = new BitmapFactory.Options();
                         Bitmap bm = BitmapFactory.decodeStream(is, null, options);
-                        return generateBitmap(context, bm, width, height);
+                        return generateBitmap(bm, width, height);
                     } catch (OutOfMemoryError e) {
                         Log.w(TAG, "Can't decode stream", e);
                     } finally {
                         try {
                             is.close();
                         } catch (IOException e) {
+                            // Ignore
                         }
                     }
                 }
             } catch (RemoteException e) {
+                // Ignore
             }
             return null;
         }
     }
     
-    private static Object mSync = new Object();
+    private static final Object sSync = new Object[0];
     private static Globals sGlobals;
 
     static void initGlobals(Looper looper) {
-        synchronized (mSync) {
+        synchronized (sSync) {
             if (sGlobals == null) {
                 sGlobals = new Globals(looper);
             }
@@ -390,8 +387,7 @@
     public Drawable getFastDrawable() {
         Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true);
         if (bm != null) {
-            Drawable dr = new FastBitmapDrawable(bm);
-            return dr;
+            return new FastBitmapDrawable(bm);
         }
         return null;
     }
@@ -406,13 +402,21 @@
     public Drawable peekFastDrawable() {
         Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
         if (bm != null) {
-            Drawable dr = new FastBitmapDrawable(bm);
-            return dr;
+            return new FastBitmapDrawable(bm);
         }
         return null;
     }
 
     /**
+     * Like {@link #getDrawable()} but returns a Bitmap.
+     * 
+     * @hide
+     */
+    public Bitmap getBitmap() {
+        return sGlobals.peekWallpaperBitmap(mContext, true);
+    }
+
+    /**
      * Remove all internal references to the last loaded wallpaper.  Useful
      * for apps that want to reduce memory usage when they only temporarily
      * need to have the wallpaper.  After calling, the next request for the
@@ -464,6 +468,7 @@
                 }
             }
         } catch (RemoteException e) {
+            // Ignore
         }
     }
     
@@ -493,6 +498,7 @@
                 }
             }
         } catch (RemoteException e) {
+            // Ignore
         }
     }
 
@@ -524,6 +530,7 @@
                 }
             }
         } catch (RemoteException e) {
+            // Ignore
         }
     }
 
@@ -594,6 +601,7 @@
         try {
             sGlobals.mService.setDimensionHints(minimumWidth, minimumHeight);
         } catch (RemoteException e) {
+            // Ignore
         }
     }
     
@@ -690,7 +698,7 @@
         setResource(com.android.internal.R.drawable.default_wallpaper);
     }
     
-    static Bitmap generateBitmap(Context context, Bitmap bm, int width, int height) {
+    static Bitmap generateBitmap(Bitmap bm, int width, int height) {
         if (bm == null) {
             return null;
         }
@@ -717,7 +725,7 @@
 
             if (deltaw > 0 || deltah > 0) {
                 // We need to scale up so it covers the entire area.
-                float scale = 1.0f;
+                float scale;
                 if (deltaw > deltah) {
                     scale = width / (float)targetRect.right;
                 } else {
diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java
index fcc19a2..6bffed7 100644
--- a/core/java/android/content/AbstractThreadedSyncAdapter.java
+++ b/core/java/android/content/AbstractThreadedSyncAdapter.java
@@ -34,6 +34,51 @@
  * If a cancelSync() is received that matches an existing sync operation then the thread
  * that is running that sync operation will be interrupted, which will indicate to the thread
  * that the sync has been canceled.
+ * <p>
+ * In order to be a sync adapter one must extend this class, provide implementations for the
+ * abstract methods and write a service that returns the result of {@link #getSyncAdapterBinder()}
+ * in the service's {@link android.app.Service#onBind(android.content.Intent)} when invoked
+ * with an intent with action <code>android.content.SyncAdapter</code>. This service
+ * must specify the following intent filter and metadata tags in its AndroidManifest.xml file
+ * <pre>
+ *   &lt;intent-filter&gt;
+ *     &lt;action android:name="android.content.SyncAdapter" /&gt;
+ *   &lt;/intent-filter&gt;
+ *   &lt;meta-data android:name="android.content.SyncAdapter"
+ *             android:resource="@xml/syncadapter" /&gt;
+ * </pre>
+ * The <code>android:resource</code> attribute must point to a resource that looks like:
+ * <pre>
+ * &lt;sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
+ *    android:contentAuthority="authority"
+ *    android:accountType="accountType"
+ *    android:userVisible="true|false"
+ *    android:supportsUploading="true|false"
+ *    android:allowParallelSyncs="true|false"
+ *    android:isAlwaysSyncable="true|false"
+ *    android:syncAdapterSettingsAction="ACTION_OF_SETTINGS_ACTIVITY"
+ * /&gt;
+ * </pre>
+ * <ul>
+ * <li>The <code>android:contentAuthority</code> and <code>android:accountType</code> attributes
+ * indicate which content authority and for which account types this sync adapter serves.
+ * <li><code>android:userVisible</code> defaults to true and controls whether or not this sync
+ * adapter shows up in the Sync Settings screen.
+ * <li><code>android:supportsUploading</code> defaults
+ * to true and if true an upload-only sync will be requested for all syncadapters associated
+ * with an authority whenever that authority's content provider does a
+ * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}
+ * with syncToNetwork set to true.
+ * <li><code>android:allowParallelSyncs</code> defaults to false and if true indicates that
+ * the sync adapter can handle syncs for multiple accounts at the same time. Otherwise
+ * the SyncManager will wait until the sync adapter is not in use before requesting that
+ * it sync an account's data.
+ * <li><code>android:isAlwaysSyncable</code> defaults to false and if true tells the SyncManager
+ * to intialize the isSyncable state to 1 for that sync adapter for each account that is added.
+ * <li><code>android:syncAdapterSettingsAction</code> defaults to null and if supplied it
+ * specifies an Intent action of an activity that can be used to adjust the sync adapter's
+ * sync settings. The activity must live in the same package as the sync adapter.
+ * </ul>
  */
 public abstract class AbstractThreadedSyncAdapter {
     /**
diff --git a/core/java/android/content/SyncAdapterType.java b/core/java/android/content/SyncAdapterType.java
index b85346e..8a16ac9 100644
--- a/core/java/android/content/SyncAdapterType.java
+++ b/core/java/android/content/SyncAdapterType.java
@@ -32,6 +32,7 @@
     private final boolean supportsUploading;
     private final boolean isAlwaysSyncable;
     private final boolean allowParallelSyncs;
+    private final String settingsActivity;
 
     public SyncAdapterType(String authority, String accountType, boolean userVisible,
             boolean supportsUploading) {
@@ -47,6 +48,7 @@
         this.supportsUploading = supportsUploading;
         this.isAlwaysSyncable = false;
         this.allowParallelSyncs = false;
+        this.settingsActivity = null;
         this.isKey = false;
     }
 
@@ -54,7 +56,8 @@
     public SyncAdapterType(String authority, String accountType, boolean userVisible,
             boolean supportsUploading,
             boolean isAlwaysSyncable,
-            boolean allowParallelSyncs) {
+            boolean allowParallelSyncs,
+            String settingsActivity) {
         if (TextUtils.isEmpty(authority)) {
             throw new IllegalArgumentException("the authority must not be empty: " + authority);
         }
@@ -67,6 +70,7 @@
         this.supportsUploading = supportsUploading;
         this.isAlwaysSyncable = isAlwaysSyncable;
         this.allowParallelSyncs = allowParallelSyncs;
+        this.settingsActivity = settingsActivity;
         this.isKey = false;
     }
 
@@ -83,6 +87,7 @@
         this.supportsUploading = true;
         this.isAlwaysSyncable = false;
         this.allowParallelSyncs = false;
+        this.settingsActivity = null;
         this.isKey = true;
     }
 
@@ -131,6 +136,18 @@
         return isAlwaysSyncable;
     }
 
+    /**
+     * @return The activity to use to invoke this SyncAdapter's settings activity.
+     * May be null.
+     */
+    public String getSettingsActivity() {
+        if (isKey) {
+            throw new IllegalStateException(
+                    "this method is not allowed to be called when this is a key");
+        }
+        return settingsActivity;
+    }
+
     public static SyncAdapterType newKey(String authority, String accountType) {
         return new SyncAdapterType(authority, accountType);
     }
@@ -163,6 +180,7 @@
                     + ", supportsUploading=" + supportsUploading
                     + ", isAlwaysSyncable=" + isAlwaysSyncable
                     + ", allowParallelSyncs=" + allowParallelSyncs
+                    + ", settingsActivity=" + settingsActivity
                     + "}";
         }
     }
@@ -182,6 +200,7 @@
         dest.writeInt(supportsUploading ? 1 : 0);
         dest.writeInt(isAlwaysSyncable ? 1 : 0);
         dest.writeInt(allowParallelSyncs ? 1 : 0);
+        dest.writeString(settingsActivity);
     }
 
     public SyncAdapterType(Parcel source) {
@@ -191,7 +210,8 @@
                 source.readInt() != 0,
                 source.readInt() != 0,
                 source.readInt() != 0,
-                source.readInt() != 0);
+                source.readInt() != 0,
+                source.readString());
     }
 
     public static final Creator<SyncAdapterType> CREATOR = new Creator<SyncAdapterType>() {
diff --git a/core/java/android/content/SyncAdaptersCache.java b/core/java/android/content/SyncAdaptersCache.java
index 33a713b..7b643a0 100644
--- a/core/java/android/content/SyncAdaptersCache.java
+++ b/core/java/android/content/SyncAdaptersCache.java
@@ -66,8 +66,11 @@
             final boolean allowParallelSyncs =
                     sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_allowParallelSyncs,
                             false);
+            final String settingsActivity =
+                    sa.getString(com.android.internal.R.styleable
+                            .SyncAdapter_settingsActivity);
             return new SyncAdapterType(authority, accountType, userVisible, supportsUploading,
-		    isAlwaysSyncable, allowParallelSyncs);
+                    isAlwaysSyncable, allowParallelSyncs, settingsActivity);
         } finally {
             sa.recycle();
         }
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index a00f790..5c3a17a 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -345,7 +345,6 @@
             sb.append(" (no locale)");
         }
         switch (textLayoutDirection) {
-            case LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE: sb.append(" ?layoutdir"); break;
             case LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE: sb.append(" rtl"); break;
             default: sb.append(" layoutdir="); sb.append(textLayoutDirection); break;
         }
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index a41a330..bc45945 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -2328,7 +2328,7 @@
          * <p>The reference code is as follows.
          *
 	 * <pre>
-         * public void public void onOrientationChanged(int orientation) {
+         * public void onOrientationChanged(int orientation) {
          *     if (orientation == ORIENTATION_UNKNOWN) return;
          *     android.hardware.Camera.CameraInfo info =
          *            new android.hardware.Camera.CameraInfo();
diff --git a/core/java/android/net/DnsPinger.java b/core/java/android/net/DnsPinger.java
index 6115fef..3e27b0d 100644
--- a/core/java/android/net/DnsPinger.java
+++ b/core/java/android/net/DnsPinger.java
@@ -67,7 +67,7 @@
     private final Context mContext;
     private final int mConnectionType;
     private final Handler mTarget;
-    private final InetAddress mDefaultDns;
+    private final ArrayList<InetAddress> mDefaultDns;
     private String TAG;
 
     private static final int BASE = Protocol.BASE_DNS_PINGER;
@@ -113,7 +113,8 @@
             throw new IllegalArgumentException("Invalid connectionType in constructor: "
                     + connectionType);
         }
-        mDefaultDns = getDefaultDns();
+        mDefaultDns = new ArrayList<InetAddress>();
+        mDefaultDns.add(getDefaultDns());
         mEventCounter = 0;
     }
 
@@ -213,17 +214,16 @@
                 for (ActivePing activePing : mActivePings)
                     activePing.socket.close();
                 mActivePings.clear();
-                removeMessages(ACTION_PING_DNS);
                 break;
         }
     }
 
     /**
-     * @return The first DNS in the link properties of the specified connection
-     *         type or the default system DNS if the link properties has null
-     *         dns set. Should not be null.
+     * Returns a list of DNS addresses, coming from either the link properties of the
+     * specified connection or the default system DNS if the link properties has no dnses.
+     * @return a non-empty non-null list
      */
-    public InetAddress getDns() {
+    public List<InetAddress> getDnsList() {
         LinkProperties curLinkProps = getCurrentLinkProperties();
         if (curLinkProps == null) {
             Slog.e(TAG, "getCurLinkProperties:: LP for type" + mConnectionType + " is null!");
@@ -236,7 +236,7 @@
             return mDefaultDns;
         }
 
-        return dnses.iterator().next();
+        return new ArrayList<InetAddress>(dnses);
     }
 
     /**
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 272545d..5b883a0 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -313,6 +313,22 @@
     }
 
     /**
+     * Return total bytes represented by this snapshot object, usually used when
+     * checking if a {@link #subtract(NetworkStats)} delta passes a threshold.
+     */
+    public long getTotalBytes() {
+        long totalBytes = 0;
+        for (int i = 0; i < size; i++) {
+            // skip specific tags, since already counted in TAG_NONE
+            if (tag[i] != TAG_NONE) continue;
+
+            totalBytes += rxBytes[i];
+            totalBytes += txBytes[i];
+        }
+        return totalBytes;
+    }
+
+    /**
      * Subtract the given {@link NetworkStats}, effectively leaving the delta
      * between two snapshots in time. Assumes that statistics rows collect over
      * time, and that none of them have disappeared.
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index b4f15ac..b19949e 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -53,18 +53,21 @@
 public class NetworkStatsHistory implements Parcelable {
     private static final int VERSION_INIT = 1;
     private static final int VERSION_ADD_PACKETS = 2;
+    private static final int VERSION_ADD_ACTIVE = 3;
 
-    public static final int FIELD_RX_BYTES = 0x01;
-    public static final int FIELD_RX_PACKETS = 0x02;
-    public static final int FIELD_TX_BYTES = 0x04;
-    public static final int FIELD_TX_PACKETS = 0x08;
-    public static final int FIELD_OPERATIONS = 0x10;
+    public static final int FIELD_ACTIVE_TIME = 0x01;
+    public static final int FIELD_RX_BYTES = 0x02;
+    public static final int FIELD_RX_PACKETS = 0x04;
+    public static final int FIELD_TX_BYTES = 0x08;
+    public static final int FIELD_TX_PACKETS = 0x10;
+    public static final int FIELD_OPERATIONS = 0x20;
 
     public static final int FIELD_ALL = 0xFFFFFFFF;
 
     private long bucketDuration;
     private int bucketCount;
     private long[] bucketStart;
+    private long[] activeTime;
     private long[] rxBytes;
     private long[] rxPackets;
     private long[] txBytes;
@@ -74,8 +77,9 @@
     public static class Entry {
         public static final long UNKNOWN = -1;
 
-        public long bucketStart;
         public long bucketDuration;
+        public long bucketStart;
+        public long activeTime;
         public long rxBytes;
         public long rxPackets;
         public long txBytes;
@@ -94,6 +98,7 @@
     public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) {
         this.bucketDuration = bucketDuration;
         bucketStart = new long[initialSize];
+        if ((fields & FIELD_ACTIVE_TIME) != 0) activeTime = new long[initialSize];
         if ((fields & FIELD_RX_BYTES) != 0) rxBytes = new long[initialSize];
         if ((fields & FIELD_RX_PACKETS) != 0) rxPackets = new long[initialSize];
         if ((fields & FIELD_TX_BYTES) != 0) txBytes = new long[initialSize];
@@ -105,6 +110,7 @@
     public NetworkStatsHistory(Parcel in) {
         bucketDuration = in.readLong();
         bucketStart = readLongArray(in);
+        activeTime = readLongArray(in);
         rxBytes = readLongArray(in);
         rxPackets = readLongArray(in);
         txBytes = readLongArray(in);
@@ -117,6 +123,7 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeLong(bucketDuration);
         writeLongArray(out, bucketStart, bucketCount);
+        writeLongArray(out, activeTime, bucketCount);
         writeLongArray(out, rxBytes, bucketCount);
         writeLongArray(out, rxPackets, bucketCount);
         writeLongArray(out, txBytes, bucketCount);
@@ -138,9 +145,12 @@
                 bucketCount = bucketStart.length;
                 break;
             }
-            case VERSION_ADD_PACKETS: {
+            case VERSION_ADD_PACKETS:
+            case VERSION_ADD_ACTIVE: {
                 bucketDuration = in.readLong();
                 bucketStart = readVarLongArray(in);
+                activeTime = (version >= VERSION_ADD_ACTIVE) ? readVarLongArray(in)
+                        : new long[bucketStart.length];
                 rxBytes = readVarLongArray(in);
                 rxPackets = readVarLongArray(in);
                 txBytes = readVarLongArray(in);
@@ -156,9 +166,10 @@
     }
 
     public void writeToStream(DataOutputStream out) throws IOException {
-        out.writeInt(VERSION_ADD_PACKETS);
+        out.writeInt(VERSION_ADD_ACTIVE);
         out.writeLong(bucketDuration);
         writeVarLongArray(out, bucketStart, bucketCount);
+        writeVarLongArray(out, activeTime, bucketCount);
         writeVarLongArray(out, rxBytes, bucketCount);
         writeVarLongArray(out, rxPackets, bucketCount);
         writeVarLongArray(out, txBytes, bucketCount);
@@ -202,6 +213,7 @@
         final Entry entry = recycle != null ? recycle : new Entry();
         entry.bucketStart = bucketStart[i];
         entry.bucketDuration = bucketDuration;
+        entry.activeTime = getLong(activeTime, i, UNKNOWN);
         entry.rxBytes = getLong(rxBytes, i, UNKNOWN);
         entry.rxPackets = getLong(rxPackets, i, UNKNOWN);
         entry.txBytes = getLong(txBytes, i, UNKNOWN);
@@ -252,8 +264,9 @@
             final long fracRxPackets = entry.rxPackets * overlap / duration;
             final long fracTxBytes = entry.txBytes * overlap / duration;
             final long fracTxPackets = entry.txPackets * overlap / duration;
-            final int fracOperations = (int) (entry.operations * overlap / duration);
+            final long fracOperations = entry.operations * overlap / duration;
 
+            addLong(activeTime, i, overlap);
             addLong(rxBytes, i, fracRxBytes); entry.rxBytes -= fracRxBytes;
             addLong(rxPackets, i, fracRxPackets); entry.rxPackets -= fracRxPackets;
             addLong(txBytes, i, fracTxBytes); entry.txBytes -= fracTxBytes;
@@ -311,6 +324,7 @@
         if (bucketCount >= bucketStart.length) {
             final int newLength = Math.max(bucketStart.length, 10) * 3 / 2;
             bucketStart = Arrays.copyOf(bucketStart, newLength);
+            if (activeTime != null) activeTime = Arrays.copyOf(activeTime, newLength);
             if (rxBytes != null) rxBytes = Arrays.copyOf(rxBytes, newLength);
             if (rxPackets != null) rxPackets = Arrays.copyOf(rxPackets, newLength);
             if (txBytes != null) txBytes = Arrays.copyOf(txBytes, newLength);
@@ -324,6 +338,7 @@
             final int length = bucketCount - index;
 
             System.arraycopy(bucketStart, index, bucketStart, dstPos, length);
+            if (activeTime != null) System.arraycopy(activeTime, index, activeTime, dstPos, length);
             if (rxBytes != null) System.arraycopy(rxBytes, index, rxBytes, dstPos, length);
             if (rxPackets != null) System.arraycopy(rxPackets, index, rxPackets, dstPos, length);
             if (txBytes != null) System.arraycopy(txBytes, index, txBytes, dstPos, length);
@@ -332,6 +347,7 @@
         }
 
         bucketStart[index] = start;
+        setLong(activeTime, index, 0L);
         setLong(rxBytes, index, 0L);
         setLong(rxPackets, index, 0L);
         setLong(txBytes, index, 0L);
@@ -357,6 +373,7 @@
         if (i > 0) {
             final int length = bucketStart.length;
             bucketStart = Arrays.copyOfRange(bucketStart, i, length);
+            if (activeTime != null) activeTime = Arrays.copyOfRange(activeTime, i, length);
             if (rxBytes != null) rxBytes = Arrays.copyOfRange(rxBytes, i, length);
             if (rxPackets != null) rxPackets = Arrays.copyOfRange(rxPackets, i, length);
             if (txBytes != null) txBytes = Arrays.copyOfRange(txBytes, i, length);
@@ -380,8 +397,9 @@
      */
     public Entry getValues(long start, long end, long now, Entry recycle) {
         final Entry entry = recycle != null ? recycle : new Entry();
-        entry.bucketStart = start;
         entry.bucketDuration = end - start;
+        entry.bucketStart = start;
+        entry.activeTime = activeTime != null ? 0 : UNKNOWN;
         entry.rxBytes = rxBytes != null ? 0 : UNKNOWN;
         entry.rxPackets = rxPackets != null ? 0 : UNKNOWN;
         entry.txBytes = txBytes != null ? 0 : UNKNOWN;
@@ -404,6 +422,7 @@
             if (overlap <= 0) continue;
 
             // integer math each time is faster than floating point
+            if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketDuration;
             if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketDuration;
             if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketDuration;
             if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketDuration;
@@ -463,6 +482,7 @@
         for (int i = start; i < bucketCount; i++) {
             pw.print(prefix);
             pw.print("  bucketStart="); pw.print(bucketStart[i]);
+            if (activeTime != null) pw.print(" activeTime="); pw.print(activeTime[i]);
             if (rxBytes != null) pw.print(" rxBytes="); pw.print(rxBytes[i]);
             if (rxPackets != null) pw.print(" rxPackets="); pw.print(rxPackets[i]);
             if (txBytes != null) pw.print(" txBytes="); pw.print(txBytes[i]);
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index c2c5c18..ec3b1e1 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -198,6 +198,18 @@
     }
 
     /**
+     * Increment count of network operations performed under the accounting tag
+     * currently active on the calling thread. This can be used to derive
+     * bytes-per-operation.
+     *
+     * @param operationCount Number of operations to increment count by.
+     */
+    public static void incrementOperationCount(int operationCount) {
+        final int tag = getThreadStatsTag();
+        incrementOperationCount(tag, operationCount);
+    }
+
+    /**
      * Increment count of network operations performed under the given
      * accounting tag. This can be used to derive bytes-per-operation.
      *
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index 5b29103..6fe5124 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -110,6 +110,12 @@
     public static final String EXTRA_EVENT_END_TIME = "endTime";
 
     /**
+     * Intent Extras key: When creating an event, set this to true to create an
+     * all-day event by default
+     */
+    public static final String EXTRA_EVENT_ALL_DAY = "allDay";
+
+    /**
      * This authority is used for writing to or querying from the calendar
      * provider. Note: This is set at first run and cannot be changed without
      * breaking apps that access the provider.
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index c5a924b..886edaf 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -202,6 +202,42 @@
         public static final String GEOCODED_LOCATION = "geocoded_location";
 
         /**
+         * The cached URI to look up the contact associated with the phone number, if it exists.
+         * This value is not guaranteed to be current, if the contact information
+         * associated with this number has changed.
+         * <P>Type: TEXT</P>
+         * @hide
+         */
+        public static final String CACHED_LOOKUP_URI = "lookup_uri";
+
+        /**
+         * The cached phone number of the contact which matches this entry, if it exists.
+         * This value is not guaranteed to be current, if the contact information
+         * associated with this number has changed.
+         * <P>Type: TEXT</P>
+         * @hide
+         */
+        public static final String CACHED_MATCHED_NUMBER = "matched_number";
+
+        /**
+         * The cached normalized version of the phone number, if it exists.
+         * This value is not guaranteed to be current, if the contact information
+         * associated with this number has changed.
+         * <P>Type: TEXT</P>
+         * @hide
+         */
+        public static final String CACHED_NORMALIZED_NUMBER = "normalized_number";
+
+        /**
+         * The cached photo id of the picture associated with the phone number, if it exists.
+         * This value is not guaranteed to be current, if the contact information
+         * associated with this number has changed.
+         * <P>Type: INTEGER (long)</P>
+         * @hide
+         */
+        public static final String CACHED_PHOTO_ID = "photo_id";
+
+        /**
          * Adds a call to the call log.
          *
          * @param ci the CallerInfo object to get the target contact from.  Can be null
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index a66fa81..e205f97 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -2692,6 +2692,7 @@
                 ContentValues cv = new ContentValues();
                 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, ACCOUNT_NAME);
                 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, ACCOUNT_TYPE);
+                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, DATA_SET);
                 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, _ID);
                 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, DIRTY);
                 DatabaseUtils.cursorLongToContentValuesIfPresent(cursor, cv, VERSION);
@@ -3059,6 +3060,12 @@
      */
     protected interface StreamItemsColumns {
         /**
+         * A reference to the {@link android.provider.ContactsContract.Contacts#_ID}
+         * that this stream item belongs to.
+         */
+        public static final String CONTACT_ID = "contact_id";
+
+        /**
          * A reference to the {@link RawContacts#_ID}
          * that this stream item belongs to.
          */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 15c57e6..0c791e1 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -38,6 +38,7 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.SystemProperties;
+import android.speech.tts.TextToSpeech;
 import android.text.TextUtils;
 import android.util.AndroidException;
 import android.util.Log;
@@ -1062,7 +1063,7 @@
         public static void clearConfiguration(Configuration inoutConfig) {
             inoutConfig.fontScale = 0;
         }
-        
+
         /**
          * Convenience function to write a batch of configuration-related
          * settings from a {@link Configuration} object.
@@ -2781,7 +2782,11 @@
          * of the application settings.
          * 1 = override application settings,
          * 0 = use application settings (if specified).
+         *
+         * @deprecated  The value of this setting is no longer respected by
+         * the framework text to speech APIs as of the Ice Cream Sandwich release.
          */
+        @Deprecated
         public static final String TTS_USE_DEFAULTS = "tts_use_defaults";
 
         /**
@@ -2801,24 +2806,46 @@
 
         /**
          * Default text-to-speech language.
+         *
+         * @deprecated this setting is no longer in use, as of the Ice Cream
+         * Sandwich release. Apps should never need to read this setting directly,
+         * instead can query the TextToSpeech framework classes for the default
+         * locale. {@link TextToSpeech#getLanguage()}.
          */
+        @Deprecated
         public static final String TTS_DEFAULT_LANG = "tts_default_lang";
 
         /**
          * Default text-to-speech country.
+         *
+         * @deprecated this setting is no longer in use, as of the Ice Cream
+         * Sandwich release. Apps should never need to read this setting directly,
+         * instead can query the TextToSpeech framework classes for the default
+         * locale. {@link TextToSpeech#getLanguage()}.
          */
+        @Deprecated
         public static final String TTS_DEFAULT_COUNTRY = "tts_default_country";
 
         /**
          * Default text-to-speech locale variant.
+         *
+         * @deprecated this setting is no longer in use, as of the Ice Cream
+         * Sandwich release. Apps should never need to read this setting directly,
+         * instead can query the TextToSpeech framework classes for the
+         * locale that is in use {@link TextToSpeech#getLanguage()}.
          */
+        @Deprecated
         public static final String TTS_DEFAULT_VARIANT = "tts_default_variant";
 
         /**
          * Stores the default tts locales on a per engine basis. Stored as
          * a comma seperated list of values, each value being of the form
          * {@code engine_name:locale} for example,
-         * {@code com.foo.ttsengine:eng-USA,com.bar.ttsengine:esp-ESP}.
+         * {@code com.foo.ttsengine:eng-USA,com.bar.ttsengine:esp-ESP}. This
+         * supersedes {@link #TTS_DEFAULT_LANG}, {@link #TTS_DEFAULT_COUNTRY} and
+         * {@link #TTS_DEFAULT_VARIANT}. Apps should never need to read this
+         * setting directly, and can query the TextToSpeech framework classes
+         * for the locale that is in use.
          *
          * @hide
          */
@@ -3785,6 +3812,13 @@
                 "selected_spell_checker_subtype";
 
         /**
+         * The {@link ComponentName} string whether spell checker is enabled or not.
+         *
+         * @hide
+         */
+        public static final String SPELL_CHECKER_ENABLED = "spell_checker_enabled";
+
+        /**
          * What happens when the user presses the Power button while in-call
          * and the screen is on.<br/>
          * <b>Values:</b><br/>
@@ -4007,6 +4041,7 @@
             TTS_DEFAULT_LANG,
             TTS_DEFAULT_COUNTRY,
             TTS_ENABLED_PLUGINS,
+            TTS_DEFAULT_LOCALE,
             WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
             WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
             WIFI_NUM_OPEN_NETWORKS_KEPT,
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 6bde802..5fed775 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -16,21 +16,18 @@
 
 package android.text;
 
-import com.android.internal.util.ArrayUtils;
-
 import android.graphics.Canvas;
 import android.graphics.Paint;
-import android.text.style.SuggestionSpan;
+
+import com.android.internal.util.ArrayUtils;
 
 import java.lang.reflect.Array;
 
 /**
  * This is the class for text whose content and markup can both be changed.
  */
-public class SpannableStringBuilder
-implements CharSequence, GetChars, Spannable, Editable, Appendable,
-           GraphicsOperations
-{
+public class SpannableStringBuilder implements CharSequence, GetChars, Spannable, Editable,
+        Appendable, GraphicsOperations {
     /**
      * Create a new SpannableStringBuilder with empty contents
      */
@@ -111,8 +108,7 @@
         if (where < 0) {
             throw new IndexOutOfBoundsException("charAt: " + where + " < 0");
         } else if (where >= len) {
-            throw new IndexOutOfBoundsException("charAt: " + where +
-                                                " >= length " + len);
+            throw new IndexOutOfBoundsException("charAt: " + where + " >= length " + len);
         }
 
         if (where >= mGapStart)
@@ -266,8 +262,7 @@
         return append(String.valueOf(text));
     }
 
-    private int change(int start, int end,
-                       CharSequence tb, int tbstart, int tbend) {
+    private int change(int start, int end, CharSequence tb, int tbstart, int tbend) {
         return change(true, start, end, tb, tbstart, tbend);
     }
 
@@ -277,8 +272,9 @@
         int ret = tbend - tbstart;
         TextWatcher[] recipients = null;
 
-        if (notify)
+        if (notify) {
             recipients = sendTextWillChange(start, end - start, tbend - tbstart);
+        }
 
         for (int i = mSpanCount - 1; i >= 0; i--) {
             if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) {
@@ -353,7 +349,6 @@
         // no need for span fixup on pure insertion
         if (tbend > tbstart && end - start == 0) {
             if (notify) {
-                removeSuggestionSpans(start, end);
                 sendTextChange(recipients, start, end - start, tbend - tbstart);
                 sendTextHasChanged(recipients);
             }
@@ -388,7 +383,6 @@
             if (mSpanEnds[i] < mSpanStarts[i]) {
                 removeSpan(i);
             }
-            removeSuggestionSpans(start, end);
         }
 
         if (notify) {
@@ -399,30 +393,26 @@
         return ret;
     }
 
-    /**
-     * Removes the SuggestionSpan that overlap the [start, end] range, and that would
-     * not make sense anymore after the change.
-     */
-    private void removeSuggestionSpans(int start, int end) {
-        for (int i = mSpanCount - 1; i >= 0; i--) {
-            final int spanEnd = mSpanEnds[i];
-            final int spanSpart = mSpanStarts[i];
-            if ((mSpans[i] instanceof SuggestionSpan) && (
-                    (spanSpart < start && spanEnd > start) ||
-                    (spanSpart < end && spanEnd > end))) {
-                removeSpan(i);
-            }
-        }
-    }
-
     private void removeSpan(int i) {
-        // XXX send notification on removal
-        System.arraycopy(mSpans, i + 1, mSpans, i, mSpanCount - (i + 1));
-        System.arraycopy(mSpanStarts, i + 1, mSpanStarts, i, mSpanCount - (i + 1));
-        System.arraycopy(mSpanEnds, i + 1, mSpanEnds, i, mSpanCount - (i + 1));
-        System.arraycopy(mSpanFlags, i + 1, mSpanFlags, i, mSpanCount - (i + 1));
+        Object object = mSpans[i];
+
+        int start = mSpanStarts[i];
+        int end = mSpanEnds[i];
+
+        if (start > mGapStart) start -= mGapLength;
+        if (end > mGapStart) end -= mGapLength;
+
+        int count = mSpanCount - (i + 1);
+        System.arraycopy(mSpans, i + 1, mSpans, i, count);
+        System.arraycopy(mSpanStarts, i + 1, mSpanStarts, i, count);
+        System.arraycopy(mSpanEnds, i + 1, mSpanEnds, i, count);
+        System.arraycopy(mSpanFlags, i + 1, mSpanFlags, i, count);
 
         mSpanCount--;
+
+        mSpans[mSpanCount] = null;
+
+        sendSpanRemoved(object, start, end);
     }
 
     // Documentation from interface
@@ -462,11 +452,10 @@
             moveGapTo(end);
             TextWatcher[] recipients;
 
-            recipients = sendTextWillChange(start, end - start,
-                                            tbend - tbstart);
-
             int origlen = end - start;
 
+            recipients = sendTextWillChange(start, origlen, tbend - tbstart);
+
             if (mGapLength < 2)
                 resizeFor(length() + 1);
 
@@ -486,11 +475,9 @@
                 new Exception("mGapLength < 1").printStackTrace();
             }
 
-            int oldlen = (end + 1) - start;
-
             int inserted = change(false, start + 1, start + 1, tb, tbstart, tbend);
             change(false, start, start + 1, "", 0, 0);
-            change(false, start + inserted, start + inserted + oldlen - 1, "", 0, 0);
+            change(false, start + inserted, start + inserted + origlen, "", 0, 0);
 
             /*
              * Special case to keep the cursor in the same position
@@ -515,13 +502,12 @@
                 off = off * inserted / (end - start);
                 selend = (int) off + start;
 
-                setSpan(false, Selection.SELECTION_END, selend, selend,
-                        Spanned.SPAN_POINT_POINT);
+                setSpan(false, Selection.SELECTION_END, selend, selend, Spanned.SPAN_POINT_POINT);
             }
-
             sendTextChange(recipients, start, origlen, inserted);
             sendTextHasChanged(recipients);
         }
+
         return this; 
     }
 
@@ -534,8 +520,7 @@
         setSpan(true, what, start, end, flags);
     }
 
-    private void setSpan(boolean send,
-                         Object what, int start, int end, int flags) {
+    private void setSpan(boolean send, Object what, int start, int end, int flags) {
         int nstart = start;
         int nend = end;
 
@@ -546,8 +531,7 @@
                 char c = charAt(start - 1);
 
                 if (c != '\n')
-                    throw new RuntimeException(
-                            "PARAGRAPH span must start at paragraph boundary");
+                    throw new RuntimeException("PARAGRAPH span must start at paragraph boundary");
             }
         }
 
@@ -556,23 +540,22 @@
                 char c = charAt(end - 1);
 
                 if (c != '\n')
-                    throw new RuntimeException(
-                            "PARAGRAPH span must end at paragraph boundary");
+                    throw new RuntimeException("PARAGRAPH span must end at paragraph boundary");
             }
         }
 
-        if (start > mGapStart)
+        if (start > mGapStart) {
             start += mGapLength;
-        else if (start == mGapStart) {
+        } else if (start == mGapStart) {
             int flag = (flags & START_MASK) >> START_SHIFT;
 
             if (flag == POINT || (flag == PARAGRAPH && start == length()))
                 start += mGapLength;
         }
 
-        if (end > mGapStart)
+        if (end > mGapStart) {
             end += mGapLength;
-        else if (end == mGapStart) {
+        } else if (end == mGapStart) {
             int flag = (flags & END_MASK);
 
             if (flag == POINT || (flag == PARAGRAPH && end == length()))
@@ -637,25 +620,7 @@
     public void removeSpan(Object what) {
         for (int i = mSpanCount - 1; i >= 0; i--) {
             if (mSpans[i] == what) {
-                int ostart = mSpanStarts[i];
-                int oend = mSpanEnds[i];
-
-                if (ostart > mGapStart)
-                    ostart -= mGapLength;
-                if (oend > mGapStart)
-                    oend -= mGapLength;
-
-                int count = mSpanCount - (i + 1);
-
-                System.arraycopy(mSpans, i + 1, mSpans, i, count);
-                System.arraycopy(mSpanStarts, i + 1, mSpanStarts, i, count);
-                System.arraycopy(mSpanEnds, i + 1, mSpanEnds, i, count);
-                System.arraycopy(mSpanFlags, i + 1, mSpanFlags, i, count);
-
-                mSpanCount--;
-                mSpans[mSpanCount] = null;
-
-                sendSpanRemoved(what, ostart, oend);
+                removeSpan(i);
                 return;
             }
         }
@@ -729,6 +694,8 @@
      */
     @SuppressWarnings("unchecked")
     public <T> T[] getSpans(int queryStart, int queryEnd, Class<T> kind) {
+        if (kind == null) return ArrayUtils.emptyArray(kind);
+
         int spanCount = mSpanCount;
         Object[] spans = mSpans;
         int[] starts = mSpanStarts;
@@ -742,6 +709,8 @@
         T ret1 = null;
 
         for (int i = 0; i < spanCount; i++) {
+            if (!kind.isInstance(spans[i])) continue;
+
             int spanStart = starts[i];
             int spanEnd = ends[i];
 
@@ -766,10 +735,6 @@
                     continue;
             }
 
-            if (kind != null && !kind.isInstance(spans[i])) {
-                continue;
-            }
-
             if (count == 0) {
                 // Safe conversion thanks to the isInstance test above
                 ret1 = (T) spans[i];
@@ -909,8 +874,7 @@
         return recip;
     }
 
-    private void sendTextChange(TextWatcher[] recip, int start, int before,
-                                int after) {
+    private void sendTextChange(TextWatcher[] recip, int start, int before, int after) {
         int n = recip.length;
 
         for (int i = 0; i < n; i++) {
@@ -945,8 +909,7 @@
     }
 
     private void sendSpanChanged(Object what, int s, int e, int st, int en) {
-        SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en),
-                                  SpanWatcher.class);
+        SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en), SpanWatcher.class);
         int n = recip.length;
 
         for (int i = 0; i < n; i++) {
diff --git a/core/java/android/text/TextDirectionHeuristics.java b/core/java/android/text/TextDirectionHeuristics.java
index 6debc6b..18b4040 100644
--- a/core/java/android/text/TextDirectionHeuristics.java
+++ b/core/java/android/text/TextDirectionHeuristics.java
@@ -17,6 +17,10 @@
 package android.text;
 
 
+import java.util.Locale;
+
+import android.util.LocaleUtil;
+
 /**
  * Some objects that implement TextDirectionHeuristic.
  * @hide
@@ -75,6 +79,11 @@
     public static final TextDirectionHeuristic CHARCOUNT_RTL =
         new TextDirectionHeuristicInternal(CharCount.INSTANCE_DEFAULT, true);
 
+    /**
+     * Force the paragraph direction to the Locale direction. Falls back to left to right.
+     */
+    public static final TextDirectionHeuristic LOCALE = TextDirectionHeuristicLocale.INSTANCE;
+
     private static enum TriState {
         TRUE, FALSE, UNKNOWN;
     }
@@ -300,4 +309,23 @@
         public static final float DEFAULT_THRESHOLD = 0.6f;
         public static final CharCount INSTANCE_DEFAULT = new CharCount(DEFAULT_THRESHOLD);
     }
+
+    /**
+     * Algorithm that uses the Locale direction to force the direction of a paragraph.
+     */
+    public static class TextDirectionHeuristicLocale extends TextDirectionHeuristicImpl {
+
+        public TextDirectionHeuristicLocale() {
+            super(null);
+        }
+
+        @Override
+        protected boolean defaultIsRtl() {
+            final int dir = LocaleUtil.getLayoutDirectionFromLocale(java.util.Locale.getDefault());
+            return (dir == LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE);
+        }
+
+        public static final TextDirectionHeuristicLocale INSTANCE =
+                new TextDirectionHeuristicLocale();
+    }
 }
diff --git a/core/java/android/text/method/WordIterator.java b/core/java/android/text/method/WordIterator.java
index af524ee..0433ec4 100644
--- a/core/java/android/text/method/WordIterator.java
+++ b/core/java/android/text/method/WordIterator.java
@@ -73,6 +73,10 @@
         }
     };
 
+    public void forceUpdate() {
+        mCurrentDirty = true;
+    }
+
     public void setCharSequence(CharSequence incoming) {
         // When incoming is different object, move listeners to new sequence
         // and mark as dirty so we reload contents.
diff --git a/core/java/android/text/style/SpellCheckSpan.java b/core/java/android/text/style/SpellCheckSpan.java
new file mode 100644
index 0000000..9b23177
--- /dev/null
+++ b/core/java/android/text/style/SpellCheckSpan.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.style;
+
+/**
+ * A SpellCheckSpan is an internal data structure created by the TextView's SpellChecker to
+ * annotate portions of the text that are about to or currently being spell checked. They are
+ * automatically removed once the spell check is completed.
+ *
+ * @hide
+ */
+public class SpellCheckSpan {
+
+    private boolean mSpellCheckInProgress;
+
+    public SpellCheckSpan() {
+        mSpellCheckInProgress = false;
+    }
+
+    public void setSpellCheckInProgress() {
+        mSpellCheckInProgress = true;
+    }
+
+    public boolean isSpellCheckInProgress() {
+        return mSpellCheckInProgress;
+    }
+}
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index fb94bc7..ea57f91 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -40,7 +40,7 @@
  * These spans should typically be created by the input method to provide correction and alternates
  * for the text.
  *
- * @see TextView#setSuggestionsEnabled(boolean)
+ * @see TextView#isSuggestionsEnabled()
  */
 public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
 
@@ -76,7 +76,7 @@
      * And the current IME might want to specify any IME as the target IME including other IMEs.
      */
 
-    private final int mFlags;
+    private int mFlags;
     private final String[] mSuggestions;
     private final String mLocaleString;
     private final String mNotificationTargetClassName;
@@ -134,8 +134,7 @@
         } else {
             mNotificationTargetClassName = "";
         }
-        mHashCode = hashCodeInternal(
-                mFlags, mSuggestions, mLocaleString, mNotificationTargetClassName);
+        mHashCode = hashCodeInternal(mSuggestions, mLocaleString, mNotificationTargetClassName);
 
         initStyle(context);
     }
@@ -211,6 +210,10 @@
         return mFlags;
     }
 
+    public void setFlags(int flags) {
+        mFlags = flags;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -247,10 +250,10 @@
         return mHashCode;
     }
 
-    private static int hashCodeInternal(int flags, String[] suggestions,String locale,
+    private static int hashCodeInternal(String[] suggestions, String locale,
             String notificationTargetClassName) {
-        return Arrays.hashCode(new Object[] {SystemClock.uptimeMillis(), flags, suggestions, locale,
-                notificationTargetClassName});
+        return Arrays.hashCode(new Object[] {Long.valueOf(SystemClock.uptimeMillis()), suggestions,
+                locale, notificationTargetClassName});
     }
 
     public static final Parcelable.Creator<SuggestionSpan> CREATOR =
diff --git a/core/java/android/util/LocaleUtil.java b/core/java/android/util/LocaleUtil.java
index 74a930f..763af73 100644
--- a/core/java/android/util/LocaleUtil.java
+++ b/core/java/android/util/LocaleUtil.java
@@ -32,11 +32,6 @@
     /**
      * @hide Do not use. Implementation not finished.
      */
-    public static final int TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE = -1;
-
-    /**
-     * @hide Do not use. Implementation not finished.
-     */
     public static final int TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE = 0;
 
     /**
@@ -54,7 +49,6 @@
      *
      * @param locale the Locale for which we want the layout direction. Can be null.
      * @return the layout direction. This may be one of:
-     * {@link #TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE} or
      * {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or
      * {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}.
      *
@@ -63,17 +57,16 @@
      * @hide
      */
     public static int getLayoutDirectionFromLocale(Locale locale) {
-        if (locale == null || locale.equals(Locale.ROOT)) {
-            return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
+        if (locale != null && !locale.equals(Locale.ROOT)) {
+            final String scriptSubtag = ICU.getScript(ICU.addLikelySubtags(locale.toString()));
+            if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale);
+
+            if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) ||
+                    scriptSubtag.equalsIgnoreCase(HEBR_SCRIPT_SUBTAG)) {
+                return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
+            }
         }
 
-        final String scriptSubtag = ICU.getScript(ICU.addLikelySubtags(locale.toString()));
-        if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale);
-
-        if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) ||
-                scriptSubtag.equalsIgnoreCase(HEBR_SCRIPT_SUBTAG)) {
-            return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
-        }
         return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
     }
 
@@ -84,7 +77,6 @@
      *
      * @param locale
      * @return the layout direction. This may be one of:
-     * {@link #TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE} or
      * {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or
      * {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}.
      *
@@ -94,13 +86,13 @@
      */
     private static int getLayoutDirectionFromFirstChar(Locale locale) {
         switch(Character.getDirectionality(locale.getDisplayName(locale).charAt(0))) {
-            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
-                return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
             case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
             case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
                 return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
+
+            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
             default:
-                return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
+                return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
         }
     }
 }
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index cfbb47c..c934c7b 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -541,9 +541,19 @@
     
     @Override
     public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
-        return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
+        if (bounds != null) {
+            return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
+        }
+
+        int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
+        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+        int count = nSaveLayer(mRenderer, nativePaint, saveFlags);
+        if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
+        return count;
     }
 
+    private static native int nSaveLayer(int renderer, int paint, int saveFlags);    
+
     @Override
     public int saveLayer(float left, float top, float right, float bottom, Paint paint,
             int saveFlags) {
@@ -562,10 +572,15 @@
 
     @Override
     public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
-        return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
-                alpha, saveFlags);
+        if (bounds != null) {
+            return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
+                    alpha, saveFlags);
+        }
+        return nSaveLayerAlpha(mRenderer, alpha, saveFlags);
     }
 
+    private static native int nSaveLayerAlpha(int renderer, int alpha, int saveFlags);    
+
     @Override
     public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
             int saveFlags) {
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index a05637d..2bf16d8 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -21,6 +21,7 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
+import android.opengl.GLUtils;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.util.Log;
@@ -402,51 +403,6 @@
         }
 
         /**
-         * Return a string for the EGL error code, or the hex representation
-         * if the error is unknown.
-         * 
-         * @param error The EGL error to convert into a String.
-         * 
-         * @return An error string correponding to the EGL error code.
-         */
-        static String getEGLErrorString(int error) {
-            switch (error) {
-                case EGL_SUCCESS:
-                    return "EGL_SUCCESS";
-                case EGL_NOT_INITIALIZED:
-                    return "EGL_NOT_INITIALIZED";
-                case EGL_BAD_ACCESS:
-                    return "EGL_BAD_ACCESS";
-                case EGL_BAD_ALLOC:
-                    return "EGL_BAD_ALLOC";
-                case EGL_BAD_ATTRIBUTE:
-                    return "EGL_BAD_ATTRIBUTE";
-                case EGL_BAD_CONFIG:
-                    return "EGL_BAD_CONFIG";
-                case EGL_BAD_CONTEXT:
-                    return "EGL_BAD_CONTEXT";
-                case EGL_BAD_CURRENT_SURFACE:
-                    return "EGL_BAD_CURRENT_SURFACE";
-                case EGL_BAD_DISPLAY:
-                    return "EGL_BAD_DISPLAY";
-                case EGL_BAD_MATCH:
-                    return "EGL_BAD_MATCH";
-                case EGL_BAD_NATIVE_PIXMAP:
-                    return "EGL_BAD_NATIVE_PIXMAP";
-                case EGL_BAD_NATIVE_WINDOW:
-                    return "EGL_BAD_NATIVE_WINDOW";
-                case EGL_BAD_PARAMETER:
-                    return "EGL_BAD_PARAMETER";
-                case EGL_BAD_SURFACE:
-                    return "EGL_BAD_SURFACE";
-                case EGL11.EGL_CONTEXT_LOST:
-                    return "EGL_CONTEXT_LOST";
-                default:
-                    return "0x" + Integer.toHexString(error);
-            }
-        }
-
-        /**
          * Checks for OpenGL errors. If an error has occured, {@link #destroy(boolean)}
          * is invoked and the requested flag is turned off. The error code is
          * also logged as a warning.
@@ -457,8 +413,8 @@
                 if (error != EGL_SUCCESS) {
                     // something bad has happened revert to
                     // normal rendering.
+                    Log.w(LOG_TAG, "EGL error: " + GLUtils.getEGLErrorString(error));
                     fallback(error != EGL11.EGL_CONTEXT_LOST);
-                    Log.w(LOG_TAG, "EGL error: " + getEGLErrorString(error));
                 }
             }
         }
@@ -523,14 +479,14 @@
                     
                     if (sEglDisplay == EGL_NO_DISPLAY) {
                         throw new RuntimeException("eglGetDisplay failed "
-                                + getEGLErrorString(sEgl.eglGetError()));
+                                + GLUtils.getEGLErrorString(sEgl.eglGetError()));
                     }
                     
                     // We can now initialize EGL for that display
                     int[] version = new int[2];
                     if (!sEgl.eglInitialize(sEglDisplay, version)) {
                         throw new RuntimeException("eglInitialize failed " +
-                                getEGLErrorString(sEgl.eglGetError()));
+                                GLUtils.getEGLErrorString(sEgl.eglGetError()));
                     }
         
                     sEglConfig = chooseEglConfig();
@@ -579,7 +535,7 @@
 
             if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) {
                 throw new IllegalArgumentException("eglChooseConfig failed " +
-                        getEGLErrorString(sEgl.eglGetError()));
+                        GLUtils.getEGLErrorString(sEgl.eglGetError()));
             } else if (configsCount[0] > 0) {
                 if ("choice".equalsIgnoreCase(debug)) {
                     printConfig(configs[0]);
@@ -647,7 +603,7 @@
              */
             if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
                 throw new Surface.OutOfResourcesException("eglMakeCurrent failed "
-                        + getEGLErrorString(sEgl.eglGetError()));
+                        + GLUtils.getEGLErrorString(sEgl.eglGetError()));
             }
 
             // If mDirtyRegions is set, this means we have an EGL configuration
@@ -734,7 +690,7 @@
                     return false;
                 }
                 throw new RuntimeException("createWindowSurface failed "
-                        + getEGLErrorString(error));
+                        + GLUtils.getEGLErrorString(error));
             }
             return true;
         }
@@ -746,8 +702,9 @@
 
         @Override
         void setup(int width, int height) {
-            checkCurrent();
-            mCanvas.setViewport(width, height);
+            if (validate()) {
+                mCanvas.setViewport(width, height);
+            }
         }
 
         boolean canDraw() {
@@ -854,9 +811,9 @@
             if (!mEglContext.equals(sEgl.eglGetCurrentContext()) ||
                     !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) {
                 if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
-                    fallback(true);
                     Log.e(LOG_TAG, "eglMakeCurrent failed " +
-                            getEGLErrorString(sEgl.eglGetError()));
+                            GLUtils.getEGLErrorString(sEgl.eglGetError()));
+                    fallback(true);
                     return SURFACE_STATE_ERROR;
                 } else {
                     return SURFACE_STATE_UPDATED;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 17e637c..80b5dad3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6433,10 +6433,10 @@
         if ((flags & VISIBILITY_MASK) == VISIBLE) {
             if ((changed & VISIBILITY_MASK) != 0) {
                 /*
-                 * If this view is becoming visible, set the DRAWN flag so that
-                 * the next invalidate() will not be skipped.
+                 * If this view is becoming visible, invalidate it in case it changed while
+                 * it was not visible.
                  */
-                mPrivateFlags |= DRAWN;
+                invalidate(true);
 
                 needGlobalAttributesUpdate(true);
 
@@ -9992,8 +9992,6 @@
                 // The dirty rect should always be null for a display list
                 canvas.onPreDraw(null);
 
-                final int restoreCount = canvas.save();
-
                 computeScroll();
                 canvas.translate(-mScrollX, -mScrollY);
                 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
@@ -10005,8 +10003,6 @@
                 } else {
                     draw(canvas);
                 }
-
-                canvas.restoreToCount(restoreCount);
             } finally {
                 canvas.onPostDraw();
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f23c366..a0cc287 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -61,6 +61,7 @@
 import android.util.TypedValue;
 import android.view.View.MeasureSpec;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityInteractionClient;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -575,7 +576,6 @@
 
         if (hardwareAccelerated) {
             if (!HardwareRenderer.isAvailable()) {
-                mAttachInfo.mHardwareAccelerationRequested = true;
                 return;
             }
 
@@ -601,6 +601,13 @@
                 mAttachInfo.mHardwareRenderer = HardwareRenderer.createGlRenderer(2, translucent);
                 mAttachInfo.mHardwareAccelerated = mAttachInfo.mHardwareAccelerationRequested
                         = mAttachInfo.mHardwareRenderer != null;
+            } else {
+                // We would normally have enabled hardware acceleration, but
+                // haven't because we are in the system process.  We still want
+                // what is drawn on the screen to behave as if it is accelerated,
+                // so that our preview starting windows visually match what will
+                // actually be drawn by the app.
+                mAttachInfo.mHardwareAccelerationRequested = true;
             }
         }
     }
@@ -879,6 +886,8 @@
             host.dispatchAttachedToWindow(attachInfo, 0);
             //Log.i(TAG, "Screen on initialized: " + attachInfo.mKeepScreenOn);
 
+            host.fitSystemWindows(mAttachInfo.mContentInsets);
+
         } else {
             desiredWindowWidth = frame.width();
             desiredWindowHeight = frame.height();
@@ -914,85 +923,15 @@
             final Resources res = mView.getContext().getResources();
 
             if (mFirst) {
-                host.fitSystemWindows(mAttachInfo.mContentInsets);
                 // make sure touch mode code executes by setting cached value
                 // to opposite of the added touch mode.
                 mAttachInfo.mInTouchMode = !mAddedTouchMode;
                 ensureTouchModeLocally(mAddedTouchMode);
             } else {
-                if (!mAttachInfo.mContentInsets.equals(mPendingContentInsets)) {
-                    if (mWidth > 0 && mHeight > 0 &&
-                            mSurface != null && mSurface.isValid() &&
-                            !mAttachInfo.mTurnOffWindowResizeAnim &&
-                            mAttachInfo.mHardwareRenderer != null &&
-                            mAttachInfo.mHardwareRenderer.isEnabled() &&
-                            mAttachInfo.mHardwareRenderer.validate() &&
-                            lp != null && !PixelFormat.formatHasAlpha(lp.format)) {
-
-                        disposeResizeBuffer();
-
-                        boolean completed = false;
-                        HardwareCanvas canvas = null;
-                        try {
-                            if (mResizeBuffer == null) {
-                                mResizeBuffer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
-                                        mWidth, mHeight, false);
-                            } else if (mResizeBuffer.getWidth() != mWidth ||
-                                    mResizeBuffer.getHeight() != mHeight) {
-                                mResizeBuffer.resize(mWidth, mHeight);
-                            }
-                            canvas = mResizeBuffer.start(mAttachInfo.mHardwareCanvas);
-                            canvas.setViewport(mWidth, mHeight);
-                            canvas.onPreDraw(null);
-                            final int restoreCount = canvas.save();
-                            
-                            canvas.drawColor(0xff000000, PorterDuff.Mode.SRC);
-
-                            int yoff;
-                            final boolean scrolling = mScroller != null
-                                    && mScroller.computeScrollOffset();
-                            if (scrolling) {
-                                yoff = mScroller.getCurrY();
-                                mScroller.abortAnimation();
-                            } else {
-                                yoff = mScrollY;
-                            }
-
-                            canvas.translate(0, -yoff);
-                            if (mTranslator != null) {
-                                mTranslator.translateCanvas(canvas);
-                            }
-
-                            mView.draw(canvas);
-
-                            mResizeBufferStartTime = SystemClock.uptimeMillis();
-                            mResizeBufferDuration = mView.getResources().getInteger(
-                                    com.android.internal.R.integer.config_mediumAnimTime);
-                            completed = true;
-
-                            canvas.restoreToCount(restoreCount);
-                        } catch (OutOfMemoryError e) {
-                            Log.w(TAG, "Not enough memory for content change anim buffer", e);
-                        } finally {
-                            if (canvas != null) {
-                                canvas.onPostDraw();
-                            }
-                            if (mResizeBuffer != null) {
-                                mResizeBuffer.end(mAttachInfo.mHardwareCanvas);
-                                if (!completed) {
-                                    mResizeBuffer.destroy();
-                                    mResizeBuffer = null;
-                                }
-                            }
-                        }
-                    }
-                    mAttachInfo.mContentInsets.set(mPendingContentInsets);
-                    host.fitSystemWindows(mAttachInfo.mContentInsets);
+                if (!mPendingContentInsets.equals(mAttachInfo.mContentInsets)) {
                     insetsChanged = true;
-                    if (DEBUG_LAYOUT) Log.v(TAG, "Content insets changing to: "
-                            + mAttachInfo.mContentInsets);
                 }
-                if (!mAttachInfo.mVisibleInsets.equals(mPendingVisibleInsets)) {
+                if (!mPendingVisibleInsets.equals(mAttachInfo.mVisibleInsets)) {
                     mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets);
                     if (DEBUG_LAYOUT) Log.v(TAG, "Visible insets changing to: "
                             + mAttachInfo.mVisibleInsets);
@@ -1203,6 +1142,71 @@
                 visibleInsetsChanged = !mPendingVisibleInsets.equals(
                         mAttachInfo.mVisibleInsets);
                 if (contentInsetsChanged) {
+                    if (mWidth > 0 && mHeight > 0 &&
+                            mSurface != null && mSurface.isValid() &&
+                            !mAttachInfo.mTurnOffWindowResizeAnim &&
+                            mAttachInfo.mHardwareRenderer != null &&
+                            mAttachInfo.mHardwareRenderer.isEnabled() &&
+                            mAttachInfo.mHardwareRenderer.validate() &&
+                            lp != null && !PixelFormat.formatHasAlpha(lp.format)) {
+
+                        disposeResizeBuffer();
+
+                        boolean completed = false;
+                        HardwareCanvas canvas = null;
+                        try {
+                            if (mResizeBuffer == null) {
+                                mResizeBuffer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
+                                        mWidth, mHeight, false);
+                            } else if (mResizeBuffer.getWidth() != mWidth ||
+                                    mResizeBuffer.getHeight() != mHeight) {
+                                mResizeBuffer.resize(mWidth, mHeight);
+                            }
+                            canvas = mResizeBuffer.start(mAttachInfo.mHardwareCanvas);
+                            canvas.setViewport(mWidth, mHeight);
+                            canvas.onPreDraw(null);
+                            final int restoreCount = canvas.save();
+                            
+                            canvas.drawColor(0xff000000, PorterDuff.Mode.SRC);
+
+                            int yoff;
+                            final boolean scrolling = mScroller != null
+                                    && mScroller.computeScrollOffset();
+                            if (scrolling) {
+                                yoff = mScroller.getCurrY();
+                                mScroller.abortAnimation();
+                            } else {
+                                yoff = mScrollY;
+                            }
+
+                            canvas.translate(0, -yoff);
+                            if (mTranslator != null) {
+                                mTranslator.translateCanvas(canvas);
+                            }
+
+                            mView.draw(canvas);
+
+                            mResizeBufferStartTime = SystemClock.uptimeMillis();
+                            mResizeBufferDuration = mView.getResources().getInteger(
+                                    com.android.internal.R.integer.config_mediumAnimTime);
+                            completed = true;
+
+                            canvas.restoreToCount(restoreCount);
+                        } catch (OutOfMemoryError e) {
+                            Log.w(TAG, "Not enough memory for content change anim buffer", e);
+                        } finally {
+                            if (canvas != null) {
+                                canvas.onPostDraw();
+                            }
+                            if (mResizeBuffer != null) {
+                                mResizeBuffer.end(mAttachInfo.mHardwareCanvas);
+                                if (!completed) {
+                                    mResizeBuffer.destroy();
+                                    mResizeBuffer = null;
+                                }
+                            }
+                        }
+                    }
                     mAttachInfo.mContentInsets.set(mPendingContentInsets);
                     host.fitSystemWindows(mAttachInfo.mContentInsets);
                     if (DEBUG_LAYOUT) Log.v(TAG, "Content insets changing to: "
@@ -1348,7 +1352,7 @@
                     mAttachInfo.mHardwareRenderer != null &&
                     mAttachInfo.mHardwareRenderer.isEnabled())) {
                 mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
-                if (!hwInitialized) {
+                if (!hwInitialized && mAttachInfo.mHardwareRenderer.isEnabled()) {
                     mAttachInfo.mHardwareRenderer.invalidate(mHolder);
                 }
             }
@@ -4359,37 +4363,42 @@
         }
 
         public void findAccessibilityNodeInfoByAccessibilityId(int accessibilityId,
-                int interactionId, IAccessibilityInteractionConnectionCallback callback) {
+                int interactionId, IAccessibilityInteractionConnectionCallback callback,
+                int interrogatingPid, long interrogatingTid) {
             if (mViewAncestor.get() != null) {
                 getAccessibilityInteractionController()
                     .findAccessibilityNodeInfoByAccessibilityIdClientThread(accessibilityId,
-                        interactionId, callback);
+                        interactionId, callback, interrogatingPid, interrogatingTid);
             }
         }
 
         public void performAccessibilityAction(int accessibilityId, int action,
-                int interactionId, IAccessibilityInteractionConnectionCallback callback) {
+                int interactionId, IAccessibilityInteractionConnectionCallback callback,
+                int interogatingPid, long interrogatingTid) {
             if (mViewAncestor.get() != null) {
                 getAccessibilityInteractionController()
                     .performAccessibilityActionClientThread(accessibilityId, action, interactionId,
-                            callback);
+                            callback, interogatingPid, interrogatingTid);
             }
         }
 
         public void findAccessibilityNodeInfoByViewId(int viewId,
-                int interactionId, IAccessibilityInteractionConnectionCallback callback) {
+                int interactionId, IAccessibilityInteractionConnectionCallback callback,
+                int interrogatingPid, long interrogatingTid) {
             if (mViewAncestor.get() != null) {
                 getAccessibilityInteractionController()
-                    .findAccessibilityNodeInfoByViewIdClientThread(viewId, interactionId, callback);
+                    .findAccessibilityNodeInfoByViewIdClientThread(viewId, interactionId, callback,
+                            interrogatingPid, interrogatingTid);
             }
         }
 
         public void findAccessibilityNodeInfosByViewText(String text, int accessibilityId,
-                int interactionId, IAccessibilityInteractionConnectionCallback callback) {
+                int interactionId, IAccessibilityInteractionConnectionCallback callback,
+                int interrogatingPid, long interrogatingTid) {
             if (mViewAncestor.get() != null) {
                 getAccessibilityInteractionController()
                     .findAccessibilityNodeInfosByViewTextClientThread(text, accessibilityId,
-                            interactionId, callback);
+                            interactionId, callback, interrogatingPid, interrogatingTid);
             }
         }
     }
@@ -4465,13 +4474,24 @@
         }
 
         public void findAccessibilityNodeInfoByAccessibilityIdClientThread(int accessibilityId,
-                int interactionId, IAccessibilityInteractionConnectionCallback callback) {
+                int interactionId, IAccessibilityInteractionConnectionCallback callback,
+                int interrogatingPid, long interrogatingTid) {
             Message message = Message.obtain();
             message.what = DO_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID;
             message.arg1 = accessibilityId;
             message.arg2 = interactionId;
             message.obj = callback;
-            sendMessage(message);
+            // If the interrogation is performed by the same thread as the main UI
+            // thread in this process, set the message as a static reference so
+            // after this call completes the same thread but in the interrogating
+            // client can handle the message to generate the result.
+            if (interrogatingPid == Process.myPid()
+                    && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+                message.setTarget(ViewRootImpl.this);
+                AccessibilityInteractionClient.getInstance().setSameThreadMessage(message);
+            } else {
+                sendMessage(message);
+            }
         }
 
         public void findAccessibilityNodeInfoByAccessibilityIdUiThread(Message message) {
@@ -4499,13 +4519,24 @@
         }
 
         public void findAccessibilityNodeInfoByViewIdClientThread(int viewId, int interactionId,
-                IAccessibilityInteractionConnectionCallback callback) {
+                IAccessibilityInteractionConnectionCallback callback, int interrogatingPid,
+                long interrogatingTid) {
             Message message = Message.obtain();
             message.what = DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID;
             message.arg1 = viewId;
             message.arg2 = interactionId;
             message.obj = callback;
-            sendMessage(message);
+            // If the interrogation is performed by the same thread as the main UI
+            // thread in this process, set the message as a static reference so
+            // after this call completes the same thread but in the interrogating
+            // client can handle the message to generate the result.
+            if (interrogatingPid == Process.myPid()
+                    && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+                message.setTarget(ViewRootImpl.this);
+                AccessibilityInteractionClient.getInstance().setSameThreadMessage(message);
+            } else {
+                sendMessage(message);
+            }
         }
 
         public void findAccessibilityNodeInfoByViewIdUiThread(Message message) {
@@ -4532,7 +4563,8 @@
 
         public void findAccessibilityNodeInfosByViewTextClientThread(String text,
                 int accessibilityViewId, int interactionId,
-                IAccessibilityInteractionConnectionCallback callback) {
+                IAccessibilityInteractionConnectionCallback callback, int interrogatingPid,
+                long interrogatingTid) {
             Message message = Message.obtain();
             message.what = DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT;
             SomeArgs args = mPool.acquire();
@@ -4541,7 +4573,17 @@
             args.argi2 = interactionId;
             args.arg2 = callback;
             message.obj = args;
-            sendMessage(message);
+            // If the interrogation is performed by the same thread as the main UI
+            // thread in this process, set the message as a static reference so
+            // after this call completes the same thread but in the interrogating
+            // client can handle the message to generate the result.
+            if (interrogatingPid == Process.myPid()
+                    && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+                message.setTarget(ViewRootImpl.this);
+                AccessibilityInteractionClient.getInstance().setSameThreadMessage(message);
+            } else {
+                sendMessage(message);
+            }
         }
 
         public void findAccessibilityNodeInfosByViewTextUiThread(Message message) {
@@ -4594,7 +4636,8 @@
         }
 
         public void performAccessibilityActionClientThread(int accessibilityId, int action,
-                int interactionId, IAccessibilityInteractionConnectionCallback callback) {
+                int interactionId, IAccessibilityInteractionConnectionCallback callback,
+                int interogatingPid, long interrogatingTid) {
             Message message = Message.obtain();
             message.what = DO_PERFORM_ACCESSIBILITY_ACTION;
             SomeArgs args = mPool.acquire();
@@ -4603,7 +4646,17 @@
             args.argi3 = interactionId;
             args.arg1 = callback;
             message.obj = args;
-            sendMessage(message);
+            // If the interrogation is performed by the same thread as the main UI
+            // thread in this process, set the message as a static reference so
+            // after this call completes the same thread but in the interrogating
+            // client can handle the message to generate the result.
+            if (interogatingPid == Process.myPid()
+                    && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
+                message.setTarget(ViewRootImpl.this);
+                AccessibilityInteractionClient.getInstance().setSameThreadMessage(message);
+            } else {
+                sendMessage(message);
+            }
         }
 
         public void perfromAccessibilityActionUiThread(Message message) {
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
new file mode 100644
index 0000000..071701e
--- /dev/null
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -0,0 +1,462 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+package android.view.accessibility;
+
+import android.accessibilityservice.IAccessibilityServiceConnection;
+import android.graphics.Rect;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.SystemClock;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * This class is a singleton that performs accessibility interaction
+ * which is it queries remote view hierarchies about snapshots of their
+ * views as well requests from these hierarchies to perform certain
+ * actions on their views.
+ *
+ * Rationale: The content retrieval APIs are synchronous from a client's
+ *     perspective but internally they are asynchronous. The client thread
+ *     calls into the system requesting an action and providing a callback
+ *     to receive the result after which it waits up to a timeout for that
+ *     result. The system enforces security and the delegates the request
+ *     to a given view hierarchy where a message is posted (from a binder
+ *     thread) describing what to be performed by the main UI thread the
+ *     result of which it delivered via the mentioned callback. However,
+ *     the blocked client thread and the main UI thread of the target view
+ *     hierarchy can be the same thread, for example an accessibility service
+ *     and an activity run in the same process, thus they are executed on the
+ *     same main thread. In such a case the retrieval will fail since the UI
+ *     thread that has to process the message describing the work to be done
+ *     is blocked waiting for a result is has to compute! To avoid this scenario
+ *     when making a call the client also passes its process and thread ids so
+ *     the accessed view hierarchy can detect if the client making the request
+ *     is running in its main UI thread. In such a case the view hierarchy,
+ *     specifically the binder thread performing the IPC to it, does not post a
+ *     message to be run on the UI thread but passes it to the singleton
+ *     interaction client through which all interactions occur and the latter is
+ *     responsible to execute the message before starting to wait for the
+ *     asynchronous result delivered via the callback. In this case the expected
+ *     result is already received so no waiting is performed.
+ *
+ * @hide
+ */
+public final class AccessibilityInteractionClient
+        extends IAccessibilityInteractionConnectionCallback.Stub {
+
+    private static final long TIMEOUT_INTERACTION_MILLIS = 5000;
+
+    private static final Object sStaticLock = new Object();
+
+    private static AccessibilityInteractionClient sInstance;
+
+    private final AtomicInteger mInteractionIdCounter = new AtomicInteger();
+
+    private final Object mInstanceLock = new Object();
+
+    private int mInteractionId = -1;
+
+    private AccessibilityNodeInfo mFindAccessibilityNodeInfoResult;
+
+    private List<AccessibilityNodeInfo> mFindAccessibilityNodeInfosResult;
+
+    private boolean mPerformAccessibilityActionResult;
+
+    private Message mSameThreadMessage;
+
+    private final Rect mTempBounds = new Rect();
+
+    /**
+     * @return The singleton of this class.
+     */
+    public static AccessibilityInteractionClient getInstance() {
+        synchronized (sStaticLock) {
+            if (sInstance == null) {
+                sInstance = new AccessibilityInteractionClient();
+            }
+            return sInstance;
+        }
+    }
+
+    /**
+     * Sets the message to be processed if the interacted view hierarchy
+     * and the interacting client are running in the same thread.
+     *
+     * @param message The message.
+     */
+    public void setSameThreadMessage(Message message) {
+        synchronized (mInstanceLock) {
+            mSameThreadMessage = message;
+        }
+    }
+
+    /**
+     * Finds an {@link AccessibilityNodeInfo} by accessibility id.
+     *
+     * @param connection A connection for interacting with the system.
+     * @param accessibilityWindowId A unique window id.
+     * @param accessibilityViewId A unique View accessibility id.
+     * @return An {@link AccessibilityNodeInfo} if found, null otherwise.
+     */
+    public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(
+            IAccessibilityServiceConnection connection, int accessibilityWindowId,
+            int accessibilityViewId) {
+        try {
+            final int interactionId = mInteractionIdCounter.getAndIncrement();
+            final float windowScale = connection.findAccessibilityNodeInfoByAccessibilityId(
+                    accessibilityWindowId, accessibilityViewId, interactionId, this,
+                    Thread.currentThread().getId());
+            // If the scale is zero the call has failed.
+            if (windowScale > 0) {
+                handleSameThreadMessageIfNeeded();
+                AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
+                        interactionId);
+                finalizeAccessibilityNodeInfo(info, connection, windowScale);
+                return info;
+            }
+        } catch (RemoteException re) {
+            /* ignore */
+        }
+        return null;
+    }
+
+    /**
+     * Finds an {@link AccessibilityNodeInfo} by View id. The search is performed
+     * in the currently active window and starts from the root View in the window.
+     *
+     * @param connection A connection for interacting with the system.
+     * @param id The id of the node.
+     * @return An {@link AccessibilityNodeInfo} if found, null otherwise.
+     */
+    public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(
+            IAccessibilityServiceConnection connection, int viewId) {
+        try {
+            final int interactionId = mInteractionIdCounter.getAndIncrement();
+            final float windowScale = connection.findAccessibilityNodeInfoByViewIdInActiveWindow(
+                    viewId, interactionId, this, Thread.currentThread().getId());
+            // If the scale is zero the call has failed.
+            if (windowScale > 0) {
+                handleSameThreadMessageIfNeeded();
+                AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
+                        interactionId);
+                finalizeAccessibilityNodeInfo(info, connection, windowScale);
+                return info;
+            }
+        } catch (RemoteException re) {
+            /* ignore */
+        }
+        return null;
+    }
+
+    /**
+     * Finds {@link AccessibilityNodeInfo}s by View text. The match is case
+     * insensitive containment. The search is performed in the currently
+     * active window and starts from the root View in the window.
+     *
+     * @param connection A connection for interacting with the system.
+     * @param text The searched text.
+     * @return A list of found {@link AccessibilityNodeInfo}s.
+     */
+    public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewTextInActiveWindow(
+            IAccessibilityServiceConnection connection, String text) {
+        try {
+            final int interactionId = mInteractionIdCounter.getAndIncrement();
+            final float windowScale = connection.findAccessibilityNodeInfosByViewTextInActiveWindow(
+                    text, interactionId, this, Thread.currentThread().getId());
+            // If the scale is zero the call has failed.
+            if (windowScale > 0) {
+                handleSameThreadMessageIfNeeded();
+                List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
+                        interactionId);
+                finalizeAccessibilityNodeInfos(infos, connection, windowScale);
+                return infos;
+            }
+        } catch (RemoteException re) {
+            /* ignore */
+        }
+        return null;
+    }
+
+    /**
+     * Finds {@link AccessibilityNodeInfo}s by View text. The match is case
+     * insensitive containment. The search is performed in the window whose
+     * id is specified and starts from the View whose accessibility id is
+     * specified.
+     *
+     * @param connection A connection for interacting with the system.
+     * @param text The searched text.
+     * @param accessibilityWindowId A unique window id.
+     * @param accessibilityViewId A unique View accessibility id from where to start the search.
+     *        Use {@link android.view.View#NO_ID} to start from the root.
+     * @return A list of found {@link AccessibilityNodeInfo}s.
+     */
+    public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(
+            IAccessibilityServiceConnection connection, String text, int accessibilityWindowId,
+            int accessibilityViewId) {
+        try {
+            final int interactionId = mInteractionIdCounter.getAndIncrement();
+            final float windowScale = connection.findAccessibilityNodeInfosByViewText(text,
+                    accessibilityWindowId, accessibilityViewId, interactionId, this,
+                    Thread.currentThread().getId());
+            // If the scale is zero the call has failed.
+            if (windowScale > 0) {
+                handleSameThreadMessageIfNeeded();
+                List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
+                        interactionId);
+                finalizeAccessibilityNodeInfos(infos, connection, windowScale);
+                return infos;
+            }
+        } catch (RemoteException re) {
+            /* ignore */
+        }
+        return Collections.emptyList();
+    }
+
+    /**
+     * Performs an accessibility action on an {@link AccessibilityNodeInfo}.
+     *
+     * @param connection A connection for interacting with the system.
+     * @param accessibilityWindowId The id of the window.
+     * @param accessibilityViewId A unique View accessibility id.
+     * @param action The action to perform.
+     * @return Whether the action was performed.
+     */
+    public boolean performAccessibilityAction(IAccessibilityServiceConnection connection,
+            int accessibilityWindowId, int accessibilityViewId, int action) {
+        try {
+            final int interactionId = mInteractionIdCounter.getAndIncrement();
+            final boolean success = connection.performAccessibilityAction(
+                    accessibilityWindowId, accessibilityViewId, action, interactionId, this,
+                    Thread.currentThread().getId());
+            if (success) {
+                handleSameThreadMessageIfNeeded();
+                return getPerformAccessibilityActionResult(interactionId);
+            }
+        } catch (RemoteException re) {
+            /* ignore */
+        }
+        return false;
+    }
+
+    /**
+     * Gets the the result of an async request that returns an {@link AccessibilityNodeInfo}.
+     *
+     * @param interactionId The interaction id to match the result with the request.
+     * @return The result {@link AccessibilityNodeInfo}.
+     */
+    private AccessibilityNodeInfo getFindAccessibilityNodeInfoResultAndClear(int interactionId) {
+        synchronized (mInstanceLock) {
+            final boolean success = waitForResultTimedLocked(interactionId);
+            AccessibilityNodeInfo result = success ? mFindAccessibilityNodeInfoResult : null;
+            clearResultLocked();
+            return result;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setFindAccessibilityNodeInfoResult(AccessibilityNodeInfo info,
+                int interactionId) {
+        synchronized (mInstanceLock) {
+            if (interactionId > mInteractionId) {
+                mFindAccessibilityNodeInfoResult = info;
+                mInteractionId = interactionId;
+            }
+            mInstanceLock.notifyAll();
+        }
+    }
+
+    /**
+     * Gets the the result of an async request that returns {@link AccessibilityNodeInfo}s.
+     *
+     * @param interactionId The interaction id to match the result with the request.
+     * @return The result {@link AccessibilityNodeInfo}s.
+     */
+    private List<AccessibilityNodeInfo> getFindAccessibilityNodeInfosResultAndClear(
+                int interactionId) {
+        synchronized (mInstanceLock) {
+            final boolean success = waitForResultTimedLocked(interactionId);
+            List<AccessibilityNodeInfo> result = success ? mFindAccessibilityNodeInfosResult : null;
+            clearResultLocked();
+            return result;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setFindAccessibilityNodeInfosResult(List<AccessibilityNodeInfo> infos,
+                int interactionId) {
+        synchronized (mInstanceLock) {
+            if (interactionId > mInteractionId) {
+                mFindAccessibilityNodeInfosResult = infos;
+                mInteractionId = interactionId;
+            }
+            mInstanceLock.notifyAll();
+        }
+    }
+
+    /**
+     * Gets the result of a request to perform an accessibility action.
+     *
+     * @param interactionId The interaction id to match the result with the request.
+     * @return Whether the action was performed.
+     */
+    private boolean getPerformAccessibilityActionResult(int interactionId) {
+        synchronized (mInstanceLock) {
+            final boolean success = waitForResultTimedLocked(interactionId);
+            final boolean result = success ? mPerformAccessibilityActionResult : false;
+            clearResultLocked();
+            return result;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setPerformAccessibilityActionResult(boolean succeeded, int interactionId) {
+        synchronized (mInstanceLock) {
+            if (interactionId > mInteractionId) {
+                mPerformAccessibilityActionResult = succeeded;
+                mInteractionId = interactionId;
+            }
+            mInstanceLock.notifyAll();
+        }
+    }
+
+    /**
+     * Clears the result state.
+     */
+    private void clearResultLocked() {
+        mInteractionId = -1;
+        mFindAccessibilityNodeInfoResult = null;
+        mFindAccessibilityNodeInfosResult = null;
+        mPerformAccessibilityActionResult = false;
+    }
+
+    /**
+     * Waits up to a given bound for a result of a request and returns it.
+     *
+     * @param interactionId The interaction id to match the result with the request.
+     * @return Whether the result was received.
+     */
+    private boolean waitForResultTimedLocked(int interactionId) {
+        long waitTimeMillis = TIMEOUT_INTERACTION_MILLIS;
+        final long startTimeMillis = SystemClock.uptimeMillis();
+        while (true) {
+            try {
+                if (mInteractionId == interactionId) {
+                    return true;
+                }
+                if (mInteractionId > interactionId) {
+                    return false;
+                }
+                final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
+                waitTimeMillis = TIMEOUT_INTERACTION_MILLIS - elapsedTimeMillis;
+                if (waitTimeMillis <= 0) {
+                    return false;
+                }
+                mInstanceLock.wait(waitTimeMillis);
+            } catch (InterruptedException ie) {
+                /* ignore */
+            }
+        }
+    }
+
+    /**
+     * Applies compatibility scale to the info bounds if it is not equal to one.
+     *
+     * @param info The info whose bounds to scale.
+     * @param scale The scale to apply.
+     */
+    private void applyCompatibilityScaleIfNeeded(AccessibilityNodeInfo info, float scale) {
+        if (scale == 1.0f) {
+            return;
+        }
+        Rect bounds = mTempBounds;
+        info.getBoundsInParent(bounds);
+        bounds.scale(scale);
+        info.setBoundsInParent(bounds);
+
+        info.getBoundsInScreen(bounds);
+        bounds.scale(scale);
+        info.setBoundsInScreen(bounds);
+    }
+
+    /**
+     * Handles the message stored if the interacted and interacting
+     * threads are the same otherwise this is a NOP.
+     */
+    private void handleSameThreadMessageIfNeeded() {
+        Message sameProcessMessage = getSameProcessMessageAndClear();
+        if (sameProcessMessage != null) {
+            sameProcessMessage.getTarget().handleMessage(sameProcessMessage);
+        }
+    }
+
+    /**
+     * Finalize an {@link AccessibilityNodeInfo} before passing it to the client.
+     *
+     * @param info The info.
+     * @param connection The current connection to the system.
+     * @param windowScale The source window compatibility scale.
+     */
+    private void finalizeAccessibilityNodeInfo(AccessibilityNodeInfo info,
+            IAccessibilityServiceConnection connection, float windowScale) {
+        if (info != null) {
+            applyCompatibilityScaleIfNeeded(info, windowScale);
+            info.setConnection(connection);
+            info.setSealed(true);
+        }
+    }
+
+    /**
+     * Finalize {@link AccessibilityNodeInfo}s before passing them to the client.
+     *
+     * @param infos The {@link AccessibilityNodeInfo}s.
+     * @param connection The current connection to the system.
+     * @param windowScale The source window compatibility scale.
+     */
+    private void finalizeAccessibilityNodeInfos(List<AccessibilityNodeInfo> infos,
+            IAccessibilityServiceConnection connection, float windowScale) {
+        if (infos != null) {
+            final int infosCount = infos.size();
+            for (int i = 0; i < infosCount; i++) {
+                AccessibilityNodeInfo info = infos.get(i);
+                finalizeAccessibilityNodeInfo(info, connection, windowScale);
+            }
+        }
+    }
+
+    /**
+     * Gets the message stored if the interacted and interacting
+     * threads are the same.
+     *
+     * @return The message.
+     */
+    private Message getSameProcessMessageAndClear() {
+        synchronized (mInstanceLock) {
+            Message result = mSameThreadMessage;
+            mSameThreadMessage = null;
+            return result;
+        }
+    }
+}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 6469b35..f0e8005 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -20,7 +20,6 @@
 import android.graphics.Rect;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.RemoteException;
 import android.text.TextUtils;
 import android.util.SparseIntArray;
 import android.view.View;
@@ -181,13 +180,9 @@
         if (!canPerformRequestOverConnection(childAccessibilityViewId)) {
             return null;
         }
-        try {
-            return mConnection.findAccessibilityNodeInfoByAccessibilityId(mAccessibilityWindowId,
-                    childAccessibilityViewId);
-        } catch (RemoteException re) {
-             /* ignore*/
-        }
-        return null;
+        AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
+        return client.findAccessibilityNodeInfoByAccessibilityId(mConnection,
+                mAccessibilityWindowId, childAccessibilityViewId);
     }
 
     /**
@@ -257,13 +252,9 @@
         if (!canPerformRequestOverConnection(mAccessibilityViewId)) {
             return false;
         }
-        try {
-            return mConnection.performAccessibilityAction(mAccessibilityWindowId,
-                    mAccessibilityViewId, action);
-        } catch (RemoteException e) {
-            /* ignore */
-        }
-        return false;
+        AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
+        return client.performAccessibilityAction(mConnection, mAccessibilityWindowId,
+                mAccessibilityViewId, action);
     }
 
     /**
@@ -284,13 +275,9 @@
         if (!canPerformRequestOverConnection(mAccessibilityViewId)) {
             return Collections.emptyList();
         }
-        try {
-            return mConnection.findAccessibilityNodeInfosByViewText(text, mAccessibilityWindowId,
-                    mAccessibilityViewId);
-        } catch (RemoteException e) {
-            /* ignore */
-        }
-        return Collections.emptyList();
+        AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
+        return client.findAccessibilityNodeInfosByViewText(mConnection, text,
+                mAccessibilityWindowId, mAccessibilityViewId);
     }
 
     /**
@@ -308,13 +295,9 @@
         if (!canPerformRequestOverConnection(mAccessibilityViewId)) {
             return null;
         }
-        try {
-            return mConnection.findAccessibilityNodeInfoByAccessibilityId(
-                    mAccessibilityWindowId, mParentAccessibilityViewId);
-        } catch (RemoteException e) {
-            /* ignore */
-        }
-        return null;
+        AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
+        return client.findAccessibilityNodeInfoByAccessibilityId(mConnection,
+                mAccessibilityWindowId, mParentAccessibilityViewId);
     }
 
     /**
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 210106f..afd7473 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -18,7 +18,6 @@
 
 import android.accessibilityservice.IAccessibilityServiceConnection;
 import android.os.Parcelable;
-import android.os.RemoteException;
 import android.view.View;
 
 import java.util.ArrayList;
@@ -127,13 +126,9 @@
         if (mSourceWindowId == View.NO_ID || mSourceViewId == View.NO_ID || mConnection == null) {
             return null;
         }
-        try {
-            return mConnection.findAccessibilityNodeInfoByAccessibilityId(mSourceWindowId,
-                    mSourceViewId);
-        } catch (RemoteException e) {
-           /* ignore */
-        }
-        return null;
+        AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
+        return client.findAccessibilityNodeInfoByAccessibilityId(mConnection, mSourceWindowId,
+                mSourceViewId);
     }
 
     /**
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionCallback.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionCallback.aidl
new file mode 100644
index 0000000..eeab4f2
--- /dev/null
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionCallback.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.accessibility;
+
+import android.view.accessibility.AccessibilityNodeInfo;
+import java.util.List;
+
+/**
+ * Callback for specifying the result for an asynchronous request made
+ * via calling a method on IAccessibilityInteractionCallback.
+ *
+ * @hide
+ */
+oneway interface IAccessibilityInteractionCallback {
+
+    /**
+     * Sets the result of an async request that returns an {@link AccessibilityNodeInfo}.
+     *
+     * @param infos The result {@link AccessibilityNodeInfo}.
+     * @param interactionId The interaction id to match the result with the request.
+     */
+    void setFindAccessibilityNodeInfoResult(in AccessibilityNodeInfo info, int interactionId);
+
+    /**
+     * Sets the result of an async request that returns {@link AccessibilityNodeInfo}s.
+     *
+     * @param infos The result {@link AccessibilityNodeInfo}s.
+     * @param interactionId The interaction id to match the result with the request.
+     */
+    void setFindAccessibilityNodeInfosResult(in List<AccessibilityNodeInfo> infos,
+        int interactionId);
+
+    /**
+     * Sets the result of a request to perform an accessibility action.
+     *
+     * @param Whether the action was performed.
+     * @param interactionId The interaction id to match the result with the request.
+     */
+    void setPerformAccessibilityActionResult(boolean succeeded, int interactionId);
+}
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index d35186b..535d594 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -28,14 +28,18 @@
 oneway interface IAccessibilityInteractionConnection {
 
     void findAccessibilityNodeInfoByAccessibilityId(int accessibilityViewId, int interactionId,
-        IAccessibilityInteractionConnectionCallback callback);
+        IAccessibilityInteractionConnectionCallback callback,
+        int interrogatingPid, long interrogatingTid);
 
     void findAccessibilityNodeInfoByViewId(int id, int interactionId,
-        IAccessibilityInteractionConnectionCallback callback);
+        IAccessibilityInteractionConnectionCallback callback,
+        int interrogatingPid, long interrogatingTid);
 
     void findAccessibilityNodeInfosByViewText(String text, int accessibilityViewId,
-        int interactionId, IAccessibilityInteractionConnectionCallback callback);
+        int interactionId, IAccessibilityInteractionConnectionCallback callback,
+        int interrogatingPid, long interrogatingTid);
 
     void performAccessibilityAction(int accessibilityId, int action, int interactionId,
-        IAccessibilityInteractionConnectionCallback callback);
+        IAccessibilityInteractionConnectionCallback callback, int interrogatingPid,
+        long interrogatingTid);
 }
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
index 9c5e8dc..c1a3ab7 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
@@ -27,10 +27,28 @@
  */
 oneway interface IAccessibilityInteractionConnectionCallback {
 
+    /**
+     * Sets the result of an async request that returns an {@link AccessibilityNodeInfo}.
+     *
+     * @param infos The result {@link AccessibilityNodeInfo}.
+     * @param interactionId The interaction id to match the result with the request.
+     */
     void setFindAccessibilityNodeInfoResult(in AccessibilityNodeInfo info, int interactionId);
 
+    /**
+     * Sets the result of an async request that returns {@link AccessibilityNodeInfo}s.
+     *
+     * @param infos The result {@link AccessibilityNodeInfo}s.
+     * @param interactionId The interaction id to match the result with the request.
+     */
     void setFindAccessibilityNodeInfosResult(in List<AccessibilityNodeInfo> infos,
         int interactionId);
 
+    /**
+     * Sets the result of a request to perform an accessibility action.
+     *
+     * @param Whether the action was performed.
+     * @param interactionId The interaction id to match the result with the request.
+     */
     void setPerformAccessibilityActionResult(boolean succeeded, int interactionId);
 }
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index b7dfabc..c1eec6f 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -116,7 +116,8 @@
 
     /**
      * Indicates whether the animation transformation should be applied before the
-     * animation starts.
+     * animation starts. The value of this variable is only relevant if mFillEnabled is true;
+     * otherwise it is assumed to be true.
      */
     boolean mFillBefore = true;
 
@@ -127,7 +128,7 @@
     boolean mFillAfter = false;
 
     /**
-     * Indicates whether fillAfter should be taken into account.
+     * Indicates whether fillBefore should be taken into account.
      */
     boolean mFillEnabled = false;    
 
@@ -440,6 +441,7 @@
      */
     public void scaleCurrentDuration(float scale) {
         mDuration = (long) (mDuration * scale);
+        mStartOffset = (long) (mStartOffset * scale);
     }
 
     /**
@@ -505,9 +507,9 @@
     }
 
     /**
-     * If fillEnabled is true, this animation will apply fillBefore and fillAfter.
+     * If fillEnabled is true, this animation will apply the value of fillBefore.
      *
-     * @return true if the animation will take fillBefore and fillAfter into account
+     * @return true if the animation will take fillBefore into account
      * @attr ref android.R.styleable#Animation_fillEnabled
      */
     public boolean isFillEnabled() {
@@ -515,11 +517,11 @@
     }
 
     /**
-     * If fillEnabled is true, the animation will apply the value of fillBefore and
-     * fillAfter. Otherwise, fillBefore and fillAfter are ignored and the animation
-     * transformation is always applied.
+     * If fillEnabled is true, the animation will apply the value of fillBefore.
+     * Otherwise, fillBefore is ignored and the animation
+     * transformation is always applied until the animation ends.
      *
-     * @param fillEnabled true if the animation should take fillBefore and fillAfter into account
+     * @param fillEnabled true if the animation should take the value of fillBefore into account
      * @attr ref android.R.styleable#Animation_fillEnabled
      *
      * @see #setFillBefore(boolean)
@@ -531,7 +533,8 @@
 
     /**
      * If fillBefore is true, this animation will apply its transformation
-     * before the start time of the animation. Defaults to true if not set.
+     * before the start time of the animation. Defaults to true if
+     * {@link #setFillEnabled(boolean)} is not set to true.
      * Note that this applies when using an {@link
      * android.view.animation.AnimationSet AnimationSet} to chain
      * animations. The transformation is not applied before the AnimationSet
@@ -549,10 +552,9 @@
     /**
      * If fillAfter is true, the transformation that this animation performed
      * will persist when it is finished. Defaults to false if not set.
-     * Note that this applies when using an {@link
+     * Note that this applies to individual animations and when using an {@link
      * android.view.animation.AnimationSet AnimationSet} to chain
-     * animations. The transformation is not applied before the AnimationSet
-     * itself starts.
+     * animations.
      *
      * @param fillAfter true if the animation should apply its transformation after it ends
      * @attr ref android.R.styleable#Animation_fillAfter
@@ -674,7 +676,9 @@
 
     /**
      * If fillBefore is true, this animation will apply its transformation
-     * before the start time of the animation.
+     * before the start time of the animation. If fillBefore is false and
+     * {@link #isFillEnabled() fillEnabled} is true, the transformation will not be applied until
+     * the start time of the animation.
      *
      * @return true if the animation applies its transformation before it starts
      * @attr ref android.R.styleable#Animation_fillBefore
diff --git a/core/java/android/view/textservice/SpellCheckerInfo.java b/core/java/android/view/textservice/SpellCheckerInfo.java
index 89cb11c..9d8475d 100644
--- a/core/java/android/view/textservice/SpellCheckerInfo.java
+++ b/core/java/android/view/textservice/SpellCheckerInfo.java
@@ -24,7 +24,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
@@ -71,7 +70,6 @@
         final PackageManager pm = context.getPackageManager();
         int label = 0;
         String settingsActivityComponent = null;
-        int isDefaultResId = 0;
 
         XmlResourceParser parser = null;
         try {
@@ -221,6 +219,15 @@
         return mService.loadIcon(pm);
     }
 
+
+    /**
+     * Return the raw information about the Service implementing this
+     * spell checker.  Do not modify the returned object.
+     */
+    public ServiceInfo getServiceInfo() {
+        return mService.serviceInfo;
+    }
+
     /**
      * Return the class name of an activity that provides a settings UI.
      * You can launch this activity be starting it with
diff --git a/core/java/android/view/textservice/SpellCheckerSubtype.java b/core/java/android/view/textservice/SpellCheckerSubtype.java
index dbd3081..aeb3ba6 100644
--- a/core/java/android/view/textservice/SpellCheckerSubtype.java
+++ b/core/java/android/view/textservice/SpellCheckerSubtype.java
@@ -17,13 +17,16 @@
 package android.view.textservice;
 
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 
 /**
  * This class is used to specify meta information of a subtype contained in a spell checker.
@@ -97,6 +100,48 @@
         return false;
     }
 
+    private static Locale constructLocaleFromString(String localeStr) {
+        if (TextUtils.isEmpty(localeStr))
+            return null;
+        String[] localeParams = localeStr.split("_", 3);
+        // The length of localeStr is guaranteed to always return a 1 <= value <= 3
+        // because localeStr is not empty.
+        if (localeParams.length == 1) {
+            return new Locale(localeParams[0]);
+        } else if (localeParams.length == 2) {
+            return new Locale(localeParams[0], localeParams[1]);
+        } else if (localeParams.length == 3) {
+            return new Locale(localeParams[0], localeParams[1], localeParams[2]);
+        }
+        return null;
+    }
+
+    /**
+     * @param context Context will be used for getting Locale and PackageManager.
+     * @param packageName The package name of the spell checker
+     * @param appInfo The application info of the spell checker
+     * @return a display name for this subtype. The string resource of the label (mSubtypeNameResId)
+     * can have only one %s in it. If there is, the %s part will be replaced with the locale's
+     * display name by the formatter. If there is not, this method simply returns the string
+     * specified by mSubtypeNameResId. If mSubtypeNameResId is not specified (== 0), it's up to the
+     * framework to generate an appropriate display name.
+     */
+    public CharSequence getDisplayName(
+            Context context, String packageName, ApplicationInfo appInfo) {
+        final Locale locale = constructLocaleFromString(mSubtypeLocale);
+        final String localeStr = locale != null ? locale.getDisplayName() : mSubtypeLocale;
+        if (mSubtypeNameResId == 0) {
+            return localeStr;
+        }
+        final CharSequence subtypeName = context.getPackageManager().getText(
+                packageName, mSubtypeNameResId, appInfo);
+        if (!TextUtils.isEmpty(subtypeName)) {
+            return String.format(subtypeName.toString(), localeStr);
+        } else {
+            return localeStr;
+        }
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/core/java/android/view/textservice/SuggestionsInfo.java b/core/java/android/view/textservice/SuggestionsInfo.java
index ed0f89d..62a06b9 100644
--- a/core/java/android/view/textservice/SuggestionsInfo.java
+++ b/core/java/android/view/textservice/SuggestionsInfo.java
@@ -16,6 +16,8 @@
 
 package android.view.textservice;
 
+import com.android.internal.util.ArrayUtils;
+
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -23,7 +25,7 @@
  * This class contains a metadata of suggestions from the text service
  */
 public final class SuggestionsInfo implements Parcelable {
-    private static final String[] EMPTY = new String[0];
+    private static final String[] EMPTY = ArrayUtils.emptyArray(String.class);
 
     /**
      * Flag of the attributes of the suggestions that can be obtained by
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index bb13052..c85b2d9 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -72,27 +72,53 @@
      * languages in settings will be returned.
      * @return the spell checker session of the spell checker
      */
-    // TODO: Add a method to get enabled spell checkers.
-    // TODO: Handle referToSpellCheckerLanguageSettings
     public SpellCheckerSession newSpellCheckerSession(Bundle bundle, Locale locale,
             SpellCheckerSessionListener listener, boolean referToSpellCheckerLanguageSettings) {
         if (listener == null) {
             throw new NullPointerException();
         }
-        // TODO: set a proper locale instead of the dummy locale
-        final String localeString = locale == null ? "en" : locale.toString();
+        if (!referToSpellCheckerLanguageSettings && locale == null) {
+            throw new IllegalArgumentException("Locale should not be null if you don't refer"
+                    + " settings.");
+        }
         final SpellCheckerInfo sci;
         try {
-            sci = sService.getCurrentSpellChecker(localeString);
+            sci = sService.getCurrentSpellChecker(null);
         } catch (RemoteException e) {
             return null;
         }
         if (sci == null) {
             return null;
         }
+        SpellCheckerSubtype subtypeInUse = null;
+        if (referToSpellCheckerLanguageSettings) {
+            subtypeInUse = getCurrentSpellCheckerSubtype(true);
+            if (subtypeInUse == null) {
+                return null;
+            }
+            if (locale != null) {
+                final String subtypeLocale = subtypeInUse.getLocale();
+                final String inputLocale = locale.toString();
+                if (subtypeLocale.length() < 2 || inputLocale.length() < 2
+                        || !subtypeLocale.substring(0, 2).equals(inputLocale.substring(0, 2))) {
+                    return null;
+                }
+            }
+        } else {
+            final String localeStr = locale.toString();
+            for (int i = 0; i < sci.getSubtypeCount(); ++i) {
+                final SpellCheckerSubtype subtype = sci.getSubtypeAt(i);
+                if (subtype.getLocale().equals(localeStr)) {
+                    subtypeInUse = subtype;
+                }
+            }
+        }
+        if (subtypeInUse == null) {
+            return null;
+        }
         final SpellCheckerSession session = new SpellCheckerSession(sci, sService, listener);
         try {
-            sService.getSpellCheckerService(sci.getId(), localeString,
+            sService.getSpellCheckerService(sci.getId(), subtypeInUse.getLocale(),
                     session.getTextServicesSessionListener(),
                     session.getSpellCheckerSessionListener(), bundle);
         } catch (RemoteException e) {
@@ -146,10 +172,11 @@
     /**
      * @hide
      */
-    public SpellCheckerSubtype getCurrentSpellCheckerSubtype() {
+    public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
+            boolean allowImplicitlySelectedSubtype) {
         try {
             // Passing null as a locale for ICS
-            return sService.getCurrentSpellCheckerSubtype(null);
+            return sService.getCurrentSpellCheckerSubtype(null, allowImplicitlySelectedSubtype);
         } catch (RemoteException e) {
             Log.e(TAG, "Error in getCurrentSpellCheckerSubtype: " + e);
             return null;
@@ -161,14 +188,38 @@
      */
     public void setSpellCheckerSubtype(SpellCheckerSubtype subtype) {
         try {
+            final int hashCode;
             if (subtype == null) {
-                throw new NullPointerException("SpellCheckerSubtype is null.");
+                hashCode = 0;
+            } else {
+                hashCode = subtype.hashCode();
             }
-            sService.setCurrentSpellCheckerSubtype(null, subtype.hashCode());
+            sService.setCurrentSpellCheckerSubtype(null, hashCode);
         } catch (RemoteException e) {
             Log.e(TAG, "Error in setSpellCheckerSubtype:" + e);
         }
     }
 
+    /**
+     * @hide
+     */
+    public void setSpellCheckerEnabled(boolean enabled) {
+        try {
+            sService.setSpellCheckerEnabled(enabled);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error in setSpellCheckerSubtype:" + e);
+        }
+    }
 
+    /**
+     * @hide
+     */
+    public boolean isSpellCheckerEnabled() {
+        try {
+            return sService.isSpellCheckerEnabled();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error in setSpellCheckerSubtype:" + e);
+            return false;
+        }
+    }
 }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 5d776fd..8c3c212 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -3451,6 +3451,7 @@
                 }
                 abortAnimation();
                 mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
+                nativeSetIsScrolling(false);
                 if (!mBlockWebkitViewMessages) {
                     WebViewCore.resumePriority();
                     if (!mSelectingText) {
@@ -6382,6 +6383,8 @@
         WebViewCore.reducePriority();
         // to get better performance, pause updating the picture
         WebViewCore.pauseUpdatePicture(mWebViewCore);
+        nativeSetIsScrolling(true);
+
         if (!mDragFromTextInput) {
             nativeHideCursor();
         }
@@ -6478,6 +6481,7 @@
                 || mTouchMode == TOUCH_DRAG_LAYER_MODE) && !mSelectingText) {
             WebViewCore.resumePriority();
             WebViewCore.resumeUpdatePicture(mWebViewCore);
+            nativeSetIsScrolling(false);
         }
         mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
         mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
@@ -9277,6 +9281,7 @@
      * @return True if the layer is successfully scrolled.
      */
     private native boolean  nativeScrollLayer(int layer, int newX, int newY);
+    private native void     nativeSetIsScrolling(boolean isScrolling);
     private native int      nativeGetBackgroundColor();
     native boolean  nativeSetProperty(String key, String value);
     native String   nativeGetProperty(String key);
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 400cdbd..e6ee3cb 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1172,6 +1172,7 @@
                                     loadParams.mMimeType,
                                     loadParams.mEncoding,
                                     loadParams.mHistoryUrl);
+                            nativeContentInvalidateAll();
                             break;
 
                         case STOP_LOADING:
@@ -2070,10 +2071,8 @@
             if (!core.getSettings().enableSmoothTransition()) return;
 
             synchronized (core) {
+                core.nativeSetIsPaused(true);
                 core.mDrawIsPaused = true;
-                if (core.mDrawIsScheduled) {
-                    core.mEventHub.removeMessages(EventHub.WEBKIT_DRAW);
-                }
             }
         }
 
@@ -2082,15 +2081,14 @@
     static void resumeUpdatePicture(WebViewCore core) {
         if (core != null) {
             // if mDrawIsPaused is true, ignore the setting, continue to resume
-            if (!core.mDrawIsPaused
-                    && !core.getSettings().enableSmoothTransition()) return;
+            if (!core.mDrawIsPaused)
+                return;
 
             synchronized (core) {
+                core.nativeSetIsPaused(false);
                 core.mDrawIsPaused = false;
                 // always redraw on resume to reenable gif animations
                 core.mDrawIsScheduled = false;
-                core.nativeContentInvalidateAll();
-                core.contentDraw();
             }
         }
     }
@@ -2127,7 +2125,6 @@
             // only fire an event if this is our first request
             if (mDrawIsScheduled) return;
             mDrawIsScheduled = true;
-            if (mDrawIsPaused) return;
             mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
         }
     }
@@ -2789,6 +2786,7 @@
         return mDeviceOrientationService;
     }
 
+    private native void nativeSetIsPaused(boolean isPaused);
     private native void nativePause();
     private native void nativeResume();
     private native void nativeFreeMemory();
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 7ad5d6c..51506e8 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -368,8 +368,10 @@
         } else if (mState == STATE_EXIT) {
             if (alpha == 0) { // Done with exit
                 setState(STATE_NONE);
+            } else if (mTrackDrawable != null) {
+                mList.invalidate(viewWidth - mThumbW, 0, viewWidth, mList.getHeight());
             } else {
-                mList.invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH);            
+                mList.invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH);
             }
         }
     }
@@ -597,7 +599,7 @@
 
     private int getThumbPositionForListPosition(int firstVisibleItem, int visibleItemCount,
             int totalItemCount) {
-        if (mSectionIndexer == null) {
+        if (mSectionIndexer == null || mListAdapter == null) {
             getSectionsFromIndexer();
         }
         if (mSectionIndexer == null || !mMatchDragPosition) {
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
new file mode 100644
index 0000000..ff13dcb
--- /dev/null
+++ b/core/java/android/widget/SpellChecker.java
@@ -0,0 +1,226 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+package android.widget;
+
+import android.content.Context;
+import android.text.Editable;
+import android.text.Selection;
+import android.text.Spanned;
+import android.text.style.SpellCheckSpan;
+import android.text.style.SuggestionSpan;
+import android.util.Log;
+import android.view.textservice.SpellCheckerSession;
+import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener;
+import android.view.textservice.SuggestionsInfo;
+import android.view.textservice.TextInfo;
+import android.view.textservice.TextServicesManager;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.Locale;
+
+
+/**
+ * Helper class for TextView. Bridge between the TextView and the Dictionnary service.
+ *
+ * @hide
+ */
+public class SpellChecker implements SpellCheckerSessionListener {
+    private static final String LOG_TAG = "SpellChecker";
+    private static final boolean DEBUG_SPELL_CHECK = false;
+    private static final int DELAY_BEFORE_SPELL_CHECK = 400; // milliseconds
+
+    private final TextView mTextView;
+
+    final SpellCheckerSession spellCheckerSession;
+    final int mCookie;
+
+    // Paired arrays for the (id, spellCheckSpan) pair. mIndex is the next available position
+    private int[] mIds;
+    private SpellCheckSpan[] mSpellCheckSpans;
+    // The actual current number of used slots in the above arrays
+    private int mLength;
+
+    private int mSpanSequenceCounter = 0;
+    private Runnable mChecker;
+
+    public SpellChecker(TextView textView) {
+        mTextView = textView;
+
+        final TextServicesManager textServicesManager = (TextServicesManager) textView.getContext().
+                getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
+        spellCheckerSession = textServicesManager.newSpellCheckerSession(
+                null /* not currently used by the textServicesManager */, Locale.getDefault(),
+                this, true /* means use the languages defined in Settings */);
+        mCookie = hashCode();
+
+        // Arbitrary: 4 simultaneous spell check spans. Will automatically double size on demand
+        final int size = ArrayUtils.idealObjectArraySize(4);
+        mIds = new int[size];
+        mSpellCheckSpans = new SpellCheckSpan[size];
+        mLength = 0;
+    }
+
+    public void addSpellCheckSpan(SpellCheckSpan spellCheckSpan) {
+        int length = mIds.length;
+        if (mLength >= length) {
+            final int newSize = length * 2;
+            int[] newIds = new int[newSize];
+            SpellCheckSpan[] newSpellCheckSpans = new SpellCheckSpan[newSize];
+            System.arraycopy(mIds, 0, newIds, 0, length);
+            System.arraycopy(mSpellCheckSpans, 0, newSpellCheckSpans, 0, length);
+            mIds = newIds;
+            mSpellCheckSpans = newSpellCheckSpans;
+        }
+
+        mIds[mLength] = mSpanSequenceCounter++;
+        mSpellCheckSpans[mLength] = spellCheckSpan;
+        mLength++;
+
+        if (DEBUG_SPELL_CHECK) {
+            final Editable mText = (Editable) mTextView.getText();
+            int start = mText.getSpanStart(spellCheckSpan);
+            int end = mText.getSpanEnd(spellCheckSpan);
+            if (start >= 0 && end >= 0) {
+                Log.d(LOG_TAG, "Schedule check " + mText.subSequence(start, end));
+            } else {
+                Log.d(LOG_TAG, "Schedule check   EMPTY!");
+            }
+        }
+
+        scheduleSpellCheck();
+    }
+
+    public void removeSpellCheckSpan(SpellCheckSpan spellCheckSpan) {
+        for (int i = 0; i < mLength; i++) {
+            if (mSpellCheckSpans[i] == spellCheckSpan) {
+                removeAtIndex(i);
+                return;
+            }
+        }
+    }
+
+    private void removeAtIndex(int i) {
+        System.arraycopy(mIds, i + 1, mIds, i, mLength - i - 1);
+        System.arraycopy(mSpellCheckSpans, i + 1, mSpellCheckSpans, i, mLength - i - 1);
+        mLength--;
+    }
+
+    public void onSelectionChanged() {
+        scheduleSpellCheck();
+    }
+
+    private void scheduleSpellCheck() {
+        if (mLength == 0) return;
+        if (mChecker != null) {
+            mTextView.removeCallbacks(mChecker);
+        }
+        if (mChecker == null) {
+            mChecker = new Runnable() {
+                public void run() {
+                  spellCheck();
+                }
+            };
+        }
+        mTextView.postDelayed(mChecker, DELAY_BEFORE_SPELL_CHECK);
+    }
+
+    private void spellCheck() {
+        final Editable editable = (Editable) mTextView.getText();
+        final int selectionStart = Selection.getSelectionStart(editable);
+        final int selectionEnd = Selection.getSelectionEnd(editable);
+
+        TextInfo[] textInfos = new TextInfo[mLength];
+        int textInfosCount = 0;
+
+        for (int i = 0; i < mLength; i++) {
+            SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i];
+
+            if (spellCheckSpan.isSpellCheckInProgress()) continue;
+
+            final int start = editable.getSpanStart(spellCheckSpan);
+            final int end = editable.getSpanEnd(spellCheckSpan);
+
+            // Do not check this word if the user is currently editing it
+            if (start >= 0 && end > start && (selectionEnd < start || selectionStart > end)) {
+                final String word = editable.subSequence(start, end).toString();
+                spellCheckSpan.setSpellCheckInProgress();
+                textInfos[textInfosCount++] = new TextInfo(word, mCookie, mIds[i]);
+            }
+        }
+
+        if (textInfosCount > 0) {
+            if (textInfosCount < mLength) {
+                TextInfo[] textInfosCopy = new TextInfo[textInfosCount];
+                System.arraycopy(textInfos, 0, textInfosCopy, 0, textInfosCount);
+                textInfos = textInfosCopy;
+            }
+            spellCheckerSession.getSuggestions(textInfos, SuggestionSpan.SUGGESTIONS_MAX_SIZE,
+                    false /* TODO Set sequentialWords to true for initial spell check */);
+        }
+    }
+
+    @Override
+    public void onGetSuggestions(SuggestionsInfo[] results) {
+        final Editable editable = (Editable) mTextView.getText();
+        for (int i = 0; i < results.length; i++) {
+            SuggestionsInfo suggestionsInfo = results[i];
+            if (suggestionsInfo.getCookie() != mCookie) continue;
+
+            final int sequenceNumber = suggestionsInfo.getSequence();
+            // Starting from the end, to limit the number of array copy while removing
+            for (int j = mLength - 1; j >= 0; j--) {
+                if (sequenceNumber == mIds[j]) {
+                    SpellCheckSpan spellCheckSpan = mSpellCheckSpans[j];
+                    final int attributes = suggestionsInfo.getSuggestionsAttributes();
+                    boolean isInDictionary =
+                            ((attributes & SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY) > 0);
+                    boolean looksLikeTypo =
+                            ((attributes & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) > 0);
+
+                    if (DEBUG_SPELL_CHECK) {
+                        final int start = editable.getSpanStart(spellCheckSpan);
+                        final int end = editable.getSpanEnd(spellCheckSpan);
+                        Log.d(LOG_TAG, "Result sequence=" + suggestionsInfo.getSequence() + " " +
+                                editable.subSequence(start, end) +
+                                "\t" + (isInDictionary?"IN_DICT" : "NOT_DICT") +
+                                "\t" + (looksLikeTypo?"TYPO" : "NOT_TYPO"));
+                    }
+
+                    if (!isInDictionary && looksLikeTypo) {
+                        String[] suggestions = getSuggestions(suggestionsInfo);
+                        if (suggestions.length > 0) {
+                            SuggestionSpan suggestionSpan = new SuggestionSpan(
+                                    mTextView.getContext(), suggestions,
+                                    SuggestionSpan.FLAG_EASY_CORRECT |
+                                    SuggestionSpan.FLAG_MISSPELLED);
+                            final int start = editable.getSpanStart(spellCheckSpan);
+                            final int end = editable.getSpanEnd(spellCheckSpan);
+                            editable.setSpan(suggestionSpan, start, end,
+                                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+                            // TODO limit to the word rectangle region
+                            mTextView.invalidate();
+
+                            if (DEBUG_SPELL_CHECK) {
+                                String suggestionsString = "";
+                                for (String s : suggestions) { suggestionsString += s + "|"; }
+                                Log.d(LOG_TAG, "  Suggestions for " + sequenceNumber + " " +
+                                    editable.subSequence(start, end)+ "  " + suggestionsString);
+                            }
+                        }
+                    }
+                    editable.removeSpan(spellCheckSpan);
+                }
+            }
+        }
+    }
+
+    private static String[] getSuggestions(SuggestionsInfo suggestionsInfo) {
+        final int len = Math.max(0, suggestionsInfo.getSuggestionsCount());
+        String[] suggestions = new String[len];
+        for (int j = 0; j < len; ++j) {
+            suggestions[j] = suggestionsInfo.getSuggestionAt(j);
+        }
+        return suggestions;
+    }
+}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 662b964..c021c48 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -61,11 +61,6 @@
 import android.text.StaticLayout;
 import android.text.TextDirectionHeuristic;
 import android.text.TextDirectionHeuristics;
-import android.text.TextDirectionHeuristics.AnyStrong;
-import android.text.TextDirectionHeuristics.CharCount;
-import android.text.TextDirectionHeuristics.FirstStrong;
-import android.text.TextDirectionHeuristics.TextDirectionAlgorithm;
-import android.text.TextDirectionHeuristics.TextDirectionHeuristicImpl;
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.text.TextWatcher;
@@ -88,6 +83,7 @@
 import android.text.method.WordIterator;
 import android.text.style.ClickableSpan;
 import android.text.style.ParagraphStyle;
+import android.text.style.SpellCheckSpan;
 import android.text.style.SuggestionSpan;
 import android.text.style.TextAppearanceSpan;
 import android.text.style.URLSpan;
@@ -220,7 +216,6 @@
  * @attr ref android.R.styleable#TextView_imeActionLabel
  * @attr ref android.R.styleable#TextView_imeActionId
  * @attr ref android.R.styleable#TextView_editorExtras
- * @attr ref android.R.styleable#TextView_suggestionsEnabled
  */
 @RemoteView
 public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
@@ -334,7 +329,6 @@
     private int mTextEditSuggestionItemLayout;
     private SuggestionsPopupWindow mSuggestionsPopupWindow;
     private SuggestionRangeSpan mSuggestionRangeSpan;
-    private boolean mSuggestionsEnabled = true;
 
     private int mCursorDrawableRes;
     private final Drawable[] mCursorDrawable = new Drawable[2];
@@ -356,6 +350,8 @@
 
     private WordIterator mWordIterator;
 
+    private SpellChecker mSpellChecker;
+
     // The alignment to pass to Layout, or null if not resolved.
     private Layout.Alignment mLayoutAlignment;
 
@@ -826,10 +822,6 @@
                 mTextIsSelectable = a.getBoolean(attr, false);
                 break;
 
-            case com.android.internal.R.styleable.TextView_suggestionsEnabled:
-                mSuggestionsEnabled = a.getBoolean(attr, true);
-                break;
-
             case com.android.internal.R.styleable.TextView_textAllCaps:
                 allCaps = a.getBoolean(attr, false);
                 break;
@@ -3100,18 +3092,19 @@
         }
 
         boolean needEditableForNotification = false;
+        boolean startSpellCheck = false;
 
         if (mListeners != null && mListeners.size() != 0) {
             needEditableForNotification = true;
         }
 
-        if (type == BufferType.EDITABLE || mInput != null ||
-            needEditableForNotification) {
+        if (type == BufferType.EDITABLE || mInput != null || needEditableForNotification) {
             Editable t = mEditableFactory.newEditable(text);
             text = t;
             setFilters(t, mFilters);
             InputMethodManager imm = InputMethodManager.peekInstance();
             if (imm != null) imm.restartInput(this);
+            startSpellCheck = true;
         } else if (type == BufferType.SPANNABLE || mMovement != null) {
             text = mSpannableFactory.newSpannable(text);
         } else if (!(text instanceof CharWrapper)) {
@@ -3200,6 +3193,10 @@
         sendOnTextChanged(text, 0, oldlen, textLength);
         onTextChanged(text, 0, oldlen, textLength);
 
+        if (startSpellCheck) {
+            updateSpellCheckSpans(0, textLength);
+        }
+
         if (needEditableForNotification) {
             sendAfterTextChanged((Editable) text);
         }
@@ -4791,8 +4788,7 @@
             selEnd = getSelectionEnd();
 
             if (selStart >= 0) {
-                if (mHighlightPath == null)
-                    mHighlightPath = new Path();
+                if (mHighlightPath == null) mHighlightPath = new Path();
 
                 if (selStart == selEnd) {
                     if (isCursorVisible() &&
@@ -4998,6 +4994,7 @@
             } else {
                 // Selection extends across multiple lines -- the focused
                 // rect covers the entire width.
+                if (mHighlightPath == null) mHighlightPath = new Path();
                 if (mHighlightPathBogus) {
                     mHighlightPath.reset();
                     mLayout.getSelectionPath(selStart, selEnd, mHighlightPath);
@@ -7113,8 +7110,9 @@
      * to turn off ellipsizing.
      *
      * If {@link #setMaxLines} has been used to set two or more lines,
-     * {@link TextUtils.TruncateAt#END} and {@link TextUtils.TruncateAt#MARQUEE}
-     * are only supported (other ellipsizing types will not do anything).
+     * {@link android.text.TextUtils.TruncateAt#END} and
+     * {@link android.text.TextUtils.TruncateAt#MARQUEE}* are only supported
+     * (other ellipsizing types will not do anything).
      *
      * @attr ref android.R.styleable#TextView_ellipsize
      */
@@ -7376,7 +7374,7 @@
      * @param lengthAfter The length of the replacement modified text
      */
     protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
-        // intentionally empty
+        // intentionally empty, template pattern method can be overridden by subclasses
     }
 
     /**
@@ -7388,6 +7386,9 @@
      */
     protected void onSelectionChanged(int selStart, int selEnd) {
         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
+        if (mSpellChecker != null) {
+            mSpellChecker.onSelectionChanged();
+        }
     }
 
     /**
@@ -7422,8 +7423,7 @@
         }
     }
 
-    private void sendBeforeTextChanged(CharSequence text, int start, int before,
-                                   int after) {
+    private void sendBeforeTextChanged(CharSequence text, int start, int before, int after) {
         if (mListeners != null) {
             final ArrayList<TextWatcher> list = mListeners;
             final int count = list.size();
@@ -7431,14 +7431,32 @@
                 list.get(i).beforeTextChanged(text, start, before, after);
             }
         }
+
+        // The spans that are inside or intersect the modified region no longer make sense
+        removeIntersectingSpans(start, start + before, SpellCheckSpan.class);
+        removeIntersectingSpans(start, start + before, SuggestionSpan.class);
+    }
+
+    // Removes all spans that are inside or actually overlap the start..end range
+    private <T> void removeIntersectingSpans(int start, int end, Class<T> type) {
+        if (!(mText instanceof Editable)) return;
+        Editable text = (Editable) mText;
+
+        T[] spans = text.getSpans(start, end, type);
+        final int length = spans.length;
+        for (int i = 0; i < length; i++) {
+            final int s = text.getSpanStart(spans[i]);
+            final int e = text.getSpanEnd(spans[i]);
+            if (e == start || s == end) break;
+            text.removeSpan(spans[i]);
+        }
     }
 
     /**
      * Not private so it can be called from an inner class without going
      * through a thunk.
      */
-    void sendOnTextChanged(CharSequence text, int start, int before,
-                                   int after) {
+    void sendOnTextChanged(CharSequence text, int start, int before, int after) {
         if (mListeners != null) {
             final ArrayList<TextWatcher> list = mListeners;
             final int count = list.size();
@@ -7486,6 +7504,11 @@
         sendOnTextChanged(buffer, start, before, after);
         onTextChanged(buffer, start, before, after);
 
+        // The WordIterator text change listener may be called after this one.
+        // Make sure this changed text is rescanned before the iterator is used on it.
+        getWordIterator().forceUpdate();
+        updateSpellCheckSpans(start, start + after);
+
         // Hide the controllers if the amount of content changed
         if (before != after) {
             hideControllers();
@@ -7573,7 +7596,7 @@
                 }
             }
         }
-        
+
         if (what instanceof ParcelableSpan) {
             // If this is a span that can be sent to a remote process,
             // the current extract editor would be interested in it.
@@ -7603,10 +7626,96 @@
                 }
             }
         }
+
+        if (what instanceof SpellCheckSpan) {
+            if (newStart < 0) {
+                getSpellChecker().removeSpellCheckSpan((SpellCheckSpan) what);
+            } else if (oldStart < 0) {
+                getSpellChecker().addSpellCheckSpan((SpellCheckSpan) what);
+            }
+        }
     }
 
-    private class ChangeWatcher
-    implements TextWatcher, SpanWatcher {
+    /**
+     * Create new SpellCheckSpans on the modified region.
+     */
+    private void updateSpellCheckSpans(int start, int end) {
+        if (!(mText instanceof Editable) || !isSuggestionsEnabled()) return;
+        Editable text = (Editable) mText;
+
+        WordIterator wordIterator = getWordIterator();
+        wordIterator.setCharSequence(text);
+
+        // Move back to the beginning of the current word, if any
+        int wordStart = wordIterator.preceding(start);
+        int wordEnd;
+        if (wordStart == BreakIterator.DONE) {
+            wordEnd = wordIterator.following(start);
+            if (wordEnd != BreakIterator.DONE) {
+                wordStart = wordIterator.getBeginning(wordEnd);
+            }
+        } else {
+            wordEnd = wordIterator.getEnd(wordStart);
+        }
+        if (wordEnd == BreakIterator.DONE) {
+            return;
+        }
+
+        // Iterate over the newly added text and schedule new SpellCheckSpans
+        while (wordStart <= end) {
+            if (wordEnd >= start) {
+                // A word across the interval boundaries must remove boundary edition spans
+                if (wordStart < start && wordEnd > start) {
+                    removeEditionSpansAt(start, text);
+                }
+
+                if (wordStart < end && wordEnd > end) {
+                    removeEditionSpansAt(end, text);
+                }
+
+                // Do not create new boundary spans if they already exist
+                boolean createSpellCheckSpan = true;
+                if (wordEnd == start) {
+                    SpellCheckSpan[] spellCheckSpans = text.getSpans(start, start,
+                            SpellCheckSpan.class);
+                    if (spellCheckSpans.length > 0) createSpellCheckSpan = false;
+                }
+
+                if (wordStart == end) {
+                    SpellCheckSpan[] spellCheckSpans = text.getSpans(end, end,
+                            SpellCheckSpan.class);
+                    if (spellCheckSpans.length > 0) createSpellCheckSpan = false;
+                }
+
+                if (createSpellCheckSpan) {
+                    text.setSpan(new SpellCheckSpan(), wordStart, wordEnd,
+                            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+                }
+            }
+
+            // iterate word by word
+            wordEnd = wordIterator.following(wordEnd);
+            if (wordEnd == BreakIterator.DONE) return;
+            wordStart = wordIterator.getBeginning(wordEnd);
+            if (wordStart == BreakIterator.DONE) {
+                Log.e(LOG_TAG, "Unable to find word beginning from " + wordEnd + "in " + mText);
+                return;
+            }
+        }
+    }
+
+    private static void removeEditionSpansAt(int offset, Editable text) {
+        SuggestionSpan[] suggestionSpans = text.getSpans(offset, offset, SuggestionSpan.class);
+        for (int i = 0; i < suggestionSpans.length; i++) {
+            text.removeSpan(suggestionSpans[i]);
+        }
+        SpellCheckSpan[] spellCheckSpans = text.getSpans(offset, offset, SpellCheckSpan.class);
+        for (int i = 0; i < spellCheckSpans.length; i++) {
+            text.removeSpan(spellCheckSpans[i]);
+        }
+    }
+
+    private class ChangeWatcher implements TextWatcher, SpanWatcher {
 
         private CharSequence mBeforeText;
 
@@ -7631,8 +7740,7 @@
             TextView.this.handleTextChanged(buffer, start, before, after);
 
             if (AccessibilityManager.getInstance(mContext).isEnabled() &&
-                    (isFocused() || isSelected() &&
-                    isShown())) {
+                    (isFocused() || isSelected() && isShown())) {
                 sendAccessibilityEventTypeViewTextChanged(mBeforeText, start, before, after);
                 mBeforeText = null;
             }
@@ -7642,8 +7750,7 @@
             if (DEBUG_EXTRACT) Log.v(LOG_TAG, "afterTextChanged: " + buffer);
             TextView.this.sendAfterTextChanged(buffer);
 
-            if (MetaKeyKeyListener.getMetaState(buffer,
-                                 MetaKeyKeyListener.META_SELECTING) != 0) {
+            if (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0) {
                 MetaKeyKeyListener.stopSelecting(TextView.this, buffer);
             }
         }
@@ -7841,17 +7948,20 @@
             if (mInputContentType != null) {
                 mInputContentType.enterDown = false;
             }
+
             hideControllers();
-            removeAllSuggestionSpans();
+
+            removeSpans(0, mText.length(), SuggestionSpan.class);
+            removeSpans(0, mText.length(), SpellCheckSpan.class);
         }
 
         startStopMarquee(hasWindowFocus);
     }
 
-    private void removeAllSuggestionSpans() {
+    private void removeSpans(int start, int end, Class<?> type) {
         if (mText instanceof Editable) {
             Editable editable = ((Editable) mText);
-            SuggestionSpan[] spans = editable.getSpans(0, mText.length(), SuggestionSpan.class);
+            Object[] spans = editable.getSpans(start, end, type);
             final int length = spans.length;
             for (int i = 0; i < length; i++) {
                 editable.removeSpan(spans[i]);
@@ -7969,6 +8079,8 @@
                         }
                     }
                 }
+
+                handled = true;
             }
 
             if (handled) {
@@ -7980,11 +8092,22 @@
     }
 
     /**
+     * @return <code>true</code> if the cursor/current selection overlaps a {@link SuggestionSpan}.
+     */
+    private boolean isCursorInsideSuggestionSpan() {
+        if (!(mText instanceof Spannable)) return false;
+
+        SuggestionSpan[] suggestionSpans = ((Spannable) mText).getSpans(getSelectionStart(),
+                getSelectionEnd(), SuggestionSpan.class);
+        return (suggestionSpans.length > 0);
+    }
+
+    /**
      * @return <code>true</code> if the cursor is inside an {@link SuggestionSpan} with
      * {@link SuggestionSpan#FLAG_EASY_CORRECT} set.
      */
     private boolean isCursorInsideEasyCorrectionSpan() {
-        Spannable spannable = (Spannable) TextView.this.mText;
+        Spannable spannable = (Spannable) mText;
         SuggestionSpan[] suggestionSpans = spannable.getSpans(getSelectionStart(),
                 getSelectionEnd(), SuggestionSpan.class);
         for (int i = 0; i < suggestionSpans.length; i++) {
@@ -8445,16 +8568,14 @@
             selectionStart = ((Spanned) mText).getSpanStart(url);
             selectionEnd = ((Spanned) mText).getSpanEnd(url);
         } else {
-            if (mWordIterator == null) {
-                mWordIterator = new WordIterator();
-            }
-            // WordIerator handles text changes, this is a no-op if text in unchanged.
-            mWordIterator.setCharSequence(mText);
+            WordIterator wordIterator = getWordIterator();
+            // WordIterator handles text changes, this is a no-op if text in unchanged.
+            wordIterator.setCharSequence(mText);
 
-            selectionStart = mWordIterator.getBeginning(minOffset);
+            selectionStart = wordIterator.getBeginning(minOffset);
             if (selectionStart == BreakIterator.DONE) return false;
 
-            selectionEnd = mWordIterator.getEnd(maxOffset);
+            selectionEnd = wordIterator.getEnd(maxOffset);
             if (selectionEnd == BreakIterator.DONE) return false;
         }
 
@@ -8462,6 +8583,20 @@
         return true;
     }
 
+    WordIterator getWordIterator() {
+        if (mWordIterator == null) {
+            mWordIterator = new WordIterator();
+        }
+        return mWordIterator;
+    }
+
+    private SpellChecker getSpellChecker() {
+        if (mSpellChecker == null) {
+            mSpellChecker = new SpellChecker(this);
+        }
+        return mSpellChecker;
+    }
+
     private long getLastTouchOffsets() {
         int minOffset, maxOffset;
 
@@ -8790,7 +8925,7 @@
             final int offset = getOffsetForPosition(mLastDownPositionX, mLastDownPositionY);
             stopSelectionActionMode();
             Selection.setSelection((Spannable) mText, offset);
-            getInsertionController().showImmediately();
+            getInsertionController().showWithActionPopup();
             handled = true;
         }
 
@@ -9067,10 +9202,12 @@
     }
 
     private class SuggestionsPopupWindow extends PinnedPopupWindow implements OnClickListener {
-        private static final int MAX_NUMBER_SUGGESTIONS = 5;
+        private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE;
         private static final int NO_SUGGESTIONS = -1;
+        private static final float AVERAGE_HIGHLIGHTS_PER_SUGGESTION = 1.4f;
         private WordIterator mSuggestionWordIterator;
-        private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan[0];
+        private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan
+                [(int) (AVERAGE_HIGHLIGHTS_PER_SUGGESTION * MAX_NUMBER_SUGGESTIONS)];
 
         @Override
         protected void createPopupWindow() {
@@ -9149,9 +9286,10 @@
         @Override
         public void show() {
             if (!(mText instanceof Editable)) return;
-            updateSuggestions();
 
-            super.show();
+            if (updateSuggestions()) {
+                super.show();
+            }
         }
 
         @Override
@@ -9179,7 +9317,7 @@
             }
         }
 
-        private void updateSuggestions() {
+        private boolean updateSuggestions() {
             Spannable spannable = (Spannable)TextView.this.mText;
             SuggestionSpan[] suggestionSpans = getSuggestionSpans();
 
@@ -9217,22 +9355,15 @@
                 }
             }
 
-            if (totalNbSuggestions == 0) {
-                // TODO Replace by final text, use a dedicated layout, add a fade out timer...
-                TextView textView = (TextView) mContentView.getChildAt(0);
-                textView.setText("No suggestions available");
-                SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
-                suggestionInfo.spanStart = NO_SUGGESTIONS;
-                totalNbSuggestions++;
-            } else {
-                if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan();
-                ((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd,
-                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            if (totalNbSuggestions == 0) return false;
 
-                for (int i = 0; i < totalNbSuggestions; i++) {
-                    final TextView textView = (TextView) mContentView.getChildAt(i);
-                    highlightTextDifferences(textView, spanUnionStart, spanUnionEnd);
-                }
+            if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan();
+            ((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd,
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+            for (int i = 0; i < totalNbSuggestions; i++) {
+                final TextView textView = (TextView) mContentView.getChildAt(i);
+                highlightTextDifferences(textView, spanUnionStart, spanUnionEnd);
             }
 
             for (int i = 0; i < totalNbSuggestions; i++) {
@@ -9241,6 +9372,27 @@
             for (int i = totalNbSuggestions; i < MAX_NUMBER_SUGGESTIONS; i++) {
                 mContentView.getChildAt(i).setVisibility(GONE);
             }
+
+            return true;
+        }
+
+        private void onDictionarySuggestionsReceived(String[] suggestions) {
+            if (suggestions.length == 0) {
+                // TODO Actual implementation of this feature
+                suggestions = new String[] {"Add to dictionary"};
+            }
+
+            WordIterator wordIterator = getWordIterator();
+            wordIterator.setCharSequence(mText);
+
+            final int pos = getSelectionStart();
+            int wordStart = wordIterator.getBeginning(pos);
+            int wordEnd = wordIterator.getEnd(pos);
+
+            SuggestionSpan suggestionSpan = new SuggestionSpan(getContext(), suggestions, 0);
+            ((Editable) mText).setSpan(suggestionSpan, wordStart, wordEnd,
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            show();
         }
 
         private long[] getWordLimits(CharSequence text) {
@@ -9422,6 +9574,15 @@
                     final String originalText = mText.subSequence(spanStart, spanEnd).toString();
                     ((Editable) mText).replace(spanStart, spanEnd, suggestion);
 
+                    // A replacement on a misspelled text removes the misspelled flag.
+                    // TODO restore the flag if the misspelled word is selected back?
+                    int suggestionSpanFlags = suggestionInfo.suggestionSpan.getFlags();
+                    if ((suggestionSpanFlags & SuggestionSpan.FLAG_MISSPELLED) > 0) {
+                        suggestionSpanFlags &= ~(SuggestionSpan.FLAG_MISSPELLED);
+                        suggestionSpanFlags &= ~(SuggestionSpan.FLAG_EASY_CORRECT);
+                        suggestionInfo.suggestionSpan.setFlags(suggestionSpanFlags);
+                    }
+
                     // Notify source IME of the suggestion pick. Do this before swaping texts.
                     if (!TextUtils.isEmpty(
                             suggestionInfo.suggestionSpan.getNotificationTargetClassName())) {
@@ -9471,53 +9632,46 @@
 
     boolean areSuggestionsShown() {
         return mSuggestionsPopupWindow != null && mSuggestionsPopupWindow.isShowing();
-    } 
+    }
+
+    void onDictionarySuggestionsReceived(String[] suggestions) {
+        if (mSuggestionsPopupWindow != null) {
+            mSuggestionsPopupWindow.onDictionarySuggestionsReceived(suggestions);
+        }
+    }
 
     /**
-     * Some parts of the text can have alternate suggestion text attached. This is typically done by
-     * the IME by adding {@link SuggestionSpan}s to the text.
+     * Return whether or not suggestions are enabled on this TextView. The suggestions are generated
+     * by the IME or by the spell checker as the user types. This is done by adding
+     * {@link SuggestionSpan}s to the text.
      *
      * When suggestions are enabled (default), this list of suggestions will be displayed when the
-     * user double taps on these parts of the text. No suggestions are displayed when this value is
-     * false. Use {@link #setSuggestionsEnabled(boolean)} to change this value.
+     * user asks for them on these parts of the text. This value depends on the inputType of this
+     * TextView.
      *
-     * Note that suggestions are only enabled for a subset of input types. In addition to setting
-     * this flag to <code>true</code> using {@link #setSuggestionsEnabled(boolean)} or the
-     * <code>android:suggestionsEnabled</code> xml attribute, this method will return
-     * <code>true</code> only if the class of your input type is {@link InputType#TYPE_CLASS_TEXT}.
-     * In addition, the type variation must also be one of
+     * The class of the input type must be {@link InputType#TYPE_CLASS_TEXT}.
+     *
+     * In addition, the type variation must be one of
      * {@link InputType#TYPE_TEXT_VARIATION_NORMAL},
      * {@link InputType#TYPE_TEXT_VARIATION_EMAIL_SUBJECT},
      * {@link InputType#TYPE_TEXT_VARIATION_LONG_MESSAGE},
      * {@link InputType#TYPE_TEXT_VARIATION_SHORT_MESSAGE} or
      * {@link InputType#TYPE_TEXT_VARIATION_WEB_EDIT_TEXT}.
      *
-     * @return true if the suggestions popup window is enabled.
+     * And finally, the {@link InputType#TYPE_TEXT_FLAG_NO_SUGGESTIONS} flag must <i>not</i> be set.
      *
-     * @attr ref android.R.styleable#TextView_suggestionsEnabled
+     * @return true if the suggestions popup window is enabled, based on the inputType.
      */
     public boolean isSuggestionsEnabled() {
-        if (!mSuggestionsEnabled) return false;
         if ((mInputType & InputType.TYPE_MASK_CLASS) != InputType.TYPE_CLASS_TEXT) return false;
+        if ((mInputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) > 0) return false;
+
         final int variation = mInputType & EditorInfo.TYPE_MASK_VARIATION;
-        if (variation == EditorInfo.TYPE_TEXT_VARIATION_NORMAL ||
+        return (variation == EditorInfo.TYPE_TEXT_VARIATION_NORMAL ||
                 variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT ||
                 variation == EditorInfo.TYPE_TEXT_VARIATION_LONG_MESSAGE ||
                 variation == EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE ||
-                variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) return true;
-
-        return false;
-    }
-
-    /**
-     * Enables or disables the suggestion popup. See {@link #isSuggestionsEnabled()}.
-     *
-     * @param enabled Whether or not suggestions are enabled.
-     *
-     * @attr ref android.R.styleable#TextView_suggestionsEnabled
-     */
-    public void setSuggestionsEnabled(boolean enabled) {
-        mSuggestionsEnabled = enabled;
+                variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT);
     }
 
     /**
@@ -9787,11 +9941,11 @@
         @Override
         public void show() {
             boolean canPaste = canPaste();
-            boolean suggestionsEnabled = isSuggestionsEnabled();
+            boolean canSuggest = isSuggestionsEnabled() && isCursorInsideSuggestionSpan();
             mPasteTextView.setVisibility(canPaste ? View.VISIBLE : View.GONE);
-            mReplaceTextView.setVisibility(suggestionsEnabled ? View.VISIBLE : View.GONE);
+            mReplaceTextView.setVisibility(canSuggest ? View.VISIBLE : View.GONE);
 
-            if (!canPaste && !suggestionsEnabled) return;
+            if (!canPaste && !canSuggest) return;
 
             super.show();
         }
@@ -9802,6 +9956,9 @@
                 onTextContextMenuItem(ID_PASTE);
                 hide();
             } else if (view == mReplaceTextView) {
+                final int middle = (getSelectionStart() + getSelectionEnd()) / 2;
+                stopSelectionActionMode();
+                Selection.setSelection((Spannable) mText, middle);
                 showSuggestions();
             }
         }
@@ -10133,17 +10290,18 @@
         @Override
         public void show() {
             super.show();
-            hideAfterDelay();
-        }
-
-        public void show(int delayBeforeShowActionPopup) {
-            show();
 
             final long durationSinceCutOrCopy = SystemClock.uptimeMillis() - sLastCutOrCopyTime;
             if (durationSinceCutOrCopy < RECENT_CUT_COPY_DURATION) {
-                delayBeforeShowActionPopup = 0;
+                showActionPopupWindow(0);
             }
-            showActionPopupWindow(delayBeforeShowActionPopup);
+
+            hideAfterDelay();
+        }
+
+        public void showWithActionPopup() {
+            show();
+            showActionPopupWindow(0);
         }
 
         private void hideAfterDelay() {
@@ -10194,7 +10352,7 @@
                                 // Tapping on the handle dismisses the displayed action popup
                                 mActionPopupWindow.hide();
                             } else {
-                                show(0);
+                                showWithActionPopup();
                             }
                         }
                     }
@@ -10349,16 +10507,14 @@
     }
 
     private class InsertionPointCursorController implements CursorController {
-        private static final int DELAY_BEFORE_PASTE_ACTION = 1600;
-
         private InsertionHandleView mHandle;
 
         public void show() {
-            getHandle().show(DELAY_BEFORE_PASTE_ACTION);
+            getHandle().show();
         }
 
-        public void showImmediately() {
-            getHandle().show(0);
+        public void showWithActionPopup() {
+            getHandle().showWithActionPopup();
         }
 
         public void hide() {
@@ -10390,7 +10546,7 @@
     }
 
     private class SelectionModifierCursorController implements CursorController {
-        private static final int DELAY_BEFORE_REPLACE_ACTION = 1200;
+        private static final int DELAY_BEFORE_REPLACE_ACTION = 200; // milliseconds
         // The cursor controller handles, lazily created when shown.
         private SelectionStartHandleView mStartHandle;
         private SelectionEndHandleView mEndHandle;
@@ -10730,6 +10886,11 @@
 
     @Override
     protected void resolveTextDirection() {
+        if (hasPasswordTransformationMethod()) {
+            mTextDir = TextDirectionHeuristics.LOCALE;
+            return;
+        }
+
         // Always need to resolve layout direction first
         final boolean defaultIsRtl = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
 
@@ -10879,8 +11040,8 @@
     private int                     mAutoLinkMask;
     private boolean                 mLinksClickable = true;
 
-    private float                   mSpacingMult = 1;
-    private float                   mSpacingAdd = 0;
+    private float                   mSpacingMult = 1.0f;
+    private float                   mSpacingAdd = 0.0f;
     private boolean                 mTextIsSelectable = false;
 
     private static final int        LINES = 1;
diff --git a/core/java/com/android/internal/textservice/ITextServicesManager.aidl b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
index cc30c176..4882a12 100644
--- a/core/java/com/android/internal/textservice/ITextServicesManager.aidl
+++ b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
@@ -30,12 +30,15 @@
  */
 interface ITextServicesManager {
     SpellCheckerInfo getCurrentSpellChecker(String locale);
-    SpellCheckerSubtype getCurrentSpellCheckerSubtype(String locale);
+    SpellCheckerSubtype getCurrentSpellCheckerSubtype(
+            String locale, boolean allowImplicitlySelectedSubtype);
     oneway void getSpellCheckerService(String sciId, in String locale,
             in ITextServicesSessionListener tsListener,
             in ISpellCheckerSessionListener scListener, in Bundle bundle);
     oneway void finishSpellCheckerService(in ISpellCheckerSessionListener listener);
     oneway void setCurrentSpellChecker(String locale, String sciId);
     oneway void setCurrentSpellCheckerSubtype(String locale, int hashCode);
+    oneway void setSpellCheckerEnabled(boolean enabled);
+    boolean isSpellCheckerEnabled();
     SpellCheckerInfo[] getEnabledSpellCheckers();
 }
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index d613921..b355c41 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -31,6 +31,7 @@
     private static final String TAG = "ActionMenuView";
     
     static final int MIN_CELL_SIZE = 56; // dips
+    static final int GENERATED_ITEM_PADDING = 4; // dips
 
     private MenuBuilder mMenu;
 
@@ -39,6 +40,7 @@
     private boolean mFormatItems;
     private int mFormatItemsWidth;
     private int mMinCellSize;
+    private int mGeneratedItemPadding;
     private int mMeasuredExtraWidth;
 
     public ActionMenuView(Context context) {
@@ -48,7 +50,9 @@
     public ActionMenuView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setBaselineAligned(false);
-        mMinCellSize = (int) (MIN_CELL_SIZE * context.getResources().getDisplayMetrics().density);
+        final float density = context.getResources().getDisplayMetrics().density;
+        mMinCellSize = (int) (MIN_CELL_SIZE * density);
+        mGeneratedItemPadding = (int) (GENERATED_ITEM_PADDING * density);
     }
 
     public void setPresenter(ActionMenuPresenter presenter) {
@@ -133,8 +137,15 @@
             final View child = getChildAt(i);
             if (child.getVisibility() == GONE) continue;
 
+            final boolean isGeneratedItem = child instanceof ActionMenuItemView;
             visibleItemCount++;
 
+            if (isGeneratedItem) {
+                // Reset padding for generated menu item views; it may change below
+                // and views are recycled.
+                child.setPadding(mGeneratedItemPadding, 0, mGeneratedItemPadding, 0);
+            }
+
             final LayoutParams lp = (LayoutParams) child.getLayoutParams();
             lp.expanded = false;
             lp.extraPixels = 0;
@@ -142,6 +153,7 @@
             lp.expandable = false;
             lp.leftMargin = 0;
             lp.rightMargin = 0;
+            lp.preventEdgeOffset = isGeneratedItem && ((ActionMenuItemView) child).hasText();
 
             // Overflow always gets 1 cell. No more, no less.
             final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining;
@@ -158,6 +170,10 @@
             if (cellsUsed == 1) smallestItemsAt |= (1 << i);
         }
 
+        // When we have overflow and a single expanded (text) item, we want to try centering it
+        // visually in the available space even though overflow consumes some of it.
+        final boolean centerSingleExpandedItem = hasOverflow && visibleItemCount == 2;
+
         // Divide space for remaining cells if we have items that can expand.
         // Try distributing whole leftover cells to smaller items first.
 
@@ -184,16 +200,27 @@
                 }
             }
 
-            if (minCellsItemCount > cellsRemaining) break; // Couldn't expand anything evenly. Stop.
-
             // Items that get expanded will always be in the set of smallest items when we're done.
             smallestItemsAt |= minCellsAt;
 
-            for (int i = 0; i < childCount; i++) {
-                if ((minCellsAt & (1 << i)) == 0) continue;
+            if (minCellsItemCount > cellsRemaining) break; // Couldn't expand anything evenly. Stop.
 
+            // We have enough cells, all minimum size items will be incremented.
+            minCells++;
+
+            for (int i = 0; i < childCount; i++) {
                 final View child = getChildAt(i);
                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                if ((minCellsAt & (1 << i)) == 0) {
+                    // If this item is already at our small item count, mark it for later.
+                    if (lp.cellsUsed == minCells) smallestItemsAt |= 1 << i;
+                    continue;
+                }
+
+                if (centerSingleExpandedItem && lp.preventEdgeOffset && cellsRemaining == 1) {
+                    // Add padding to this item such that it centers.
+                    child.setPadding(mGeneratedItemPadding + cellSize, 0, mGeneratedItemPadding, 0);
+                }
                 lp.cellsUsed++;
                 lp.expanded = true;
                 cellsRemaining--;
@@ -207,16 +234,18 @@
 
         final boolean singleItem = !hasOverflow && visibleItemCount == 1;
         if (cellsRemaining > 0 && smallestItemsAt != 0 &&
-                (cellsRemaining < visibleItemCount - 1 || singleItem)) {
+                (cellsRemaining < visibleItemCount - 1 || singleItem || maxCellsUsed > 1)) {
             float expandCount = Long.bitCount(smallestItemsAt);
 
             if (!singleItem) {
                 // The items at the far edges may only expand by half in order to pin to either side.
                 if ((smallestItemsAt & 1) != 0) {
-                    expandCount -= 0.5f;
+                    LayoutParams lp = (LayoutParams) getChildAt(0).getLayoutParams();
+                    if (!lp.preventEdgeOffset) expandCount -= 0.5f;
                 }
                 if ((smallestItemsAt & (1 << (childCount - 1))) != 0) {
-                    expandCount -= 0.5f;
+                    LayoutParams lp = ((LayoutParams) getChildAt(childCount - 1).getLayoutParams());
+                    if (!lp.preventEdgeOffset) expandCount -= 0.5f;
                 }
             }
 
@@ -232,7 +261,7 @@
                     // If this is one of our views, expand and measure at the larger size.
                     lp.extraPixels = extraPixels;
                     lp.expanded = true;
-                    if (i == 0) {
+                    if (i == 0 && !lp.preventEdgeOffset) {
                         // First item gets part of its new padding pushed out of sight.
                         // The last item will get this implicitly from layout.
                         lp.leftMargin = -extraPixels / 2;
@@ -496,6 +525,8 @@
         public int extraPixels;
         @ViewDebug.ExportedProperty(category = "layout")
         public boolean expandable;
+        @ViewDebug.ExportedProperty(category = "layout")
+        public boolean preventEdgeOffset;
 
         public boolean expanded;
 
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 4efb29f..8988c9f 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -826,15 +826,18 @@
             rightOfCenter = Math.max(0, rightOfCenter - mMenuView.getMeasuredWidth());
         }
 
-        if (mExpandedActionView == null) {
-            boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
-                    (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
-            if (showTitle) {
-                availableWidth = measureChildView(mTitleLayout, availableWidth,
-                        MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
-                leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
-            }
+        if (mIndeterminateProgressView != null &&
+                mIndeterminateProgressView.getVisibility() != GONE) {
+            availableWidth = measureChildView(mIndeterminateProgressView, availableWidth,
+                    childSpecHeight, 0);
+            rightOfCenter = Math.max(0,
+                    rightOfCenter - mIndeterminateProgressView.getMeasuredWidth());
+        }
 
+        final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
+                (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
+
+        if (mExpandedActionView == null) {
             switch (mNavigationMode) {
                 case ActionBar.NAVIGATION_MODE_LIST:
                     if (mListNavLayout != null) {
@@ -865,14 +868,6 @@
             }
         }
 
-        if (mIndeterminateProgressView != null &&
-                mIndeterminateProgressView.getVisibility() != GONE) {
-            availableWidth = measureChildView(mIndeterminateProgressView, availableWidth,
-                    childSpecHeight, 0);
-            rightOfCenter = Math.max(0,
-                    rightOfCenter - mIndeterminateProgressView.getMeasuredWidth());
-        }
-
         View customView = null;
         if (mExpandedActionView != null) {
             customView = mExpandedActionView;
@@ -922,6 +917,13 @@
             customView.measure(
                     MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode),
                     MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode));
+            availableWidth -= horizontalMargin + customView.getMeasuredWidth();
+        }
+
+        if (mExpandedActionView == null && showTitle) {
+            availableWidth = measureChildView(mTitleLayout, availableWidth,
+                    MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
+            leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
         }
 
         if (mContentHeight <= 0) {
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 6b5ca50..b8f2d6f 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -39,8 +39,6 @@
 #include <binder/IServiceManager.h>
 #include <utils/threads.h>
 
-#include <ScopedUtfChars.h>
-
 #include <android_runtime/AndroidRuntime.h>
 
 //#undef LOGV
@@ -446,25 +444,6 @@
         return result;
     }
 
-    void warnIfStillLive() {
-        JNIEnv* env = javavm_to_jnienv(mVM);
-        if (mObject != NULL) {
-            // Okay, something is wrong -- we have a hard reference to a live death
-            // recipient on the VM side, but the list is being torn down.
-            jclass clazz = env->GetObjectClass(mObject);
-            jmethodID getnameMethod = env->GetMethodID(clazz, "getName", NULL);
-            jstring nameString = (jstring) env->CallObjectMethod(clazz, getnameMethod);
-            if (nameString) {
-                ScopedUtfChars nameUtf(env, nameString);
-                LOGW("BinderProxy is being destroyed but the application did not call "
-                        "unlinkToDeath to unlink all of its death recipients beforehand.  "
-                        "Releasing leaked death recipient: %s", nameUtf.c_str());
-                env->DeleteLocalRef(nameString);
-            }
-            env->DeleteLocalRef(clazz);
-        }
-    }
-
 protected:
     virtual ~JavaDeathRecipient()
     {
@@ -499,10 +478,7 @@
     // to the list are holding references on the list object.  Only when they are torn
     // down can the list header be destroyed.
     if (mList.size() > 0) {
-        List< sp<JavaDeathRecipient> >::iterator iter;
-        for (iter = mList.begin(); iter != mList.end(); iter++) {
-            (*iter)->warnIfStillLive();
-        }
+        LOGE("Retiring DRL %p with extant death recipients\n", this);
     }
 }
 
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index fb5e5fe..bcf8e71 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -222,12 +222,26 @@
     return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
 }
 
+static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
+        OpenGLRenderer* renderer, SkPaint* paint, jint saveFlags) {
+    const android::uirenderer::Rect& bounds(renderer->getClipBounds());
+    return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
+            paint, saveFlags);
+}
+
 static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jint alpha, jint saveFlags) {
     return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
 }
 
+static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz,
+        OpenGLRenderer* renderer, jint alpha, jint saveFlags) {
+    const android::uirenderer::Rect& bounds(renderer->getClipBounds());
+    return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
+            alpha, saveFlags);
+}
+
 // ----------------------------------------------------------------------------
 // Clipping
 // ----------------------------------------------------------------------------
@@ -759,7 +773,9 @@
     { "nGetSaveCount",      "(I)I",            (void*) android_view_GLES20Canvas_getSaveCount },
 
     { "nSaveLayer",         "(IFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayer },
+    { "nSaveLayer",         "(III)I",          (void*) android_view_GLES20Canvas_saveLayerClip },
     { "nSaveLayerAlpha",    "(IFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayerAlpha },
+    { "nSaveLayerAlpha",    "(III)I",          (void*) android_view_GLES20Canvas_saveLayerAlphaClip },
 
     { "nQuickReject",       "(IFFFFI)Z",       (void*) android_view_GLES20Canvas_quickReject },
     { "nClipRect",          "(IFFFFI)Z",       (void*) android_view_GLES20Canvas_clipRectF },
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
index 1b65492..c5adc38 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
index 70c1e262..efcfa26 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
index 9fa19ef..490b6f5 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
index 8384797..57f2026 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/combobox_disabled.png b/core/res/res/drawable-hdpi/combobox_disabled.png
index 50eb45e..85fbc3c 100644
--- a/core/res/res/drawable-hdpi/combobox_disabled.png
+++ b/core/res/res/drawable-hdpi/combobox_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/combobox_nohighlight.png b/core/res/res/drawable-hdpi/combobox_nohighlight.png
index 9d60301..2de2abb 100644
--- a/core/res/res/drawable-hdpi/combobox_nohighlight.png
+++ b/core/res/res/drawable-hdpi/combobox_nohighlight.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_selectall_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_selectall_holo_dark.png
index 5579443..b161361 100644
--- a/core/res/res/drawable-hdpi/ic_menu_selectall_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_selectall_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_selectall_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_selectall_holo_light.png
index 6674914..0a7b364 100644
--- a/core/res/res/drawable-hdpi/ic_menu_selectall_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_selectall_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png
index da28a17..db23635 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png
index 015d30a..269a456 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png
index df7f236..d997b36 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png
index 8950f81..8ed5eb7 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_16_inner_holo.png b/core/res/res/drawable-hdpi/spinner_16_inner_holo.png
index 2af7e810..b59b492 100644
--- a/core/res/res/drawable-hdpi/spinner_16_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_16_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_16_outer_holo.png b/core/res/res/drawable-hdpi/spinner_16_outer_holo.png
index 20fc20a..57b8b31 100644
--- a/core/res/res/drawable-hdpi/spinner_16_outer_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_16_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_20_inner_holo.png b/core/res/res/drawable-hdpi/spinner_20_inner_holo.png
index 74ce1ee..14d26a5 100644
--- a/core/res/res/drawable-hdpi/spinner_20_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_20_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_20_outer_holo.png b/core/res/res/drawable-hdpi/spinner_20_outer_holo.png
index 82b5671..e457a66 100644
--- a/core/res/res/drawable-hdpi/spinner_20_outer_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_20_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_48_inner_holo.png b/core/res/res/drawable-hdpi/spinner_48_inner_holo.png
index 7220c2f..86c036d 100644
--- a/core/res/res/drawable-hdpi/spinner_48_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_48_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_48_outer_holo.png b/core/res/res/drawable-hdpi/spinner_48_outer_holo.png
index 5648af0..ddd3e74 100644
--- a/core/res/res/drawable-hdpi/spinner_48_outer_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_48_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_76_inner_holo.png b/core/res/res/drawable-hdpi/spinner_76_inner_holo.png
index 633df1b..74e7e2e 100644
--- a/core/res/res/drawable-hdpi/spinner_76_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_76_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_76_outer_holo.png b/core/res/res/drawable-hdpi/spinner_76_outer_holo.png
index 1efa5eb..989a18c 100644
--- a/core/res/res/drawable-hdpi/spinner_76_outer_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_76_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_adb.png b/core/res/res/drawable-hdpi/stat_sys_adb.png
index ddb8a71..8e15aba2 100644
--- a/core/res/res/drawable-hdpi/stat_sys_adb.png
+++ b/core/res/res/drawable-hdpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_adb.png b/core/res/res/drawable-ldpi/stat_sys_adb.png
index 86b945b..aec8d90 100644
--- a/core/res/res/drawable-ldpi/stat_sys_adb.png
+++ b/core/res/res/drawable-ldpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
index 86debc4..abf6493 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
index b403e67..71b052b 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
index d06361a..87c62ff 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
index a4dae66..51821fa 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/combobox_disabled.png b/core/res/res/drawable-mdpi/combobox_disabled.png
index 94ad006..ac8a235 100644
--- a/core/res/res/drawable-mdpi/combobox_disabled.png
+++ b/core/res/res/drawable-mdpi/combobox_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/combobox_nohighlight.png b/core/res/res/drawable-mdpi/combobox_nohighlight.png
index 75d642c..9d60e26 100644
--- a/core/res/res/drawable-mdpi/combobox_nohighlight.png
+++ b/core/res/res/drawable-mdpi/combobox_nohighlight.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png
index 0fc20e0..84d4c11 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png
index 2b7a262..d922ef1 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png
index 1410805..8c37c8d 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png
index 34d79f6..e442c28 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_16_inner_holo.png b/core/res/res/drawable-mdpi/spinner_16_inner_holo.png
index 4f6f981..c0f1b20 100644
--- a/core/res/res/drawable-mdpi/spinner_16_inner_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_16_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_16_outer_holo.png b/core/res/res/drawable-mdpi/spinner_16_outer_holo.png
index 07df4cb..0492a62 100644
--- a/core/res/res/drawable-mdpi/spinner_16_outer_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_16_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_20_inner_holo.png b/core/res/res/drawable-mdpi/spinner_20_inner_holo.png
index fab8766..5e141d8 100644
--- a/core/res/res/drawable-mdpi/spinner_20_inner_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_20_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_20_outer_holo.png b/core/res/res/drawable-mdpi/spinner_20_outer_holo.png
index f345311..07ba3f3 100644
--- a/core/res/res/drawable-mdpi/spinner_20_outer_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_20_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_48_inner_holo.png b/core/res/res/drawable-mdpi/spinner_48_inner_holo.png
index 91a29fd..8c27069 100644
--- a/core/res/res/drawable-mdpi/spinner_48_inner_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_48_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_48_outer_holo.png b/core/res/res/drawable-mdpi/spinner_48_outer_holo.png
index 024f0f2..d5f0490 100644
--- a/core/res/res/drawable-mdpi/spinner_48_outer_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_48_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_76_inner_holo.png b/core/res/res/drawable-mdpi/spinner_76_inner_holo.png
index a388434..3e263e8 100644
--- a/core/res/res/drawable-mdpi/spinner_76_inner_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_76_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_76_outer_holo.png b/core/res/res/drawable-mdpi/spinner_76_outer_holo.png
index e81bb06..6eb6d10 100644
--- a/core/res/res/drawable-mdpi/spinner_76_outer_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_76_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_adb.png b/core/res/res/drawable-mdpi/stat_sys_adb.png
index 730d96f..ebedfa3 100644
--- a/core/res/res/drawable-mdpi/stat_sys_adb.png
+++ b/core/res/res/drawable-mdpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/platlogo.png b/core/res/res/drawable-nodpi/platlogo.png
index e619ed5..faabda1 100644
--- a/core/res/res/drawable-nodpi/platlogo.png
+++ b/core/res/res/drawable-nodpi/platlogo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
index a364792..aca0a23 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
index 5a52ad6..7dc088a 100644
--- a/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
index e34ed85..a97c1d3 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
index f76d56b..25d139a 100644
--- a/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/combobox_disabled.png b/core/res/res/drawable-xhdpi/combobox_disabled.png
index 9edf16e..e8ca0b0 100644
--- a/core/res/res/drawable-xhdpi/combobox_disabled.png
+++ b/core/res/res/drawable-xhdpi/combobox_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/combobox_nohighlight.png b/core/res/res/drawable-xhdpi/combobox_nohighlight.png
index 0b58042..d75bb06 100644
--- a/core/res/res/drawable-xhdpi/combobox_nohighlight.png
+++ b/core/res/res/drawable-xhdpi/combobox_nohighlight.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark.9.png
index 3c8979f..9cf9173 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light.9.png
index 45b7adb9b..c8d8a17 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png
index e258284a..e3793f7 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light.9.png
index 5c4bbf5..c0be34f0 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png
index 8f2b8ae..7294519 100644
--- a/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png
index 583e4a2..d43da4e 100644
--- a/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png
index b202d4e..eecac27 100644
--- a/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png
index 34fbbf0..eb91b2c 100644
--- a/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png
index c2df6b4..b1b8232 100644
--- a/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png
index fd202f4..0c15e12 100644
--- a/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png
index 9f2044d..6215e95 100644
--- a/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png
index a416478..0a67fff 100644
--- a/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png
+++ b/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_adb.png b/core/res/res/drawable-xhdpi/stat_sys_adb.png
index 01eb61d..92f8dd4 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_adb.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/layout-sw600dp/preference_list_content.xml b/core/res/res/layout-sw600dp/preference_list_content.xml
deleted file mode 100644
index 08f6453..0000000
--- a/core/res/res/layout-sw600dp/preference_list_content.xml
+++ /dev/null
@@ -1,123 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/layout/list_content.xml
-**
-** Copyright 2006, 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.
-*/
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_height="match_parent"
-    android:layout_width="match_parent">
-
-    <LinearLayout
-        android:orientation="horizontal"
-        android:layout_width="match_parent"
-        android:layout_height="0px"
-        android:layout_marginTop="@dimen/preference_screen_top_margin"
-        android:layout_marginBottom="@dimen/preference_screen_bottom_margin"
-        android:layout_weight="1">
-
-        <LinearLayout
-            android:id="@+id/headers"
-            android:orientation="vertical"
-            android:layout_width="0px"
-            android:layout_height="match_parent"
-            android:layout_marginRight="@dimen/preference_screen_side_margin_negative"
-            android:layout_marginLeft="@dimen/preference_screen_side_margin"
-            android:layout_weight="@integer/preferences_left_pane_weight">
-
-            <ListView android:id="@android:id/list"
-                android:layout_width="match_parent"
-                android:layout_height="0px"
-                android:layout_weight="1"
-                android:paddingLeft="@dimen/preference_screen_header_padding_side"
-                android:paddingRight="@dimen/preference_screen_header_padding_side"
-                android:paddingTop="@dimen/preference_screen_header_vertical_padding"
-                android:paddingBottom="@dimen/preference_screen_header_vertical_padding"
-                android:scrollbarStyle="@integer/preference_screen_header_scrollbarStyle"
-                android:drawSelectorOnTop="false"
-                android:cacheColorHint="@android:color/transparent"
-                android:listPreferredItemHeight="48dp"
-                android:scrollbarAlwaysDrawVerticalTrack="true" />
-
-            <FrameLayout android:id="@+id/list_footer"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="0" />
-
-        </LinearLayout>
-
-        <LinearLayout
-                android:id="@+id/prefs_frame"
-                android:layout_width="0px"
-                android:layout_height="match_parent"
-                android:layout_weight="@integer/preferences_right_pane_weight"
-                android:layout_marginLeft="@dimen/preference_screen_side_margin"
-                android:layout_marginRight="@dimen/preference_screen_side_margin"
-                android:background="?attr/detailsElementBackground"
-                android:orientation="vertical"
-                android:visibility="gone" >
-
-            <!-- Breadcrumb inserted here, in certain screen sizes. In others, it will be an
-                empty layout or just padding, and PreferenceActivity will put the breadcrumbs in
-                the action bar. -->
-            <include layout="@layout/breadcrumbs_in_fragment" />
-
-            <android.preference.PreferenceFrameLayout android:id="@+id/prefs"
-                    android:layout_width="match_parent"
-                    android:layout_height="0dip"
-                    android:layout_weight="1"
-                />
-        </LinearLayout>
-    </LinearLayout>
-
-    <RelativeLayout android:id="@+id/button_bar"
-        android:layout_height="wrap_content"
-        android:layout_width="match_parent"
-        android:layout_weight="0"
-        android:visibility="gone">
-
-        <Button android:id="@+id/back_button"
-            android:layout_width="150dip"
-            android:layout_height="wrap_content"
-            android:layout_margin="5dip"
-            android:layout_alignParentLeft="true"
-            android:text="@string/back_button_label"
-        />
-        <LinearLayout
-            android:orientation="horizontal"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentRight="true">
-
-            <Button android:id="@+id/skip_button"
-                android:layout_width="150dip"
-                android:layout_height="wrap_content"
-                android:layout_margin="5dip"
-                android:text="@string/skip_button_label"
-                android:visibility="gone"
-            />
-
-            <Button android:id="@+id/next_button"
-                android:layout_width="150dip"
-                android:layout_height="wrap_content"
-                android:layout_margin="5dip"
-                android:text="@string/next_button_label"
-            />
-        </LinearLayout>
-    </RelativeLayout>
-</LinearLayout>
diff --git a/core/res/res/layout/grant_credentials_permission.xml b/core/res/res/layout/grant_credentials_permission.xml
index 8b18454..3313590 100644
--- a/core/res/res/layout/grant_credentials_permission.xml
+++ b/core/res/res/layout/grant_credentials_permission.xml
@@ -24,7 +24,7 @@
     android:layout_height="match_parent"
     android:divider="?android:attr/dividerHorizontal"
     android:showDividers="middle"
-    android:dividerPadding="16dip" >
+    android:dividerPadding="0dip" >
 
     <!-- The list of packages that correspond to the requesting UID
     and the account/authtokenType that is being requested -->
@@ -123,20 +123,20 @@
     <LinearLayout
         android:id="@+id/buttons"
         android:layout_width="match_parent"
-        android:layout_height="54dip"
+        android:layout_height="wrap_content"
         style="?android:attr/buttonBarStyle">
 
         <Button
-            android:id="@+id/allow_button"
-            android:text="@string/allow"
+            android:id="@+id/deny_button"
+            android:text="@string/deny"
             android:layout_width="0dip"
             android:layout_height="wrap_content"
             android:layout_weight="2"
             style="?android:attr/buttonBarButtonStyle" />
 
         <Button
-            android:id="@+id/deny_button"
-            android:text="@string/deny"
+            android:id="@+id/allow_button"
+            android:text="@string/allow"
             android:layout_width="0dip"
             android:layout_height="wrap_content"
             android:layout_weight="2"
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index bc86ab7..12df99e 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -151,7 +151,6 @@
             android:background="@drawable/lockscreen_password_field_dark"
             android:textColor="?android:attr/textColorPrimary"
             android:imeOptions="flagNoFullscreen|actionDone"
-            android:suggestionsEnabled="false"
             />
 
         <ImageView android:id="@+id/switch_ime_button"
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index 994c439..6145e47 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -114,7 +114,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="#ffffffff"
             android:imeOptions="actionDone"
-            android:suggestionsEnabled="false"/>
+            />
 
         <ImageView android:id="@+id/switch_ime_button"
             android:layout_width="wrap_content"
diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml
index 62181b5..70bc59a 100644
--- a/core/res/res/layout/preference_list_content.xml
+++ b/core/res/res/layout/preference_list_content.xml
@@ -27,8 +27,6 @@
         android:orientation="horizontal"
         android:layout_width="match_parent"
         android:layout_height="0px"
-        android:layout_marginTop="@dimen/preference_screen_top_margin"
-        android:layout_marginBottom="@dimen/preference_screen_bottom_margin"
         android:layout_weight="1">
 
         <LinearLayout
@@ -48,6 +46,7 @@
                 android:paddingRight="@dimen/preference_screen_header_padding_side"
                 android:paddingTop="@dimen/preference_screen_header_vertical_padding"
                 android:paddingBottom="@dimen/preference_screen_header_vertical_padding"
+                android:clipToPadding="false"
                 android:scrollbarStyle="@integer/preference_screen_header_scrollbarStyle"
                 android:drawSelectorOnTop="false"
                 android:cacheColorHint="@android:color/transparent"
@@ -63,11 +62,10 @@
 
         <LinearLayout
                 android:id="@+id/prefs_frame"
+                style="?attr/preferencePanelStyle"
                 android:layout_width="0px"
                 android:layout_height="match_parent"
                 android:layout_weight="@integer/preferences_right_pane_weight"
-                android:layout_marginLeft="@dimen/preference_screen_side_margin"
-                android:layout_marginRight="@dimen/preference_screen_side_margin"
                 android:orientation="vertical"
                 android:visibility="gone" >
 
diff --git a/core/res/res/layout/preference_list_content_single.xml b/core/res/res/layout/preference_list_content_single.xml
index 6902ffd..259869d 100644
--- a/core/res/res/layout/preference_list_content_single.xml
+++ b/core/res/res/layout/preference_list_content_single.xml
@@ -39,6 +39,9 @@
                 android:layout_height="0px"
                 android:layout_weight="1"
                 android:drawSelectorOnTop="false"
+                android:paddingLeft="@dimen/preference_fragment_padding_side"
+                android:paddingRight="@dimen/preference_fragment_padding_side"
+                android:scrollbarStyle="@integer/preference_fragment_scrollbarStyle"
                 android:cacheColorHint="@android:color/transparent"
                 android:listPreferredItemHeight="48dp"
                 android:scrollbarAlwaysDrawVerticalTrack="true" />
diff --git a/core/res/res/values-h720dp/dimens.xml b/core/res/res/values-h720dp/dimens.xml
index 7efe322..6e99183 100644
--- a/core/res/res/values-h720dp/dimens.xml
+++ b/core/res/res/values-h720dp/dimens.xml
@@ -21,10 +21,6 @@
     <dimen name="alert_dialog_button_bar_height">54dip</dimen>
     <!-- Preference fragment padding, bottom -->
     <dimen name="preference_fragment_padding_bottom">16dp</dimen>
-    <!-- Preference activity top margin -->
-    <dimen name="preference_screen_top_margin">16dp</dimen>
-    <!-- Preference activity bottom margin -->
-    <dimen name="preference_screen_bottom_margin">16dp</dimen>
 
     <dimen name="preference_screen_header_padding_side">0dip</dimen>
 
diff --git a/core/res/res/values-large/styles.xml b/core/res/res/values-large/styles.xml
deleted file mode 100644
index 5206d7c..0000000
--- a/core/res/res/values-large/styles.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources>
-    <style name="PreferencePanel">
-        <item name="android:layout_marginLeft">@dimen/preference_screen_side_margin</item>
-        <item name="android:layout_marginRight">@dimen/preference_screen_side_margin</item>
-        <item name="android:layout_marginTop">48dip</item>
-        <item name="android:layout_marginBottom">48dip</item>
-        <item name="android:background">?attr/detailsElementBackground</item>
-    </style>
-</resources>
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 24d5d8d..792066e 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -45,13 +45,7 @@
     <dimen name="keyguard_pattern_unlock_status_line_font_size">14sp</dimen>
 
     <!-- Preference activity, vertical padding for the header list -->
-    <dimen name="preference_screen_header_vertical_padding">16dp</dimen>
-
-    <!-- Reduce the margin when using dual pane -->
-    <!-- Preference activity side margins -->
-    <dimen name="preference_screen_side_margin">0dp</dimen>
-    <!-- Preference activity side margins negative-->
-    <dimen name="preference_screen_side_margin_negative">-4dp</dimen>
+    <dimen name="preference_screen_header_vertical_padding">32dp</dimen>
 
 </resources>
 
diff --git a/core/res/res/values-sw600dp/styles.xml b/core/res/res/values-sw600dp/styles.xml
index 7dea9b8..f9e95b7 100644
--- a/core/res/res/values-sw600dp/styles.xml
+++ b/core/res/res/values-sw600dp/styles.xml
@@ -25,4 +25,12 @@
         <item name="android:measureWithLargestChild">true</item>
         <item name="android:tabLayout">@android:layout/tab_indicator_holo</item>
     </style>
+
+    <style name="PreferencePanel">
+        <item name="android:layout_marginLeft">@dimen/preference_screen_side_margin</item>
+        <item name="android:layout_marginRight">@dimen/preference_screen_side_margin</item>
+        <item name="android:layout_marginTop">@dimen/preference_screen_top_margin</item>
+        <item name="android:layout_marginBottom">@dimen/preference_screen_bottom_margin</item>
+        <item name="android:background">?attr/detailsElementBackground</item>
+    </style>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 8db6b4f..93cbde5 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -881,10 +881,6 @@
      Default value is false. EditText content is always selectable. -->
     <attr name="textIsSelectable" format="boolean" />
 
-    <!-- When true, IME suggestions will be displayed when the user double taps on editable text.
-     The default value is true. -->
-    <attr name="suggestionsEnabled" format="boolean" />
-
     <!-- Where to ellipsize text. -->
     <attr name="ellipsize">
         <enum name="none" value="0" />
@@ -3148,8 +3144,6 @@
 
         <!-- Indicates that the content of a non-editable text can be selected. -->
         <attr name="textIsSelectable" />
-        <!-- Suggestions will be displayed when the user double taps on editable text. -->
-        <attr name="suggestionsEnabled" />
         <!-- Present the text in ALL CAPS. This may use a small-caps form when available. -->
         <attr name="textAllCaps" />
     </declare-styleable>
@@ -3934,15 +3928,14 @@
     <declare-styleable name="Animation">
         <!-- Defines the interpolator used to smooth the animation movement in time. -->
         <attr name="interpolator" />
-        <!-- When set to true, fillAfter is taken into account. -->
+        <!-- When set to true, the value of fillBefore is taken into account. -->
         <attr name="fillEnabled" format="boolean" />
-        <!-- When set to true, the animation transformation is applied before the animation has
-             started. The default value is true. If fillEnabled is not set to true, fillBefore
-             is assumed to be true. -->
+        <!-- When set to true or when fillEnabled is not set to true, the animation transformation
+             is applied before the animation has started. The default value is true. -->
         <attr name="fillBefore" format="boolean" />
         <!-- When set to true, the animation transformation is applied after the animation is
-             over. The default value is false. If fillEnabled is not set to true and the animation
-             is not set on a View, fillAfter is assumed to be true. -->
+             over. The default value is false. If fillEnabled is not set to true and the
+             animation is not set on a View, fillAfter is assumed to be true.-->
         <attr name="fillAfter" format="boolean" />
         <!-- Amount of time (in milliseconds) for the animation to run. -->
         <attr name="duration" />
@@ -4100,7 +4093,6 @@
     <declare-styleable name="Animator">
         <!-- Defines the interpolator used to smooth the animation movement in time. -->
         <attr name="interpolator" />
-        <!-- When set to true, fillAfter is taken into account. -->
         <!-- Amount of time (in milliseconds) for the animation to run. -->
         <attr name="duration" />
         <!-- Delay in milliseconds before the animation runs, once start time is reached. -->
@@ -5118,6 +5110,10 @@
              Defaults to false.
              -->
         <attr name="isAlwaysSyncable" format="boolean"/>
+        <!-- If provided, specifies the action of the settings
+             activity for this SyncAdapter.
+             -->
+        <attr name="settingsActivity"/>
     </declare-styleable>
 
     <!-- =============================== -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8fbb09e..b155b803 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -582,21 +582,6 @@
          If false, Content-disposition fragments are ignored -->
     <bool name="config_mms_content_disposition_support">true</bool>
 
-    <!-- If this value is true, the carrier supports sms delivery reports.
-         If false, sms delivery reports are not supported and the preference
-         option to enable/disable delivery reports is removed in the Messaging app. -->
-    <bool name="config_sms_delivery_reports_support">true</bool>
-
-    <!-- If this value is true, the carrier supports mms delivery reports.
-         If false, mms delivery reports are not supported and the preference
-         option to enable/disable delivery reports is removed in the Messaging app. -->
-    <bool name="config_mms_delivery_reports_support">true</bool>
-
-    <!-- If this value is true, the carrier supports mms read reports.
-         If false, mms read reports are not supported and the preference
-         option to enable/disable read reports is removed in the Messaging app. -->
-    <bool name="config_mms_read_reports_support">true</bool>
-
     <!-- National Language Identifier codes for the following two config items.
          (from 3GPP TS 23.038 V9.1.1 Table 6.2.1.2.4.1):
           0  - reserved
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index c522c1e..62a2187 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -78,7 +78,7 @@
     <!-- Preference activity side margins -->
     <dimen name="preference_screen_side_margin">0dp</dimen>
     <!-- Preference activity side margins negative-->
-    <dimen name="preference_screen_side_margin_negative">0dp</dimen>
+    <dimen name="preference_screen_side_margin_negative">-4dp</dimen>
     <!-- Preference activity top margin -->
     <dimen name="preference_screen_top_margin">0dp</dimen>
     <!-- Preference activity bottom margin -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index a6bf1e0..b9d05fd 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1717,8 +1717,6 @@
   <public type="attr" name="textSuggestionsWindowStyle" />
   <public type="attr" name="textEditSuggestionItemLayout" />
 
-  <public type="attr" name="suggestionsEnabled" />
-
   <public type="attr" name="rowCount" />
   <public type="attr" name="rowOrderPreserved" />
   <public type="attr" name="columnCount" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8eaac8c..a3e460e 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2470,7 +2470,7 @@
     <string name="paste">Paste</string>
 
     <!-- Item on EditText context menu. This action is used to replace the current word by other suggested words, suggested by the IME or the spell checker -->
-    <string name="replace">Replace</string>
+    <string name="replace">Replace\u2026</string>
 
     <!-- Item on EditText context menu. This action is used to copy a URL from the edit field into the clipboard. -->
     <string name="copyUrl">Copy URL</string>
@@ -2665,8 +2665,8 @@
 
      <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems.  This is the notification's title / ticker. -->
      <string name="wifi_watchdog_network_disabled">Couldn\'t connect to Wi-Fi</string>
-     <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems.  This is a partial string of the message, which will also include the (possibly truncated) hotspot name. -->
-    <string name="wifi_watchdog_network_disabled_detailed"> has a poor internet connection.</string>
+     <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems.  The complete alert msg is: <hotspot name> + this string, i.e. "Linksys has a poor internet connection" -->
+    <string name="wifi_watchdog_network_disabled_detailed">\u0020has a poor internet connection.</string>
 
     <!-- Do not translate. Default access point SSID used for tethering -->
     <string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 94c6e41..d8d613a 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1854,7 +1854,7 @@
 
     <style name="Widget.Holo.ActionButton.Overflow">
         <item name="android:src">@android:drawable/ic_menu_moreoverflow_holo_dark</item>
-        <item name="android:background">?android:attr/selectableItemBackground</item>
+        <item name="android:background">?android:attr/actionBarItemBackground</item>
         <item name="android:contentDescription">@string/action_menu_overflow_description</item>
     </style>
 
diff --git a/core/tests/coretests/res/layout/interrogation_activity.xml b/core/tests/coretests/res/layout/interrogation_activity.xml
index 28d965b..44ed75c 100644
--- a/core/tests/coretests/res/layout/interrogation_activity.xml
+++ b/core/tests/coretests/res/layout/interrogation_activity.xml
@@ -30,20 +30,20 @@
         >
         <Button
             android:id="@+id/button1"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_width="160px"
+            android:layout_height="100px"
             android:text="@string/button1"
         />
         <Button
             android:id="@+id/button2"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_width="160px"
+            android:layout_height="100px"
             android:text="@string/button2"
         />
         <Button
             android:id="@+id/button3"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_width="160px"
+            android:layout_height="100px"
             android:text="@string/button3"
         />
     </LinearLayout>
@@ -55,20 +55,20 @@
         >
         <Button
             android:id="@+id/button4"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_width="160px"
+            android:layout_height="100px"
             android:text="@string/button4"
         />
         <Button
             android:id="@+id/button5"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_width="160px"
+            android:layout_height="100px"
             android:text="@string/button5"
         />
         <Button
             android:id="@+id/button6"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_width="160px"
+            android:layout_height="100px"
             android:text="@string/button6"
         />
     </LinearLayout>
@@ -80,20 +80,20 @@
         >
         <Button
             android:id="@+id/button7"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_width="160px"
+            android:layout_height="100px"
             android:text="@string/button7"
         />
         <Button
             android:id="@+id/button8"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_width="160px"
+            android:layout_height="100px"
             android:text="@string/button8"
         />
         <Button
             android:id="@+id/button9"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_width="160px"
+            android:layout_height="100px"
             android:text="@string/button9"
         />
     </LinearLayout>
diff --git a/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java b/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
index 99d534c..a542a1b 100644
--- a/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
+++ b/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
@@ -31,6 +31,7 @@
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityInteractionClient;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.IAccessibilityManager;
@@ -81,8 +82,8 @@
             // bring up the activity
             getActivity();
 
-            AccessibilityNodeInfo button =
-                getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
+            AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
             assertNotNull(button);
             assertEquals(0, button.getChildCount());
 
@@ -91,8 +92,8 @@
             button.getBoundsInParent(bounds);
             assertEquals(0, bounds.left);
             assertEquals(0, bounds.top);
-            assertEquals(73, bounds.right);
-            assertEquals(48, bounds.bottom);
+            assertEquals(160, bounds.right);
+            assertEquals(100, bounds.bottom);
 
             // char sequence attributes
             assertEquals("com.android.frameworks.coretests", button.getPackageName());
@@ -133,8 +134,8 @@
             getActivity();
 
             // find a view by text
-            List<AccessibilityNodeInfo> buttons =
-                getConnection().findAccessibilityNodeInfosByViewTextInActiveWindow("butto");
+            List<AccessibilityNodeInfo> buttons =  AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfosByViewTextInActiveWindow(getConnection(), "butto");
             assertEquals(9, buttons.size());
         } finally {
             afterClassIfNeeded();
@@ -170,8 +171,8 @@
             classNameAndTextList.add("android.widget.ButtonButton8");
             classNameAndTextList.add("android.widget.ButtonButton9");
 
-            AccessibilityNodeInfo root =
-                getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.root);
+            AccessibilityNodeInfo root = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.root);
             assertNotNull("We must find the existing root.", root);
 
             Queue<AccessibilityNodeInfo> fringe = new LinkedList<AccessibilityNodeInfo>();
@@ -214,15 +215,16 @@
             getActivity();
 
             // find a view and make sure it is not focused
-            AccessibilityNodeInfo button =
-                getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
+            AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
             assertFalse(button.isFocused());
 
             // focus the view
             assertTrue(button.performAction(ACTION_FOCUS));
 
             // find the view again and make sure it is focused
-            button = getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
+            button =  AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
             assertTrue(button.isFocused());
         } finally {
             afterClassIfNeeded();
@@ -242,22 +244,24 @@
             getActivity();
 
             // find a view and make sure it is not focused
-            AccessibilityNodeInfo button =
-                getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
+            AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
             assertFalse(button.isFocused());
 
             // focus the view
             assertTrue(button.performAction(ACTION_FOCUS));
 
             // find the view again and make sure it is focused
-            button =  getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
+            button = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
             assertTrue(button.isFocused());
 
             // unfocus the view
             assertTrue(button.performAction(ACTION_CLEAR_FOCUS));
 
             // find the view again and make sure it is not focused
-            button =  getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
+            button = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
             assertFalse(button.isFocused());
         } finally {
             afterClassIfNeeded();
@@ -278,15 +282,16 @@
             getActivity();
 
             // find a view and make sure it is not selected
-            AccessibilityNodeInfo button =
-                getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
+            AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
             assertFalse(button.isSelected());
 
             // select the view
             assertTrue(button.performAction(ACTION_SELECT));
 
             // find the view again and make sure it is selected
-            button = getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
+            button = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
             assertTrue(button.isSelected());
         } finally {
             afterClassIfNeeded();
@@ -306,22 +311,24 @@
             getActivity();
 
             // find a view and make sure it is not selected
-            AccessibilityNodeInfo button =
-                getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
+            AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
             assertFalse(button.isSelected());
 
             // select the view
             assertTrue(button.performAction(ACTION_SELECT));
 
             // find the view again and make sure it is selected
-            button = getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
+            button = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
             assertTrue(button.isSelected());
 
             // unselect the view
             assertTrue(button.performAction(ACTION_CLEAR_SELECTION));
 
             // find the view again and make sure it is not selected
-            button = getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
+            button =  AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
             assertFalse(button.isSelected());
         } finally {
             afterClassIfNeeded();
@@ -342,8 +349,8 @@
             getActivity();
 
             // find a view and make sure it is not focused
-            AccessibilityNodeInfo button =
-                getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
+            AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
             assertFalse(button.isSelected());
 
             // focus the view
@@ -406,8 +413,8 @@
             getActivity();
 
             // find a view and make sure it is not focused
-            AccessibilityNodeInfo button =
-                getConnection().findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
+            AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
             AccessibilityNodeInfo parent = button.getParent();
             final int childCount = parent.getChildCount();
             for (int i = 0; i < childCount; i++) {
diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
index 4db4ea5..b888d9a 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
@@ -99,7 +99,7 @@
                 new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L));
 
         assertEquals(1, stats.size());
-        assertValues(stats, 0, 1024L, 10L, 2048L, 20L, 2L);
+        assertValues(stats, 0, SECOND_IN_MILLIS, 1024L, 10L, 2048L, 20L, 2L);
     }
 
     public void testRecordEqualBuckets() throws Exception {
@@ -112,8 +112,8 @@
                 new NetworkStats.Entry(1024L, 10L, 128L, 2L, 2L));
 
         assertEquals(2, stats.size());
-        assertValues(stats, 0, 512L, 5L, 64L, 1L, 1L);
-        assertValues(stats, 1, 512L, 5L, 64L, 1L, 1L);
+        assertValues(stats, 0, HOUR_IN_MILLIS / 2, 512L, 5L, 64L, 1L, 1L);
+        assertValues(stats, 1, HOUR_IN_MILLIS / 2, 512L, 5L, 64L, 1L, 1L);
     }
 
     public void testRecordTouchingBuckets() throws Exception {
@@ -129,11 +129,11 @@
 
         assertEquals(3, stats.size());
         // first bucket should have (1/20 of value)
-        assertValues(stats, 0, 50L, 100L, 250L, 500L, 5L);
+        assertValues(stats, 0, MINUTE_IN_MILLIS, 50L, 100L, 250L, 500L, 5L);
         // second bucket should have (15/20 of value)
-        assertValues(stats, 1, 750L, 1500L, 3750L, 7500L, 75L);
+        assertValues(stats, 1, 15 * MINUTE_IN_MILLIS, 750L, 1500L, 3750L, 7500L, 75L);
         // final bucket should have (4/20 of value)
-        assertValues(stats, 2, 200L, 400L, 1000L, 2000L, 20L);
+        assertValues(stats, 2, 4 * MINUTE_IN_MILLIS, 200L, 400L, 1000L, 2000L, 20L);
     }
 
     public void testRecordGapBuckets() throws Exception {
@@ -150,8 +150,8 @@
 
         // we should have two buckets, far apart from each other
         assertEquals(2, stats.size());
-        assertValues(stats, 0, 128L, 2L, 256L, 4L, 1L);
-        assertValues(stats, 1, 64L, 1L, 512L, 8L, 2L);
+        assertValues(stats, 0, SECOND_IN_MILLIS, 128L, 2L, 256L, 4L, 1L);
+        assertValues(stats, 1, SECOND_IN_MILLIS, 64L, 1L, 512L, 8L, 2L);
 
         // now record something in middle, spread across two buckets
         final long middleStart = TEST_START + DAY_IN_MILLIS;
@@ -161,10 +161,10 @@
 
         // now should have four buckets, with new record in middle two buckets
         assertEquals(4, stats.size());
-        assertValues(stats, 0, 128L, 2L, 256L, 4L, 1L);
-        assertValues(stats, 1, 1024L, 2L, 1024L, 2L, 1L);
-        assertValues(stats, 2, 1024L, 2L, 1024L, 2L, 1L);
-        assertValues(stats, 3, 64L, 1L, 512L, 8L, 2L);
+        assertValues(stats, 0, SECOND_IN_MILLIS, 128L, 2L, 256L, 4L, 1L);
+        assertValues(stats, 1, HOUR_IN_MILLIS, 1024L, 2L, 1024L, 2L, 1L);
+        assertValues(stats, 2, HOUR_IN_MILLIS, 1024L, 2L, 1024L, 2L, 1L);
+        assertValues(stats, 3, SECOND_IN_MILLIS, 64L, 1L, 512L, 8L, 2L);
     }
 
     public void testRecordOverlapBuckets() throws Exception {
@@ -180,8 +180,8 @@
 
         // should have two buckets, with some data mixed together
         assertEquals(2, stats.size());
-        assertValues(stats, 0, 768L, 7L, 768L, 7L, 6L);
-        assertValues(stats, 1, 512L, 5L, 512L, 5L, 5L);
+        assertValues(stats, 0, SECOND_IN_MILLIS + (HOUR_IN_MILLIS / 2), 768L, 7L, 768L, 7L, 6L);
+        assertValues(stats, 1, (HOUR_IN_MILLIS / 2), 512L, 5L, 512L, 5L, 5L);
     }
 
     public void testRecordEntireGapIdentical() throws Exception {
@@ -345,11 +345,10 @@
 
         history.recordData(0, MINUTE_IN_MILLIS,
                 new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
-        history.recordData(0, MINUTE_IN_MILLIS * 2,
+        history.recordData(0, 2 * MINUTE_IN_MILLIS,
                 new NetworkStats.Entry(2L, 2L, 2L, 2L, 2L));
 
-        assertValues(
-                history, Long.MIN_VALUE, Long.MAX_VALUE, 1026L, UNKNOWN, 2050L, UNKNOWN, UNKNOWN);
+        assertFullValues(history, UNKNOWN, 1026L, UNKNOWN, 2050L, UNKNOWN, UNKNOWN);
     }
 
     public void testIgnoreFieldsRecordIn() throws Exception {
@@ -361,7 +360,7 @@
                 new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
         partial.recordEntireHistory(full);
 
-        assertValues(partial, Long.MIN_VALUE, Long.MAX_VALUE, UNKNOWN, 10L, UNKNOWN, UNKNOWN, 4L);
+        assertFullValues(partial, UNKNOWN, UNKNOWN, 10L, UNKNOWN, UNKNOWN, 4L);
     }
 
     public void testIgnoreFieldsRecordOut() throws Exception {
@@ -373,12 +372,12 @@
                 new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
         full.recordEntireHistory(partial);
 
-        assertValues(full, Long.MIN_VALUE, Long.MAX_VALUE, 0L, 10L, 0L, 0L, 4L);
+        assertFullValues(full, MINUTE_IN_MILLIS, 0L, 10L, 0L, 0L, 4L);
     }
 
     public void testSerialize() throws Exception {
         final NetworkStatsHistory before = new NetworkStatsHistory(MINUTE_IN_MILLIS, 40, FIELD_ALL);
-        before.recordData(0, MINUTE_IN_MILLIS * 4,
+        before.recordData(0, 4 * MINUTE_IN_MILLIS,
                 new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
         before.recordData(DAY_IN_MILLIS, DAY_IN_MILLIS + MINUTE_IN_MILLIS,
                 new NetworkStats.Entry(10L, 20L, 30L, 40L, 50L));
@@ -391,8 +390,8 @@
         final NetworkStatsHistory after = new NetworkStatsHistory(new DataInputStream(in));
 
         // must have identical totals before and after
-        assertValues(before, Long.MIN_VALUE, Long.MAX_VALUE, 1034L, 30L, 2078L, 60L, 54L);
-        assertValues(after, Long.MIN_VALUE, Long.MAX_VALUE, 1034L, 30L, 2078L, 60L, 54L);
+        assertFullValues(before, 5 * MINUTE_IN_MILLIS, 1034L, 30L, 2078L, 60L, 54L);
+        assertFullValues(after, 5 * MINUTE_IN_MILLIS, 1034L, 30L, 2078L, 60L, 54L);
     }
 
     public void testVarLong() throws Exception {
@@ -441,9 +440,10 @@
         assertEquals("unexpected txBytes", txBytes, entry.txBytes);
     }
 
-    private static void assertValues(NetworkStatsHistory stats, int index, long rxBytes,
-            long rxPackets, long txBytes, long txPackets, long operations) {
+    private static void assertValues(NetworkStatsHistory stats, int index, long activeTime,
+            long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
         final NetworkStatsHistory.Entry entry = stats.getValues(index, null);
+        assertEquals("unexpected activeTime", activeTime, entry.activeTime);
         assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
         assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
         assertEquals("unexpected txBytes", txBytes, entry.txBytes);
@@ -451,9 +451,17 @@
         assertEquals("unexpected operations", operations, entry.operations);
     }
 
-    private static void assertValues(NetworkStatsHistory stats, long start, long end, long rxBytes,
+    private static void assertFullValues(NetworkStatsHistory stats, long activeTime, long rxBytes,
             long rxPackets, long txBytes, long txPackets, long operations) {
+        assertValues(stats, Long.MIN_VALUE, Long.MAX_VALUE, activeTime, rxBytes, rxPackets, txBytes,
+                txPackets, operations);
+    }
+
+    private static void assertValues(NetworkStatsHistory stats, long start, long end,
+            long activeTime, long rxBytes, long rxPackets, long txBytes, long txPackets,
+            long operations) {
         final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null);
+        assertEquals("unexpected activeTime", activeTime, entry.activeTime);
         assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
         assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
         assertEquals("unexpected txBytes", txBytes, entry.txBytes);
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index 47ba88a..c36685d 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java
@@ -17,7 +17,9 @@
 package android.net;
 
 import static android.net.NetworkStats.SET_DEFAULT;
+import static android.net.NetworkStats.SET_FOREGROUND;
 import static android.net.NetworkStats.TAG_NONE;
+import static android.net.NetworkStats.UID_ALL;
 
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -27,6 +29,7 @@
 public class NetworkStatsTest extends TestCase {
 
     private static final String TEST_IFACE = "test0";
+    private static final String TEST_IFACE2 = "test2";
     private static final int TEST_UID = 1001;
     private static final long TEST_START = 1194220800000L;
 
@@ -135,6 +138,44 @@
         assertValues(result, 2, TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 20);
     }
 
+    public void testSubtractMissingRows() throws Exception {
+        final NetworkStats before = new NetworkStats(TEST_START, 2)
+                .addValues(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 0L, 0L, 0L, 0)
+                .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2048L, 0L, 0L, 0L, 0);
+
+        final NetworkStats after = new NetworkStats(TEST_START, 1)
+                .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2049L, 2L, 3L, 4L, 0);
+
+        final NetworkStats result = after.subtract(before);
+
+        // should silently drop omitted rows
+        assertEquals(1, result.size());
+        assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 1L, 2L, 3L, 4L, 0);
+        assertEquals(4L, result.getTotalBytes());
+    }
+
+    public void testTotalBytes() throws Exception {
+        final NetworkStats iface = new NetworkStats(TEST_START, 2)
+                .addValues(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 128L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 256L, 0L, 0L, 0L, 0L);
+        assertEquals(384L, iface.getTotalBytes());
+
+        final NetworkStats uidSet = new NetworkStats(TEST_START, 3)
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
+        assertEquals(96L, uidSet.getTotalBytes());
+
+        final NetworkStats uidTag = new NetworkStats(TEST_START, 3)
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L);
+        assertEquals(64L, uidTag.getTotalBytes());
+    }
+
     private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set,
             int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) {
         final NetworkStats.Entry entry = stats.getValues(index, null);
diff --git a/core/tests/coretests/src/android/util/LocaleUtilTest.java b/core/tests/coretests/src/android/util/LocaleUtilTest.java
index 203781f..ff3d539 100644
--- a/core/tests/coretests/src/android/util/LocaleUtilTest.java
+++ b/core/tests/coretests/src/android/util/LocaleUtilTest.java
@@ -23,7 +23,6 @@
 import dalvik.annotation.TestTargetNew;
 
 import static android.util.LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
-import static android.util.LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
 
 public class LocaleUtilTest extends AndroidTestCase {
 
@@ -33,7 +32,7 @@
         args = {Locale.class}
     )
     public void testGetLayoutDirectionFromLocale() {
-        assertEquals(TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE,
+        assertEquals(TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
                 LocaleUtil.getLayoutDirectionFromLocale(null));
 
         assertEquals(TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
@@ -59,7 +58,7 @@
         assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             LocaleUtil.getLayoutDirectionFromLocale(Locale.US));
 
-        assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE,
+        assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             LocaleUtil.getLayoutDirectionFromLocale(Locale.ROOT));
 
         assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
diff --git a/data/fonts/AndroidClock.ttf b/data/fonts/AndroidClock.ttf
index 7b550eed..6e0932e 100644
--- a/data/fonts/AndroidClock.ttf
+++ b/data/fonts/AndroidClock.ttf
Binary files differ
diff --git a/data/fonts/AndroidClock_Highlight.ttf b/data/fonts/AndroidClock_Highlight.ttf
index a95d548..6e0932e 100644
--- a/data/fonts/AndroidClock_Highlight.ttf
+++ b/data/fonts/AndroidClock_Highlight.ttf
Binary files differ
diff --git a/data/fonts/AndroidClock_Solid.ttf b/data/fonts/AndroidClock_Solid.ttf
index 108839e..6e0932e 100644
--- a/data/fonts/AndroidClock_Solid.ttf
+++ b/data/fonts/AndroidClock_Solid.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Bold.ttf b/data/fonts/Roboto-Bold.ttf
old mode 100755
new mode 100644
index 32c1794..f9311fb
--- a/data/fonts/Roboto-Bold.ttf
+++ b/data/fonts/Roboto-Bold.ttf
Binary files differ
diff --git a/data/fonts/Roboto-BoldItalic.ttf b/data/fonts/Roboto-BoldItalic.ttf
old mode 100755
new mode 100644
index 551bae2..ae92697
--- a/data/fonts/Roboto-BoldItalic.ttf
+++ b/data/fonts/Roboto-BoldItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Italic.ttf b/data/fonts/Roboto-Italic.ttf
old mode 100755
new mode 100644
index 9795cc0..109b642
--- a/data/fonts/Roboto-Italic.ttf
+++ b/data/fonts/Roboto-Italic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Regular.ttf b/data/fonts/Roboto-Regular.ttf
old mode 100755
new mode 100644
index 8545f29..2568835
--- a/data/fonts/Roboto-Regular.ttf
+++ b/data/fonts/Roboto-Regular.ttf
Binary files differ
diff --git a/data/sounds/AudioPackage7.mk b/data/sounds/AudioPackage7.mk
new file mode 100755
index 0000000..4f23716
--- /dev/null
+++ b/data/sounds/AudioPackage7.mk
@@ -0,0 +1,63 @@
+#
+# Audio Package 7 - Tuna
+# 
+# Include this file in a product makefile to include these audio files
+#
+# 
+
+LOCAL_PATH:= frameworks/base/data/sounds
+
+PRODUCT_COPY_FILES += \
+	$(LOCAL_PATH)/alarms/ogg/Cesium.ogg:system/media/audio/alarms/Cesium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Plutonium.ogg:system/media/audio/alarms/Plutonium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Scandium.ogg:system/media/audio/alarms/Scandium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Curium.ogg:system/media/audio/alarms/Curium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Fermium.ogg:system/media/audio/alarms/Fermium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Nobelium.ogg:system/media/audio/alarms/Nobelium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Copernicium.ogg:system/media/audio/alarms/Copernicium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Hassium.ogg:system/media/audio/alarms/Hassium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Neptunium.ogg:system/media/audio/alarms/Neptunium.ogg \
+	$(LOCAL_PATH)/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressStandard_24.ogg:system/media/audio/ui/KeypressStandard.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressSpacebar_24.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressDelete_24.ogg:system/media/audio/ui/KeypressDelete.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressReturn_24.ogg:system/media/audio/ui/KeypressReturn.ogg \
+	$(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/ogg/CameraShutter.ogg:system/media/audio/ui/camera_click.ogg \
+	$(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Altair.ogg:system/media/audio/notifications/Altair.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Antares.ogg:system/media/audio/notifications/Antares.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Deneb.ogg:system/media/audio/notifications/Deneb.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Proxima.ogg:system/media/audio/notifications/Proxima.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Betelgeuse.ogg:system/media/audio/notifications/Betelgeuse.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Upsilon.ogg:system/media/audio/notifications/Upsilon.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/ArgoNavis.ogg:system/media/audio/ringtones/ArgoNavis.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Bootes.ogg:system/media/audio/ringtones/Bootes.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/CanisMajor.ogg:system/media/audio/ringtones/CanisMajor.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Carina.ogg:system/media/audio/ringtones/Carina.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Cassiopeia.ogg:system/media/audio/ringtones/Cassiopeia.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Centaurus.ogg:system/media/audio/ringtones/Centaurus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Cygnus.ogg:system/media/audio/ringtones/Cygnus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Draco.ogg:system/media/audio/ringtones/Draco.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Hydra.ogg:system/media/audio/ringtones/Hydra.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Lyra.ogg:system/media/audio/ringtones/Lyra.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Machina.ogg:system/media/audio/ringtones/Machina.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Orion.ogg:system/media/audio/ringtones/Orion.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Pegasus.ogg:system/media/audio/ringtones/Pegasus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Pyxis.ogg:system/media/audio/ringtones/Pyxis.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Rigel.ogg:system/media/audio/ringtones/Rigel.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Scarabaeus.ogg:system/media/audio/ringtones/Scarabaeus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Sceptrum.ogg:system/media/audio/ringtones/Sceptrum.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Solarium.ogg:system/media/audio/ringtones/Solarium.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Testudo.ogg:system/media/audio/ringtones/Testudo.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/UrsaMinor.ogg:system/media/audio/ringtones/UrsaMinor.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Vespa.ogg:system/media/audio/ringtones/Vespa.ogg
diff --git a/data/sounds/alarms/ogg/Copernicium.ogg b/data/sounds/alarms/ogg/Copernicium.ogg
new file mode 100644
index 0000000..c619e8b
--- /dev/null
+++ b/data/sounds/alarms/ogg/Copernicium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Curium.ogg b/data/sounds/alarms/ogg/Curium.ogg
new file mode 100644
index 0000000..ebce391
--- /dev/null
+++ b/data/sounds/alarms/ogg/Curium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Fermium.ogg b/data/sounds/alarms/ogg/Fermium.ogg
new file mode 100644
index 0000000..6132565
--- /dev/null
+++ b/data/sounds/alarms/ogg/Fermium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Hassium.ogg b/data/sounds/alarms/ogg/Hassium.ogg
new file mode 100644
index 0000000..408b7c2
--- /dev/null
+++ b/data/sounds/alarms/ogg/Hassium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Neptunium.ogg b/data/sounds/alarms/ogg/Neptunium.ogg
new file mode 100644
index 0000000..058e2db
--- /dev/null
+++ b/data/sounds/alarms/ogg/Neptunium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Nobelium.ogg b/data/sounds/alarms/ogg/Nobelium.ogg
new file mode 100644
index 0000000..33878c9
--- /dev/null
+++ b/data/sounds/alarms/ogg/Nobelium.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/CameraShutter.ogg b/data/sounds/effects/ogg/CameraShutter.ogg
new file mode 100644
index 0000000..1b67dac
--- /dev/null
+++ b/data/sounds/effects/ogg/CameraShutter.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/Dock.ogg b/data/sounds/effects/ogg/Dock.ogg
old mode 100755
new mode 100644
index a1c1f2c..caa8eeb
--- a/data/sounds/effects/ogg/Dock.ogg
+++ b/data/sounds/effects/ogg/Dock.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressDelete_24.ogg b/data/sounds/effects/ogg/KeypressDelete_24.ogg
new file mode 100644
index 0000000..2503c3e
--- /dev/null
+++ b/data/sounds/effects/ogg/KeypressDelete_24.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressReturn_24.ogg b/data/sounds/effects/ogg/KeypressReturn_24.ogg
new file mode 100644
index 0000000..342eb12
--- /dev/null
+++ b/data/sounds/effects/ogg/KeypressReturn_24.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressSpacebar_24.ogg b/data/sounds/effects/ogg/KeypressSpacebar_24.ogg
new file mode 100644
index 0000000..9f17dd2
--- /dev/null
+++ b/data/sounds/effects/ogg/KeypressSpacebar_24.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressStandard_24.ogg b/data/sounds/effects/ogg/KeypressStandard_24.ogg
new file mode 100644
index 0000000..80d7d6d1
--- /dev/null
+++ b/data/sounds/effects/ogg/KeypressStandard_24.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/Lock.ogg b/data/sounds/effects/ogg/Lock.ogg
old mode 100755
new mode 100644
index deeba68..471258a
--- a/data/sounds/effects/ogg/Lock.ogg
+++ b/data/sounds/effects/ogg/Lock.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/Media_Volume.ogg b/data/sounds/effects/ogg/Media_Volume.ogg
index 88db9d9..b06656f 100644
--- a/data/sounds/effects/ogg/Media_Volume.ogg
+++ b/data/sounds/effects/ogg/Media_Volume.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/Undock.ogg b/data/sounds/effects/ogg/Undock.ogg
old mode 100755
new mode 100644
index 91e410e..28918f7
--- a/data/sounds/effects/ogg/Undock.ogg
+++ b/data/sounds/effects/ogg/Undock.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/Unlock.ogg b/data/sounds/effects/ogg/Unlock.ogg
old mode 100755
new mode 100644
index ac50288..1cd537b
--- a/data/sounds/effects/ogg/Unlock.ogg
+++ b/data/sounds/effects/ogg/Unlock.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/VideoRecord.ogg b/data/sounds/effects/ogg/VideoRecord.ogg
index 7afe9e6..28455c9 100644
--- a/data/sounds/effects/ogg/VideoRecord.ogg
+++ b/data/sounds/effects/ogg/VideoRecord.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Altair.ogg b/data/sounds/notifications/ogg/Altair.ogg
new file mode 100755
index 0000000..d84b59e
--- /dev/null
+++ b/data/sounds/notifications/ogg/Altair.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Antares.ogg b/data/sounds/notifications/ogg/Antares.ogg
new file mode 100755
index 0000000..9d60917
--- /dev/null
+++ b/data/sounds/notifications/ogg/Antares.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Betelgeuse.ogg b/data/sounds/notifications/ogg/Betelgeuse.ogg
new file mode 100644
index 0000000..83c7722
--- /dev/null
+++ b/data/sounds/notifications/ogg/Betelgeuse.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Deneb.ogg b/data/sounds/notifications/ogg/Deneb.ogg
new file mode 100755
index 0000000..e58b3b6
--- /dev/null
+++ b/data/sounds/notifications/ogg/Deneb.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Hojus.ogg b/data/sounds/notifications/ogg/Hojus.ogg
new file mode 100644
index 0000000..fc8f73f
--- /dev/null
+++ b/data/sounds/notifications/ogg/Hojus.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Lalande.ogg b/data/sounds/notifications/ogg/Lalande.ogg
new file mode 100755
index 0000000..b6e253a
--- /dev/null
+++ b/data/sounds/notifications/ogg/Lalande.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Mira.ogg b/data/sounds/notifications/ogg/Mira.ogg
new file mode 100644
index 0000000..f21e3c4
--- /dev/null
+++ b/data/sounds/notifications/ogg/Mira.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Proxima.ogg b/data/sounds/notifications/ogg/Proxima.ogg
new file mode 100644
index 0000000..235b5ca
--- /dev/null
+++ b/data/sounds/notifications/ogg/Proxima.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Upsilon.ogg b/data/sounds/notifications/ogg/Upsilon.ogg
new file mode 100644
index 0000000..036dcad
--- /dev/null
+++ b/data/sounds/notifications/ogg/Upsilon.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Cassiopeia.ogg b/data/sounds/ringtones/ogg/Cassiopeia.ogg
index 942d4e4..61c4d27 100644
--- a/data/sounds/ringtones/ogg/Cassiopeia.ogg
+++ b/data/sounds/ringtones/ogg/Cassiopeia.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Lyra.ogg b/data/sounds/ringtones/ogg/Lyra.ogg
index e4bf37a..b7f740d 100644
--- a/data/sounds/ringtones/ogg/Lyra.ogg
+++ b/data/sounds/ringtones/ogg/Lyra.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Sceptrum.ogg b/data/sounds/ringtones/ogg/Sceptrum.ogg
index a006afe..89d64d70 100644
--- a/data/sounds/ringtones/ogg/Sceptrum.ogg
+++ b/data/sounds/ringtones/ogg/Sceptrum.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Solarium.ogg b/data/sounds/ringtones/ogg/Solarium.ogg
index 108ba11..361367a 100644
--- a/data/sounds/ringtones/ogg/Solarium.ogg
+++ b/data/sounds/ringtones/ogg/Solarium.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/UrsaMinor.ogg b/data/sounds/ringtones/ogg/UrsaMinor.ogg
index 5591d73..a80801d 100644
--- a/data/sounds/ringtones/ogg/UrsaMinor.ogg
+++ b/data/sounds/ringtones/ogg/UrsaMinor.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Vespa.ogg b/data/sounds/ringtones/ogg/Vespa.ogg
index 6fb8ebd..1f75ec8 100644
--- a/data/sounds/ringtones/ogg/Vespa.ogg
+++ b/data/sounds/ringtones/ogg/Vespa.ogg
Binary files differ
diff --git a/docs/html/guide/appendix/install-location.jd b/docs/html/guide/appendix/install-location.jd
index 617f4fc..292d3e7 100644
--- a/docs/html/guide/appendix/install-location.jd
+++ b/docs/html/guide/appendix/install-location.jd
@@ -195,7 +195,7 @@
 <p>In simple terms, anything that does not use the features listed in the previous section
 are safe when installed on external storage. Large games are more commonly the types of
 applications that should allow installation on external storage, because games don't typically
-provide additional services when innactive. When external storage becomes unavailable and a game
+provide additional services when inactive. When external storage becomes unavailable and a game
 process is killed, there should be no visible effect when the storage becomes available again and
 the user restarts the game (assuming that the game properly saved its state during the normal
 <a href="{@docRoot}guide/topics/fundamentals/activities.html#Lifecycle">Activity lifecycle</a>).</p>
diff --git a/docs/html/guide/developing/device.jd b/docs/html/guide/developing/device.jd
index bde170e..e08119f 100644
--- a/docs/html/guide/developing/device.jd
+++ b/docs/html/guide/developing/device.jd
@@ -41,7 +41,8 @@
 
 <p class="note"><strong>Note:</strong> When developing on a device, keep in mind that you should
 still use the <a
-href="{@docRoot}guide/developing/devices/emulator.html">Android emulator</a> to test your application
+href="{@docRoot}guide/developing/devices/emulator.html">Android emulator</a> to test your
+application
 on configurations that are not equivalent to those of your real device. Although the emulator
 does not allow you to test every device feature (such as the accelerometer), it does
 allow you to verify that your application functions properly on different versions of the Android
@@ -56,14 +57,22 @@
 <ol>
   <li>Declare your application as "debuggable" in your Android Manifest.
     <p>In Eclipse, you can do this from the <b>Application</b> tab when viewing the Manifest
-    (on the right side, set <b>Debuggable</b> to <em>true</em>). Otherwise, in the <code>AndroidManifest.xml</code>
-    file, add <code>android:debuggable="true"</code> to the <code>&lt;application></code> element.</p>
+    (on the right side, set <b>Debuggable</b> to <em>true</em>). Otherwise, in the
+<code>AndroidManifest.xml</code>
+    file, add <code>android:debuggable="true"</code> to the <code>&lt;application></code>
+element.</p>
+  </li>
+  <li>Set up your device to allow installation of non-Market applications. <p>On
+the device, go to <strong>Settings > Applications</strong> and enable
+
+<strong>Unknown sources</strong>.</p>
+  
   </li>
   <li>Turn on "USB Debugging" on your device.
-    <p>On the device, go to the home screen, press <b>MENU</b>, select <b>Applications</b> > <b>Development</b>,
-    then enable <b>USB debugging</b>.</p>
+    <p>On the device, go to <strong>Settings > Applications > Development</strong>
+    and enable <strong>USB debugging</strong>.</p>
   </li>
-  <li>Setup your system to detect your device.
+  <li>Set up your system to detect your device.
     <ul>
       <li>If you're developing on Windows, you need to install a USB driver
       for adb. If you're using an Android Developer Phone (ADP), Nexus One, or Nexus S,
@@ -71,27 +80,37 @@
       Driver</a>. Otherwise, you can find a link to the appropriate OEM driver in the
   <a href="{@docRoot}sdk/oem-usb.html">OEM USB Drivers</a> document.</li>
       <li>If you're developing on Mac OS X, it just works. Skip this step.</li>
-      <li>If you're developing on Ubuntu Linux, you need to add a rules file
-that contains a USB configuration for each type of device you want to use for
-development. Each device manufacturer uses a different vendor ID. The
-example rules files below show how to add an entry for a single vendor ID
-(the HTC vendor ID). In order to support more devices, you will need additional
-lines of the same format that provide a different value for the
-<code>SYSFS{idVendor}</code> property. For other IDs, see the table of <a
-href="#VendorIds">USB Vendor IDs</a>, below.
-        <ol>
-          <li>Log in as root and create this file:
-            <code>/etc/udev/rules.d/51-android.rules</code>.
-            <p>For Gusty/Hardy, edit the file to read:<br/>
-            <code>SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4",
-            MODE="0666"</code></p>
+      
+      <li>If you're developing on Ubuntu Linux, you need to add a <a
+href="http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html">
+<code>udev</code></a> 
+rules file that contains a USB configuration for each type of device
+you want to use for development. In the rules file, each device manufacturer
+is identified by a unique vendor ID, as specified by the
+<code>ATTR{idVendor}</code> property. For a list of vendor IDs, see  <a
+href="#VendorIds">USB Vendor IDs</a>, below. To set up device detection on
+Ubuntu Linux:
 
-            <p>For Dapper, edit the file to read:<br/>
-            <code>SUBSYSTEM=="usb_device", SYSFS{idVendor}=="0bb4",
-            MODE="0666"</code></p>
+        <ol type="a">
+          <li>Log in as root and create this file:
+            <code>/etc/udev/rules.d/51-android.rules</code></span>.
+            <p>Use this format to add each vendor to the file:<br/>
+              <code>SUBSYSTEM==&quot;usb&quot;, ATTR{idVendor}==&quot;0bb4&quot;, MODE=&quot;0666&quot;, GROUP=&quot;plugdev&quot;</code>
+              <br /><br />
+              
+              In this example, the vendor ID is for HTC. The <code>MODE</code>
+assignment specifies read/write permissions, and <code>GROUP</code> defines
+which Unix group  owns the device node. </p>
+            
+            <p class="note"><strong>Note:</strong> The rule syntax
+may vary slightly depending on your  environment. Consult the <code>udev</code>
+documentation for your system as needed. For an overview of rule syntax, see
+this guide to <a
+href="http://www.reactivated.net/writing_udev_rules.html">writing udev
+rules</a>.</p>
           </li>
           <li>Now execute:<br/>
-              <code>chmod a+r /etc/udev/rules.d/51-android.rules</code>
+            <code>chmod a+r /etc/udev/rules.d/51-android.rules</code>
           </li>
         </ol>
       </li>
@@ -99,79 +118,143 @@
   </li>
 </ol>
 
-<p>You can verify that your device is connected by executing <code>adb devices</code> from your 
-SDK {@code platform-tools/} directory. If connected, you'll see the device name listed as a
-"device."</p>
+<p>You can verify that your device is connected by executing <code>adb
+devices</code> from your SDK {@code platform-tools/} directory. If connected,
+you'll see the device name listed as a "device."</p>
 
-<p>If using Eclipse, run or debug as usual. You will be presented
-with a <b>Device Chooser</b> dialog that lists the available emulator(s) and connected device(s).
-Select the device upon which you want to install and run the application.</p>
+<p>If using Eclipse, run or debug your application as usual. You will be
+presented with a <b>Device Chooser</b> dialog that lists the available
+emulator(s) and connected device(s). Select the device upon which you want to
+install and run the application.</p>
 
-<p>If using the <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a> (adb),
-you can issue commands with the <code>-d</code> flag to target your
-connected device.</p>
-
+<p>If using the <a href="{@docRoot}guide/developing/tools/adb.html">Android
+Debug Bridge</a> (adb), you can issue commands with the <code>-d</code> flag to
+target your connected device.</p>
 
 <h3 id="VendorIds">USB Vendor IDs</h3>
-<p>This table provides a reference to the vendor IDs needed in order to add
-USB device support on Linux. The USB Vendor ID is the value given to the
-<code>SYSFS{idVendor}</code> property in the rules file, as described in step 3, above.</p>
+
+<p>This table provides a reference to the vendor IDs needed in order to add USB
+device support on Linux. The USB Vendor ID is the value given to the
+<code>ATTR{idVendor}</code> property in the rules file, as described 
+above.</p>
 
 <table>
   <tr>
     <th>Company</th><th>USB Vendor ID</th></tr>
   <tr>
     <td>Acer</td>
-    <td><code>0502</code></td></tr>
+    <td><code>0502</code></td>
+  </tr>
+  <tr>
+    <td>ASUS</td>
+    <td><code>0B05</code></td>
+  </tr>
   <tr>
     <td>Dell</td>
-    <td><code>413c</code></td></tr>
+    <td><code>413C</code></td>
+  </tr>
   <tr>
     <td>Foxconn</td>
-    <td><code>0489</code></td></tr>
+    <td><code>0489</code></td>
+  </tr>
   <tr>
     <td>Garmin-Asus</td>
-    <td><code>091E</code></td></tr>
+    <td><code>091E</code></td>
+  </tr>
   <tr>
     <td>Google</td>
-    <td><code>18d1</code></td></tr>
+    <td><code>18D1</code></td>
+  </tr>
   <tr>
     <td>HTC</td>
-    <td><code>0bb4</code></td></tr>
+    <td><code>0BB4</code></td>
+  </tr>
   <tr>
     <td>Huawei</td>
-    <td><code>12d1</code></td></tr>
+    <td><code>12D1</code></td>
+  </tr>
   <tr>
     <td>K-Touch</td>
-    <td><code>24e3</code></td></tr>
+    <td><code>24E3</code></td>
+  </tr>
+  <tr>
+    <td>KT Tech</td>
+    <td><code>2116</code></td>
+  </tr>
   <tr>
     <td>Kyocera</td>
-    <td><code>0482</code></td></tr>
+    <td><code>0482</code></td>
+  </tr>
   <tr>
     <td>Lenevo</td>
-    <td><code>17EF</code></td></tr>
+    <td><code>17EF</code></td>
+  </tr>
   <tr>
     <td>LG</td>
-    <td><code>1004</code></td></tr>
+    <td><code>1004</code></td>
+  </tr>
   <tr>
     <td>Motorola</td>
-    <td><code>22b8</code></td></tr>
+    <td><code>22B8</code></td>
+  </tr>
+  <tr>
+    <td>NEC</td>
+    <td><code>0409</code></td>
+  </tr>
+  <tr>
+    <td>Nook</td>
+    <td><code>2080</code></td>
+  </tr>
   <tr>
     <td>Nvidia</td>
-    <td><code>0955</code></td></tr>
+    <td><code>0955</code></td>
+  </tr>
+  <tr>
+    <td>OTGV</td>
+    <td><code>2257</code></td>
+  </tr>
   <tr>
     <td>Pantech</td>
-    <td><code>10A9</code></td></tr>
+    <td><code>10A9</code></td>
+  </tr>
+  <tr>
+    <td>Pegatron</td>
+    <td><code>1D4D</code></td>
+  </tr>
+  <tr>
+    <td>Philips</td>
+    <td><code>0471</code></td>
+  </tr>
+  <tr>
+    <td>PMC-Sierra</td>
+    <td><code>04DA</code></td>
+  </tr>
+  <tr>
+    <td>Qualcomm</td>
+    <td><code>05C6</code></td>
+  </tr>
+  <tr>
+    <td>SK Telesys</td>
+    <td><code>1F53</code></td>
+  </tr>
   <tr>
     <td>Samsung</td>
-    <td><code>04e8</code></td></tr>
+    <td><code>04E8</code></td>
+  </tr>
   <tr>
     <td>Sharp</td>
-    <td><code>04dd</code></td></tr>
+    <td><code>04DD</code></td>
+  </tr>
   <tr>
     <td>Sony Ericsson</td>
-    <td><code>0fce</code></td></tr>
+    <td><code>0FCE</code></td>
+  </tr>
+  <tr>
+    <td>Toshiba</td>
+    <td><code>0930</code></td>
+  </tr>
   <tr>
     <td>ZTE</td>
-    <td><code>19D2</code></td></tr>
+    <td><code>19D2</code></td>
+  </tr>
 </table>
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index 18f47a6..bbf7cbe 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -22,6 +22,11 @@
     </li>
     <li><a href="#updating">Updating the ADT Plugin</a></li>
   </ol>
+  
+  <h2>See also</h2>
+  <ol>
+    <li><a href="{@docRoot}guide/developing/tools/adt.html">Android Developer Tools</a></li>
+  </ol>
 
 </div>
 </div>
@@ -50,6 +55,12 @@
 how to update ADT to the latest version or how to uninstall it, if necessary.
 </p>
 
+<p>For information about the features provided by the ADT plugin, such as code
+editor features, SDK tool integration, and the graphical layout editor (for drag-and-drop layout
+editing), see the <a href="{@docRoot}guide/developing/tools/adt.html">Android Developer Tools</a>
+document.</p>
+
+
 <h2 id="notes">Revisions</h2>
 
 <p>The sections below provide notes about successive releases of
diff --git a/docs/html/sdk/oem-usb.jd b/docs/html/sdk/oem-usb.jd
index 3c2ba8b..ad3be4a 100644
--- a/docs/html/sdk/oem-usb.jd
+++ b/docs/html/sdk/oem-usb.jd
@@ -92,6 +92,8 @@
 href="http://developer.motorola.com/docstools/USB_Drivers/">http://developer.motorola.com/docstools/USB_Drivers/</a></td>
 </tr><tr><td>Pantech</td>	<td><a
 href="http://www.isky.co.kr/cs/software/software.sky?fromUrl=index">http://www.isky.co.kr/cs/software/software.sky?fromUrl=index</a></td>
+</tr><tr><td>Pegatron</td>	<td><a
+href="http://www.pegatroncorp.com/download/New_Duke_PC_Driver_0705.zip">http://www.pegatroncorp.com/download/New_Duke_PC_Driver_0705.zip</a> (ZIP download)</td>
 </tr><tr><td>Samsung</td>	<td><a
 href="http://www.samsung.com/us/support/downloads">http://www.samsung.com/us/support/downloads</a></td>
 </tr><tr><td>Sharp</td>	<td><a
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index d62fd67..f3b62ec 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -93,7 +93,7 @@
      * @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
      */
     public SurfaceTexture(int texName) {
-        this(texName, true);
+        this(texName, false);
     }
 
     /**
@@ -104,6 +104,8 @@
      *      When the image stream comes from OpenGL, SurfaceTexture may run in the synchronous
      *      mode where the producer side may be blocked to avoid skipping frames. To avoid the
      *      thread block, set allowSynchronousMode to false.
+     *
+     * @hide
      */
     public SurfaceTexture(int texName, boolean allowSynchronousMode) {
         Looper looper;
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index df30e8c..923518d 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -481,6 +481,7 @@
     bool                    mMarkerReached;
     uint32_t                mNewPosition;
     uint32_t                mUpdatePeriod;
+    bool                    mFlushed; // FIXME will be made obsolete by making flush() synchronous
     uint32_t                mFlags;
     int                     mSessionId;
     int                     mAuxEffectId;
diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h
index 1affb8a..74d54d1 100644
--- a/include/media/stagefright/SurfaceMediaSource.h
+++ b/include/media/stagefright/SurfaceMediaSource.h
@@ -182,9 +182,9 @@
 
 protected:
 
-    // freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
+    // freeAllBuffersLocked frees the resources (both GraphicBuffer and EGLImage) for
     // all slots.
-    void freeAllBuffers();
+    void freeAllBuffersLocked();
     static bool isExternalFormat(uint32_t format);
 
 private:
@@ -337,8 +337,15 @@
     // Set to a default of 30 fps if not specified by the client side
     int32_t mFrameRate;
 
-    // mStarted is a flag to check if the recording has started
-    bool mStarted;
+    // mStopped is a flag to check if the recording is going on
+    bool mStopped;
+
+    // mNumFramesReceived indicates the number of frames recieved from
+    // the client side
+    int mNumFramesReceived;
+    // mNumFramesEncoded indicates the number of frames passed on to the
+    // encoder
+    int mNumFramesEncoded;
 
     // mFrameAvailableCondition condition used to indicate whether there
     // is a frame available for dequeuing
diff --git a/include/media/stagefright/foundation/ALooperRoster.h b/include/media/stagefright/foundation/ALooperRoster.h
index c1bd4ed..2e5fd73 100644
--- a/include/media/stagefright/foundation/ALooperRoster.h
+++ b/include/media/stagefright/foundation/ALooperRoster.h
@@ -31,9 +31,14 @@
 
     void unregisterHandler(ALooper::handler_id handlerID);
 
-    void postMessage(const sp<AMessage> &msg, int64_t delayUs = 0);
+    status_t postMessage(const sp<AMessage> &msg, int64_t delayUs = 0);
     void deliverMessage(const sp<AMessage> &msg);
 
+    status_t postAndAwaitResponse(
+            const sp<AMessage> &msg, sp<AMessage> *response);
+
+    void postReply(uint32_t replyID, const sp<AMessage> &reply);
+
     sp<ALooper> findLooper(ALooper::handler_id handlerID);
 
 private:
@@ -45,6 +50,12 @@
     Mutex mLock;
     KeyedVector<ALooper::handler_id, HandlerInfo> mHandlers;
     ALooper::handler_id mNextHandlerID;
+    uint32_t mNextReplyID;
+    Condition mRepliesCondition;
+
+    KeyedVector<uint32_t, sp<AMessage> > mReplies;
+
+    status_t postMessage_l(const sp<AMessage> &msg, int64_t delayUs);
 
     DISALLOW_EVIL_CONSTRUCTORS(ALooperRoster);
 };
diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h
index 72dc730..7ec54aa 100644
--- a/include/media/stagefright/foundation/AMessage.h
+++ b/include/media/stagefright/foundation/AMessage.h
@@ -72,6 +72,17 @@
 
     void post(int64_t delayUs = 0);
 
+    // Posts the message to its target and waits for a response (or error)
+    // before returning.
+    status_t postAndAwaitResponse(sp<AMessage> *response);
+
+    // If this returns true, the sender of this message is synchronously
+    // awaiting a response, the "replyID" can be used to send the response
+    // via "postReply" below.
+    bool senderAwaitsResponse(uint32_t *replyID) const;
+
+    void postReply(uint32_t replyID);
+
     // Performs a deep-copy of "this", contained messages are in turn "dup'ed".
     // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
     // their refcount incremented.
diff --git a/include/media/stagefright/openmax/OMX_IVCommon.h b/include/media/stagefright/openmax/OMX_IVCommon.h
index 97170d7..65b6339 100644
--- a/include/media/stagefright/openmax/OMX_IVCommon.h
+++ b/include/media/stagefright/openmax/OMX_IVCommon.h
@@ -154,7 +154,8 @@
      * Gralloc Buffers.
      * FIXME: In the process of reserving some enum values for
      * Android-specific OMX IL colorformats. Change this enum to
-     * an acceptable range once that is done.*/
+     * an acceptable range once that is done.
+     * */
     OMX_COLOR_FormatAndroidOpaque = 0x7F000001,
     OMX_TI_COLOR_FormatYUV420PackedSemiPlanar = 0x7F000100,
     OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00,
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index 370253a..b9deafc 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -62,6 +62,7 @@
         USAGE_HW_TEXTURE        = GRALLOC_USAGE_HW_TEXTURE,
         USAGE_HW_RENDER         = GRALLOC_USAGE_HW_RENDER,
         USAGE_HW_2D             = GRALLOC_USAGE_HW_2D,
+        USAGE_HW_COMPOSER       = GRALLOC_USAGE_HW_COMPOSER,
         USAGE_HW_MASK           = GRALLOC_USAGE_HW_MASK
     };
 
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index ac9b33b..79a01a3 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -608,6 +608,9 @@
             if (mConnectedApi == api) {
                 drainQueueAndFreeBuffersLocked();
                 mConnectedApi = NO_CONNECTED_API;
+                mNextCrop.makeInvalid();
+                mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
+                mNextTransform = 0;
                 mDequeueCondition.signal();
             } else {
                 LOGE("disconnect: connected to another api (cur=%d, req=%d)",
@@ -1022,7 +1025,7 @@
             mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
             mCurrentTransform, mCurrentTexture,
             prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, mNextCrop.bottom,
-            mCurrentTransform, fifoSize, fifo.string()
+            mNextTransform, fifoSize, fifo.string()
     );
     result.append(buffer);
 
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 5a35b4d..710ef94 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -407,8 +407,15 @@
     LOGV("SurfaceTextureClient::disconnect");
     Mutex::Autolock lock(mMutex);
     int err = mSurfaceTexture->disconnect(api);
-    if (!err && api == NATIVE_WINDOW_API_CPU) {
-        mConnectedToCpu = false;
+    if (!err) {
+        freeAllBuffers();
+        mReqFormat = 0;
+        mReqWidth = 0;
+        mReqHeight = 0;
+        mReqUsage = 0;
+        if (api == NATIVE_WINDOW_API_CPU) {
+            mConnectedToCpu = false;
+        }
     }
     return err;
 }
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 88cfc5a..cedf456 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -194,6 +194,7 @@
 
 void DisplayList::init() {
     mSize = 0;
+    mIsRenderable = true;
 }
 
 size_t DisplayList::getSize() {
@@ -892,7 +893,7 @@
 // Base structure
 ///////////////////////////////////////////////////////////////////////////////
 
-DisplayListRenderer::DisplayListRenderer(): mWriter(MIN_WRITER_SIZE) {
+DisplayListRenderer::DisplayListRenderer(): mWriter(MIN_WRITER_SIZE), mHasDrawOps(false) {
 }
 
 DisplayListRenderer::~DisplayListRenderer() {
@@ -926,6 +927,8 @@
     mPathMap.clear();
 
     mMatrices.clear();
+
+    mHasDrawOps = false;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -938,6 +941,7 @@
     } else {
         displayList->initFromDisplayListRenderer(*this, true);
     }
+    displayList->setRenderable(mHasDrawOps);
     return displayList;
 }
 
@@ -982,7 +986,11 @@
 }
 
 void DisplayListRenderer::restore() {
-    addOp(DisplayList::Restore);
+    if (mRestoreSaveCount < 0) {
+        addOp(DisplayList::Restore);
+    } else {
+        mRestoreSaveCount--;
+    }
     OpenGLRenderer::restore();
 }
 
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 69e72a4..8cd7fea 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -63,6 +63,7 @@
     // IMPORTANT: Update the intialization of OP_NAMES in the .cpp file
     //            when modifying this file
     enum Op {
+        // Non-drawing operations
         Save = 0,
         Restore,
         RestoreToCount,
@@ -75,6 +76,7 @@
         SetMatrix,
         ConcatMatrix,
         ClipRect,
+        // Drawing operations
         DrawDisplayList,
         DrawLayer,
         DrawBitmap,
@@ -113,6 +115,14 @@
 
     static void outputLogBuffer(int fd);
 
+    void setRenderable(bool renderable) {
+        mIsRenderable = renderable;
+    }
+
+    bool isRenderable() const {
+        return mIsRenderable;
+    }
+
 private:
     void init();
 
@@ -207,6 +217,8 @@
     mutable SkFlattenableReadBuffer mReader;
 
     size_t mSize;
+
+    bool mIsRenderable;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -328,6 +340,7 @@
     inline void addOp(DisplayList::Op drawOp) {
         insertRestoreToCount();
         mWriter.writeInt(drawOp);
+        mHasDrawOps = mHasDrawOps || drawOp >= DisplayList::DrawDisplayList;
     }
 
     inline void addInt(int value) {
@@ -479,6 +492,7 @@
     SkWriter32 mWriter;
 
     int mRestoreSaveCount;
+    bool mHasDrawOps;
 
     friend class DisplayList;
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index e89d6ec..a20a88e 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1278,7 +1278,7 @@
 
     // All the usual checks and setup operations (quickReject, setupDraw, etc.)
     // will be performed by the display list itself
-    if (displayList) {
+    if (displayList && displayList->isRenderable()) {
         return displayList->replay(*this, dirty, level);
     }
 
@@ -1493,7 +1493,8 @@
         const float y = (int) floorf(dstTop + mSnapshot->transform->getTranslateY() + 0.5f);
 
         GLenum filter = GL_NEAREST;
-        if (u1 > 0.0f || u2 < 1.0f || v1 > 0.0f || v2 < 1.0f) {
+        // Enable linear filtering if the source rectangle is scaled
+        if (srcRight - srcLeft != dstRight - dstLeft || srcBottom - srcTop != dstBottom - dstTop) {
             filter = GL_LINEAR;
         }
         texture->setFilter(filter, filter, true);
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index 36bbdf0..d6ab0da 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -284,6 +284,15 @@
     }
 }
 
+Element::Builder::Builder() {
+    const uint32_t initialCapacity = 32;
+    mBuilderElementRefs.setCapacity(initialCapacity);
+    mBuilderElements.setCapacity(initialCapacity);
+    mBuilderNameStrings.setCapacity(initialCapacity);
+    mBuilderNameLengths.setCapacity(initialCapacity);
+    mBuilderArrays.setCapacity(initialCapacity);
+}
+
 void Element::Builder::add(const Element *e, const char *nameStr, uint32_t arraySize) {
     mBuilderElementRefs.push(ObjectBaseRef<const Element>(e));
     mBuilderElements.push(e);
@@ -303,41 +312,12 @@
 
 
 ElementState::ElementState() {
-    const uint32_t initialCapacity = 32;
-    mBuilderElements.setCapacity(initialCapacity);
-    mBuilderNameStrings.setCapacity(initialCapacity);
-    mBuilderNameLengths.setCapacity(initialCapacity);
-    mBuilderArrays.setCapacity(initialCapacity);
 }
 
 ElementState::~ElementState() {
     rsAssert(!mElements.size());
 }
 
-void ElementState::elementBuilderBegin() {
-    mBuilderElements.clear();
-    mBuilderNameStrings.clear();
-    mBuilderNameLengths.clear();
-    mBuilderArrays.clear();
-}
-
-void ElementState::elementBuilderAdd(const Element *e, const char *nameStr, uint32_t arraySize) {
-    mBuilderElements.push(e);
-    mBuilderNameStrings.push(nameStr);
-    mBuilderNameLengths.push(strlen(nameStr));
-    mBuilderArrays.push(arraySize);
-
-}
-
-const Element *ElementState::elementBuilderCreate(Context *rsc) {
-    return Element::create(rsc, mBuilderElements.size(),
-                           &(mBuilderElements.editArray()[0]),
-                           &(mBuilderNameStrings.editArray()[0]),
-                           mBuilderNameLengths.editArray(),
-                           mBuilderArrays.editArray());
-}
-
-
 /////////////////////////////////////////
 //
 
diff --git a/libs/rs/rsElement.h b/libs/rs/rsElement.h
index c3ef250..bfdec53 100644
--- a/libs/rs/rsElement.h
+++ b/libs/rs/rsElement.h
@@ -30,6 +30,7 @@
 public:
     class Builder {
     public:
+        Builder();
         void add(const Element *e, const char *nameStr, uint32_t arraySize);
         ObjectBaseRef<const Element> create(Context *rsc);
     private:
@@ -135,17 +136,8 @@
     ElementState();
     ~ElementState();
 
-    void elementBuilderBegin();
-    void elementBuilderAdd(const Element *e, const char *nameStr, uint32_t arraySize);
-    const Element *elementBuilderCreate(Context *rsc);
-
     // Cache of all existing elements.
     Vector<Element *> mElements;
-private:
-    Vector<const Element *> mBuilderElements;
-    Vector<const char*> mBuilderNameStrings;
-    Vector<size_t> mBuilderNameLengths;
-    Vector<uint32_t> mBuilderArrays;
 };
 
 
diff --git a/libs/rs/rsLocklessFifo.cpp b/libs/rs/rsLocklessFifo.cpp
index 02a76ab..4d02269 100644
--- a/libs/rs/rsLocklessFifo.cpp
+++ b/libs/rs/rsLocklessFifo.cpp
@@ -21,11 +21,11 @@
 using namespace android;
 using namespace android::renderscript;
 
-LocklessCommandFifo::LocklessCommandFifo() : mBuffer(0) {
+LocklessCommandFifo::LocklessCommandFifo() : mBuffer(0), mInitialized(false) {
 }
 
 LocklessCommandFifo::~LocklessCommandFifo() {
-    if (!mInShutdown) {
+    if (!mInShutdown && mInitialized) {
         shutdown();
     }
     if (mBuffer) {
@@ -58,6 +58,7 @@
     mGet = mBuffer;
     mEnd = mBuffer + (sizeInBytes) - 1;
     //dumpState("init");
+    mInitialized = true;
     return true;
 }
 
diff --git a/libs/rs/rsLocklessFifo.h b/libs/rs/rsLocklessFifo.h
index 4962ef6..fa53d40 100644
--- a/libs/rs/rsLocklessFifo.h
+++ b/libs/rs/rsLocklessFifo.h
@@ -47,6 +47,7 @@
     uint8_t * mEnd;
     uint8_t mSize;
     bool mInShutdown;
+    bool mInitialized;
 
     Signal mSignalToWorker;
     Signal mSignalToControl;
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index acc2b23..fe57e8a 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -3072,11 +3072,13 @@
     /**
      * Update the remote control displays with the new "focused" client generation
      */
-    private void setNewRcClientGenerationOnDisplays_syncRcStack(int newClientGeneration) {
+    private void setNewRcClientOnDisplays_syncAfRcsCurrc(int newClientGeneration,
+            ComponentName newClientEventReceiver, boolean clearing) {
         // NOTE: Only one IRemoteControlDisplay supported in this implementation
         if (mRcDisplay != null) {
             try {
-                mRcDisplay.setCurrentClientGenerationId(newClientGeneration);
+                mRcDisplay.setCurrentClientId(
+                        newClientGeneration, newClientEventReceiver, clearing);
             } catch (RemoteException e) {
                 Log.e(TAG, "Dead display in onRcDisplayUpdate() "+e);
                 // if we had a display before, stop monitoring its death
@@ -3089,7 +3091,7 @@
     /**
      * Update the remote control clients with the new "focused" client generation
      */
-    private void setNewRcClientGenerationOnClients_syncRcStack(int newClientGeneration) {
+    private void setNewRcClientGenerationOnClients_syncAfRcsCurrc(int newClientGeneration) {
         Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
         while(stackIterator.hasNext()) {
             RemoteControlStackEntry se = stackIterator.next();
@@ -3106,15 +3108,20 @@
     }
 
     /**
-     * Update the displays and clients with the new "focused" client generation
+     * Update the displays and clients with the new "focused" client generation and name
+     * @param newClientGeneration the new generation value matching a client update
+     * @param newClientEventReceiver the media button event receiver associated with the client.
+     *    May be null, which implies there is no registered media button event receiver.
+     * @param clearing true if the new client generation value maps to a remote control update
+     *    where the display should be cleared.
      */
-    private void setNewRcClientGeneration(int newClientGeneration) {
-        synchronized(mRCStack) {
-            // send the new valid client generation ID to all displays
-            setNewRcClientGenerationOnDisplays_syncRcStack(newClientGeneration);
-            // send the new valid client generation ID to all clients
-            setNewRcClientGenerationOnClients_syncRcStack(newClientGeneration);
-        }
+    private void setNewRcClient_syncAfRcsCurrc(int newClientGeneration,
+            ComponentName newClientEventReceiver, boolean clearing) {
+        // send the new valid client generation ID to all displays
+        setNewRcClientOnDisplays_syncAfRcsCurrc(newClientGeneration, newClientEventReceiver,
+                clearing);
+        // send the new valid client generation ID to all clients
+        setNewRcClientGenerationOnClients_syncAfRcsCurrc(newClientGeneration);
     }
 
     /**
@@ -3124,11 +3131,13 @@
         // TODO remove log before release
         Log.i(TAG, "Clear remote control display");
 
-        synchronized(mCurrentRcLock) {
-            mCurrentRcClientGen++;
-
-            // synchronously update the displays and clients with the new client generation
-            setNewRcClientGeneration(mCurrentRcClientGen);
+        synchronized(mRCStack) {
+            synchronized(mCurrentRcLock) {
+                mCurrentRcClientGen++;
+                // synchronously update the displays and clients with the new client generation
+                setNewRcClient_syncAfRcsCurrc(mCurrentRcClientGen,
+                        null /*event receiver*/, true /*clearing*/);
+            }
         }
     }
 
@@ -3136,28 +3145,32 @@
      * Called when processing MSG_RCDISPLAY_UPDATE event
      */
     private void onRcDisplayUpdate(RemoteControlStackEntry rcse, int flags /* USED ?*/) {
-        synchronized(mCurrentRcLock) {
-            if ((mCurrentRcClient != null) && (mCurrentRcClient.equals(rcse.mRcClient))) {
-                // TODO remove log before release
-                Log.i(TAG, "Display/update remote control ");
+        synchronized(mRCStack) {
+            synchronized(mCurrentRcLock) {
+                if ((mCurrentRcClient != null) && (mCurrentRcClient.equals(rcse.mRcClient))) {
+                    // TODO remove log before release
+                    Log.i(TAG, "Display/update remote control ");
 
-                mCurrentRcClientGen++;
+                    mCurrentRcClientGen++;
+                    // synchronously update the displays and clients with
+                    //      the new client generation
+                    setNewRcClient_syncAfRcsCurrc(mCurrentRcClientGen,
+                            rcse.mReceiverComponent /*event receiver*/,
+                            false /*clearing*/);
 
-                // synchronously update the displays and clients with the new client generation
-                setNewRcClientGeneration(mCurrentRcClientGen);
-
-                // ask the current client that it needs to send info
-                try {
-                    mCurrentRcClient.onInformationRequested(mCurrentRcClientGen,
-                            flags, mArtworkExpectedWidth, mArtworkExpectedHeight);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Current valid remote client is dead: "+e);
-                    mCurrentRcClient = null;
+                    // ask the current client that it needs to send info
+                    try {
+                        mCurrentRcClient.onInformationRequested(mCurrentRcClientGen,
+                                flags, mArtworkExpectedWidth, mArtworkExpectedHeight);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Current valid remote client is dead: "+e);
+                        mCurrentRcClient = null;
+                    }
+                } else {
+                    // the remote control display owner has changed between the
+                    // the message to update the display was sent, and the time it
+                    // gets to be processed (now)
                 }
-            } else {
-                // the remote control display owner has changed between the
-                // the message to update the display was sent, and the time it
-                // gets to be processed (now)
             }
         }
     }
@@ -3320,10 +3333,31 @@
         }
     }
 
-    /** see AudioManager.unregisterRemoteControlClient(ComponentName eventReceiver, ...) */
+    /**
+     * see AudioManager.unregisterRemoteControlClient(ComponentName eventReceiver, ...)
+     * rcClient is guaranteed non-null
+     */
     public void unregisterRemoteControlClient(ComponentName eventReceiver,
             IRemoteControlClient rcClient) {
-        //FIXME implement
+        synchronized(mAudioFocusLock) {
+            synchronized(mRCStack) {
+                Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
+                while(stackIterator.hasNext()) {
+                    RemoteControlStackEntry rcse = stackIterator.next();
+                    if ((rcse.mReceiverComponent.equals(eventReceiver))
+                            && rcClient.equals(rcse.mRcClient)) {
+                        // we found the IRemoteControlClient to unregister
+                        // stop monitoring its death
+                        rcse.unlinkToRcClientDeath();
+                        // reset the client-related fields
+                        rcse.mRcClient = null;
+                        rcse.mRcClientName = null;
+                        rcse.mRcClientDeathHandler = null;
+                        rcse.mCallingPackageName = null;
+                    }
+                }
+            }
+        }
     }
 
     /**
diff --git a/media/java/android/media/IRemoteControlDisplay.aidl b/media/java/android/media/IRemoteControlDisplay.aidl
index d000906..fd50b7e 100644
--- a/media/java/android/media/IRemoteControlDisplay.aidl
+++ b/media/java/android/media/IRemoteControlDisplay.aidl
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.content.ComponentName;
 import android.graphics.Bitmap;
 import android.os.Bundle;
 
@@ -29,15 +30,23 @@
 {
     /**
      * Sets the generation counter of the current client that is displayed on the remote control.
+     * @param clientGeneration the new RemoteControlClient generation
+     * @param clientEventReceiver the media button event receiver associated with the client.
+     *    May be null, which implies there is no registered media button event receiver. This
+     *    parameter is supplied as an optimization so a display can directly target media button
+     *    events to the client.
+     * @param clearing true if the new client generation value maps to a remote control update
+     *    where the display should be cleared.
      */
-    void setCurrentClientGenerationId(int clientGeneration);
+    void setCurrentClientId(int clientGeneration, in ComponentName clientEventReceiver,
+            boolean clearing);
 
     void setPlaybackState(int generationId, int state);
 
-    void setMetadata(int generationId, in Bundle metadata);
-
     void setTransportControlFlags(int generationId, int transportControlFlags);
 
+    void setMetadata(int generationId, in Bundle metadata);
+
     void setArtwork(int generationId, in Bitmap artwork);
 
     /**
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 3949c39..cecedb5 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -259,6 +259,7 @@
     mMarkerReached = false;
     mNewPosition = 0;
     mUpdatePeriod = 0;
+    mFlushed = false;
     mFlags = flags;
     AudioSystem::acquireAudioSessionId(mSessionId);
 
@@ -337,6 +338,7 @@
     audio_track_cblk_t* cblk = mCblk;
 
     if (mActive == 0) {
+        mFlushed = false;
         mActive = 1;
         mNewPosition = cblk->server + mUpdatePeriod;
         cblk->lock.lock();
@@ -437,6 +439,7 @@
     mUpdatePeriod = 0;
 
     if (!mActive) {
+        mFlushed = true;
         mAudioTrack->flush();
         // Release AudioTrack callback thread in case it was waiting for new buffers
         // in AudioTrack::obtainBuffer()
@@ -655,7 +658,7 @@
 {
     if (position == 0) return BAD_VALUE;
     AutoMutex lock(mLock);
-    *position = mCblk->server;
+    *position = mFlushed ? 0 : mCblk->server;
 
     return NO_ERROR;
 }
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index dd69e6b..d41ab1b 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -180,6 +180,8 @@
         } else {
             mAudioTrack->stop();
         }
+
+        mNumFramesPlayed = 0;
     } else {
         if (mAudioSink.get() != NULL) {
             mAudioSink->pause();
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index f2673b3..bc42a42 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1318,6 +1318,7 @@
 
 status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
     if (mRTSPController != NULL) {
+        mSeekNotificationSent = false;
         mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
         return OK;
     }
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index ac3565f6..256f3ba 100755
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -635,6 +635,12 @@
     mStarted = false;
     mFrameAvailableCondition.signal();
 
+    int64_t token;
+    bool isTokenValid = false;
+    if (mCamera != 0) {
+        token = IPCThreadState::self()->clearCallingIdentity();
+        isTokenValid = true;
+    }
     releaseQueuedFrames();
     while (!mFramesBeingEncoded.empty()) {
         if (NO_ERROR !=
@@ -645,6 +651,9 @@
     }
     stopCameraRecording();
     releaseCamera();
+    if (isTokenValid) {
+        IPCThreadState::self()->restoreCallingIdentity(token);
+    }
 
     if (mCollectStats) {
         LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 27dfeab..7f09319 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -808,7 +808,7 @@
         }
 
         if (format.eCompressionFormat == compressionFormat
-            && format.eColorFormat == colorFormat) {
+                && format.eColorFormat == colorFormat) {
             found = true;
             break;
         }
@@ -838,6 +838,15 @@
         case OMX_COLOR_FormatYUV420Planar:
         case OMX_COLOR_FormatYUV420SemiPlanar:
         case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
+        /*
+        * FIXME: For the Opaque color format, the frame size does not
+        * need to be (w*h*3)/2. It just needs to
+        * be larger than certain minimum buffer size. However,
+        * currently, this opaque foramt has been tested only on
+        * YUV420 formats. If that is changed, then we need to revisit
+        * this part in the future
+        */
+        case OMX_COLOR_FormatAndroidOpaque:
             return (width * height * 3) / 2;
 
         default:
@@ -887,7 +896,7 @@
         // Make sure that omx component does not overwrite
         // the incremented index (bug 2897413).
         CHECK_EQ(index, portFormat.nIndex);
-        if ((portFormat.eColorFormat == colorFormat)) {
+        if (portFormat.eColorFormat == colorFormat) {
             LOGV("Found supported color format: %d", portFormat.eColorFormat);
             return OK;  // colorFormat is supported!
         }
@@ -2316,6 +2325,7 @@
         {
             CODEC_LOGV("OMX_EventPortSettingsChanged(port=%ld, data2=0x%08lx)",
                        data1, data2);
+            CHECK(mFilledBuffers.empty());
 
             if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
                 onPortSettingsChanged(data1);
@@ -2923,6 +2933,7 @@
     size_t offset = 0;
     int32_t n = 0;
 
+
     for (;;) {
         MediaBuffer *srcBuffer;
         if (mSeekTimeUs >= 0) {
@@ -3021,6 +3032,7 @@
                 CHECK(info->mMediaBuffer == NULL);
                 info->mMediaBuffer = srcBuffer;
             } else {
+                CHECK(srcBuffer->data() != NULL) ;
                 memcpy((uint8_t *)info->mData + offset,
                         (const uint8_t *)srcBuffer->data()
                             + srcBuffer->range_offset(),
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index ddfd9ff..c2e6707 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 // #define LOG_NDEBUG 0
 #define LOG_TAG "SurfaceMediaSource"
 
@@ -47,7 +46,9 @@
                 mSynchronousMode(true),
                 mConnectedApi(NO_CONNECTED_API),
                 mFrameRate(30),
-                mStarted(false)   {
+                mNumFramesReceived(0),
+                mNumFramesEncoded(0),
+                mStopped(false) {
     LOGV("SurfaceMediaSource::SurfaceMediaSource");
     sp<ISurfaceComposer> composer(ComposerService::getComposerService());
     mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
@@ -55,10 +56,9 @@
 
 SurfaceMediaSource::~SurfaceMediaSource() {
     LOGV("SurfaceMediaSource::~SurfaceMediaSource");
-    if (mStarted) {
+    if (!mStopped) {
         stop();
     }
-    freeAllBuffers();
 }
 
 size_t SurfaceMediaSource::getQueuedCount() const {
@@ -139,12 +139,12 @@
 
     // here we're guaranteed that the client doesn't have dequeued buffers
     // and will release all of its buffer references.
-    freeAllBuffers();
     mBufferCount = bufferCount;
     mClientBufferCount = bufferCount;
     mCurrentSlot = INVALID_BUFFER_SLOT;
     mQueue.clear();
     mDequeueCondition.signal();
+    freeAllBuffersLocked();
     return OK;
 }
 
@@ -164,7 +164,7 @@
 status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
                                             uint32_t format, uint32_t usage) {
     LOGV("dequeueBuffer");
-
+    Mutex::Autolock lock(mMutex);
 
     // Check for the buffer size- the client should just use the
     // default width and height, and not try to set those.
@@ -184,10 +184,7 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock lock(mMutex);
-
     status_t returnFlags(OK);
-
     int found, foundSync;
     int dequeuedCount = 0;
     bool tryAgain = true;
@@ -218,6 +215,9 @@
                 LOGV("Waiting for the FIFO to drain");
                 mDequeueCondition.wait(mMutex);
             }
+            if (mStopped) {
+                return NO_INIT;
+            }
             // need to check again since the mode could have changed
             // while we were waiting
             minBufferCountNeeded = mSynchronousMode ?
@@ -228,7 +228,7 @@
                 ((mServerBufferCount != mBufferCount) ||
                         (mServerBufferCount < minBufferCountNeeded))) {
             // here we're guaranteed that mQueue is empty
-            freeAllBuffers();
+            freeAllBuffersLocked();
             mBufferCount = mServerBufferCount;
             if (mBufferCount < minBufferCountNeeded)
                 mBufferCount = minBufferCountNeeded;
@@ -290,9 +290,12 @@
         // for for some buffers to be consumed
         tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
         if (tryAgain) {
-            LOGW("Waiting..In synchronous mode and no buffer to dQ");
+            LOGV("Waiting..In synchronous mode and no buffer to dequeue");
             mDequeueCondition.wait(mMutex);
         }
+        if (mStopped) {
+            return NO_INIT;
+        }
     }
 
     if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
@@ -304,7 +307,7 @@
         return -EBUSY;
     }
 
-    const int buf = found;
+    const int bufIndex = found;
     *outBuf = found;
 
     const bool useDefaultSize = !w && !h;
@@ -322,9 +325,9 @@
 
     // buffer is now in DEQUEUED (but can also be current at the same time,
     // if we're in synchronous mode)
-    mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
+    mSlots[bufIndex].mBufferState = BufferSlot::DEQUEUED;
 
-    const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
+    const sp<GraphicBuffer>& buffer(mSlots[bufIndex].mGraphicBuffer);
     if ((buffer == NULL) ||
         (uint32_t(buffer->width)  != w) ||
         (uint32_t(buffer->height) != h) ||
@@ -342,22 +345,25 @@
             if (updateFormat) {
                 mPixelFormat = format;
             }
-            mSlots[buf].mGraphicBuffer = graphicBuffer;
-            mSlots[buf].mRequestBufferCalled = false;
+            mSlots[bufIndex].mGraphicBuffer = graphicBuffer;
+            mSlots[bufIndex].mRequestBufferCalled = false;
             returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
     }
     return returnFlags;
 }
 
+// TODO: clean this up
 status_t SurfaceMediaSource::setSynchronousMode(bool enabled) {
     Mutex::Autolock lock(mMutex);
+    if (mStopped) {
+        LOGE("setSynchronousMode: SurfaceMediaSource has been stopped!");
+        return NO_INIT;
+    }
 
-    status_t err = OK;
     if (!enabled) {
-        // going to asynchronous mode, drain the queue
-        while (mSynchronousMode != enabled && !mQueue.isEmpty()) {
-            mDequeueCondition.wait(mMutex);
-        }
+        // Async mode is not allowed
+        LOGE("SurfaceMediaSource can be used only synchronous mode!");
+        return INVALID_OPERATION;
     }
 
     if (mSynchronousMode != enabled) {
@@ -368,13 +374,19 @@
         mSynchronousMode = enabled;
         mDequeueCondition.signal();
     }
-    return err;
+    return OK;
 }
 
 status_t SurfaceMediaSource::connect(int api,
         uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
     LOGV("SurfaceMediaSource::connect");
     Mutex::Autolock lock(mMutex);
+
+    if (mStopped) {
+        LOGE("Connect: SurfaceMediaSource has been stopped!");
+        return NO_INIT;
+    }
+
     status_t err = NO_ERROR;
     switch (api) {
         case NATIVE_WINDOW_API_EGL:
@@ -397,9 +409,25 @@
     return err;
 }
 
+// This is called by the client side when it is done
+// TODO: Currently, this also sets mStopped to true which
+// is needed for unblocking the encoder which might be
+// waiting to read more frames. So if on the client side,
+// the same thread supplies the frames and also calls stop
+// on the encoder, the client has to call disconnect before
+// it calls stop.
+// In the case of the camera,
+// that need not be required since the thread supplying the
+// frames is separate than the one calling stop.
 status_t SurfaceMediaSource::disconnect(int api) {
     LOGV("SurfaceMediaSource::disconnect");
     Mutex::Autolock lock(mMutex);
+
+    if (mStopped) {
+        LOGE("disconnect: SurfaceMediaSoource is already stopped!");
+        return NO_INIT;
+    }
+
     status_t err = NO_ERROR;
     switch (api) {
         case NATIVE_WINDOW_API_EGL:
@@ -408,6 +436,9 @@
         case NATIVE_WINDOW_API_CAMERA:
             if (mConnectedApi == api) {
                 mConnectedApi = NO_CONNECTED_API;
+                mStopped = true;
+                mDequeueCondition.signal();
+                mFrameAvailableCondition.signal();
             } else {
                 err = -EINVAL;
             }
@@ -419,45 +450,47 @@
     return err;
 }
 
-status_t SurfaceMediaSource::queueBuffer(int buf, int64_t timestamp,
+status_t SurfaceMediaSource::queueBuffer(int bufIndex, int64_t timestamp,
         uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
     LOGV("queueBuffer");
 
     Mutex::Autolock lock(mMutex);
-    if (buf < 0 || buf >= mBufferCount) {
+    if (bufIndex < 0 || bufIndex >= mBufferCount) {
         LOGE("queueBuffer: slot index out of range [0, %d]: %d",
-                mBufferCount, buf);
+                mBufferCount, bufIndex);
         return -EINVAL;
-    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
+    } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) {
         LOGE("queueBuffer: slot %d is not owned by the client (state=%d)",
-                buf, mSlots[buf].mBufferState);
+                bufIndex, mSlots[bufIndex].mBufferState);
         return -EINVAL;
-    } else if (!mSlots[buf].mRequestBufferCalled) {
+    } else if (!mSlots[bufIndex].mRequestBufferCalled) {
         LOGE("queueBuffer: slot %d was enqueued without requesting a "
-                "buffer", buf);
+                "buffer", bufIndex);
         return -EINVAL;
     }
 
     if (mSynchronousMode) {
         // in synchronous mode we queue all buffers in a FIFO
-        mQueue.push_back(buf);
-        LOGV("Client queued buffer on slot: %d, Q size = %d",
-                                                buf, mQueue.size());
+        mQueue.push_back(bufIndex);
+        mNumFramesReceived++;
+        LOGV("Client queued buf# %d @slot: %d, Q size = %d, handle = %p, timestamp = %lld",
+            mNumFramesReceived, bufIndex, mQueue.size(),
+            mSlots[bufIndex].mGraphicBuffer->handle, timestamp);
     } else {
         // in asynchronous mode we only keep the most recent buffer
         if (mQueue.empty()) {
-            mQueue.push_back(buf);
+            mQueue.push_back(bufIndex);
         } else {
             Fifo::iterator front(mQueue.begin());
             // buffer currently queued is freed
             mSlots[*front].mBufferState = BufferSlot::FREE;
             // and we record the new buffer index in the queued list
-            *front = buf;
+            *front = bufIndex;
         }
     }
 
-    mSlots[buf].mBufferState = BufferSlot::QUEUED;
-    mSlots[buf].mTimestamp = timestamp;
+    mSlots[bufIndex].mBufferState = BufferSlot::QUEUED;
+    mSlots[bufIndex].mTimestamp = timestamp;
     // TODO: (Confirm) Don't want to signal dequeue here.
     // May be just in asynchronous mode?
     // mDequeueCondition.signal();
@@ -482,7 +515,7 @@
 // wait to hear from StageFrightRecorder to set the buffer FREE
 // Make sure this is called when the mutex is locked
 status_t SurfaceMediaSource::onFrameReceivedLocked() {
-    LOGV("On Frame Received");
+    LOGV("On Frame Received locked");
     // Signal the encoder that a new frame has arrived
     mFrameAvailableCondition.signal();
 
@@ -501,19 +534,19 @@
 }
 
 
-void SurfaceMediaSource::cancelBuffer(int buf) {
+void SurfaceMediaSource::cancelBuffer(int bufIndex) {
     LOGV("SurfaceMediaSource::cancelBuffer");
     Mutex::Autolock lock(mMutex);
-    if (buf < 0 || buf >= mBufferCount) {
+    if (bufIndex < 0 || bufIndex >= mBufferCount) {
         LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
-                mBufferCount, buf);
+                mBufferCount, bufIndex);
         return;
-    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
+    } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) {
         LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
-                buf, mSlots[buf].mBufferState);
+                bufIndex, mSlots[bufIndex].mBufferState);
         return;
     }
-    mSlots[buf].mBufferState = BufferSlot::FREE;
+    mSlots[bufIndex].mBufferState = BufferSlot::FREE;
     mDequeueCondition.signal();
 }
 
@@ -531,8 +564,8 @@
     mFrameAvailableListener = listener;
 }
 
-void SurfaceMediaSource::freeAllBuffers() {
-    LOGV("freeAllBuffers");
+void SurfaceMediaSource::freeAllBuffersLocked() {
+    LOGV("freeAllBuffersLocked");
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         mSlots[i].mGraphicBuffer = 0;
         mSlots[i].mBufferState = BufferSlot::FREE;
@@ -648,10 +681,7 @@
 
 status_t SurfaceMediaSource::start(MetaData *params)
 {
-    LOGV("start");
-    Mutex::Autolock lock(mMutex);
-    CHECK(!mStarted);
-    mStarted = true;
+    LOGV("started!");
     return OK;
 }
 
@@ -662,8 +692,11 @@
 
     Mutex::Autolock lock(mMutex);
     // TODO: Add waiting on mFrameCompletedCondition here?
-    mStarted = false;
+    mStopped = true;
     mFrameAvailableCondition.signal();
+    mDequeueCondition.signal();
+    mQueue.clear();
+    freeAllBuffersLocked();
 
     return OK;
 }
@@ -688,23 +721,25 @@
 }
 
 status_t SurfaceMediaSource::read( MediaBuffer **buffer,
-                                const ReadOptions *options)
+                                    const ReadOptions *options)
 {
+    Mutex::Autolock autoLock(mMutex) ;
+
     LOGV("Read. Size of queued buffer: %d", mQueue.size());
     *buffer = NULL;
 
-    Mutex::Autolock autoLock(mMutex) ;
     // If the recording has started and the queue is empty, then just
     // wait here till the frames come in from the client side
-    while (mStarted && mQueue.empty()) {
+    while (!mStopped && mQueue.empty()) {
         LOGV("NO FRAMES! Recorder waiting for FrameAvailableCondition");
         mFrameAvailableCondition.wait(mMutex);
     }
 
     // If the loop was exited as a result of stopping the recording,
     // it is OK
-    if (!mStarted) {
-        return OK;
+    if (mStopped) {
+        LOGV("Read: SurfaceMediaSource is stopped. Returning NO_INIT;");
+        return NO_INIT;
     }
 
     // Update the current buffer info
@@ -712,15 +747,20 @@
     // can be more than one "current" slots.
     Fifo::iterator front(mQueue.begin());
     mCurrentSlot = *front;
+    mQueue.erase(front);
     mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer;
+    int64_t prevTimeStamp = mCurrentTimestamp;
     mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp;
-
+    mNumFramesEncoded++;
     // Pass the data to the MediaBuffer. Pass in only the metadata
     passMetadataBufferLocked(buffer);
 
     (*buffer)->setObserver(this);
     (*buffer)->add_ref();
-    (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp);
+    (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp / 1000);
+    LOGV("Frames encoded = %d, timestamp = %lld, time diff = %lld",
+            mNumFramesEncoded, mCurrentTimestamp / 1000,
+            mCurrentTimestamp / 1000 - prevTimeStamp / 1000);
 
     return OK;
 }
@@ -743,15 +783,17 @@
         new MediaBuffer(4 + sizeof(buffer_handle_t));
     char *data = (char *)tempBuffer->data();
     if (data == NULL) {
-        LOGE("Cannot allocate memory for passing buffer metadata!");
+        LOGE("Cannot allocate memory for metadata buffer!");
         return;
     }
     OMX_U32 type = kMetadataBufferTypeGrallocSource;
     memcpy(data, &type, 4);
     memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t));
     *buffer = tempBuffer;
-}
 
+    LOGV("handle = %p, , offset = %d, length = %d",
+            mCurrentBuf->handle, (*buffer)->range_length(), (*buffer)->range_offset());
+}
 
 void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
     LOGV("signalBufferReturned");
@@ -759,16 +801,19 @@
     bool foundBuffer = false;
     Mutex::Autolock autoLock(mMutex);
 
-    if (!mStarted) {
-        LOGW("signalBufferReturned: mStarted = false! Nothing to do!");
+    if (mStopped) {
+        LOGV("signalBufferReturned: mStopped = true! Nothing to do!");
         return;
     }
 
-    for (Fifo::iterator it = mQueue.begin(); it != mQueue.end(); ++it) {
-        CHECK(mSlots[*it].mGraphicBuffer != NULL);
-        if (checkBufferMatchesSlot(*it, buffer)) {
-            mSlots[*it].mBufferState = BufferSlot::FREE;
-            mQueue.erase(it);
+    for (int id = 0; id < NUM_BUFFER_SLOTS; id++) {
+        if (mSlots[id].mGraphicBuffer == NULL) {
+            continue;
+        }
+        if (checkBufferMatchesSlot(id, buffer)) {
+            LOGV("Slot %d returned, matches handle = %p", id,
+                    mSlots[id].mGraphicBuffer->handle);
+            mSlots[id].mBufferState = BufferSlot::FREE;
             buffer->setObserver(0);
             buffer->release();
             mDequeueCondition.signal();
@@ -792,5 +837,4 @@
     return mSlots[slot].mGraphicBuffer->handle  ==  bufferHandle;
 }
 
-
 } // end of namespace android
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp
index 8aa1b15..e399f2f 100644
--- a/media/libstagefright/foundation/ALooperRoster.cpp
+++ b/media/libstagefright/foundation/ALooperRoster.cpp
@@ -27,7 +27,8 @@
 namespace android {
 
 ALooperRoster::ALooperRoster()
-    : mNextHandlerID(1) {
+    : mNextHandlerID(1),
+      mNextReplyID(1) {
 }
 
 ALooper::handler_id ALooperRoster::registerHandler(
@@ -70,15 +71,19 @@
     mHandlers.removeItemsAt(index);
 }
 
-void ALooperRoster::postMessage(
+status_t ALooperRoster::postMessage(
         const sp<AMessage> &msg, int64_t delayUs) {
     Mutex::Autolock autoLock(mLock);
+    return postMessage_l(msg, delayUs);
+}
 
+status_t ALooperRoster::postMessage_l(
+        const sp<AMessage> &msg, int64_t delayUs) {
     ssize_t index = mHandlers.indexOfKey(msg->target());
 
     if (index < 0) {
         LOGW("failed to post message. Target handler not registered.");
-        return;
+        return -ENOENT;
     }
 
     const HandlerInfo &info = mHandlers.valueAt(index);
@@ -91,10 +96,12 @@
              msg->target());
 
         mHandlers.removeItemsAt(index);
-        return;
+        return -ENOENT;
     }
 
     looper->post(msg, delayUs);
+
+    return OK;
 }
 
 void ALooperRoster::deliverMessage(const sp<AMessage> &msg) {
@@ -145,4 +152,38 @@
     return looper;
 }
 
+status_t ALooperRoster::postAndAwaitResponse(
+        const sp<AMessage> &msg, sp<AMessage> *response) {
+    Mutex::Autolock autoLock(mLock);
+
+    uint32_t replyID = mNextReplyID++;
+
+    msg->setInt32("replyID", replyID);
+
+    status_t err = postMessage_l(msg, 0 /* delayUs */);
+
+    if (err != OK) {
+        response->clear();
+        return err;
+    }
+
+    ssize_t index;
+    while ((index = mReplies.indexOfKey(replyID)) < 0) {
+        mRepliesCondition.wait(mLock);
+    }
+
+    *response = mReplies.valueAt(index);
+    mReplies.removeItemsAt(index);
+
+    return OK;
+}
+
+void ALooperRoster::postReply(uint32_t replyID, const sp<AMessage> &reply) {
+    Mutex::Autolock autoLock(mLock);
+
+    CHECK(mReplies.indexOfKey(replyID) < 0);
+    mReplies.add(replyID, reply);
+    mRepliesCondition.broadcast();
+}
+
 }  // namespace android
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index b592c3f..582bdba 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -27,6 +27,8 @@
 
 namespace android {
 
+extern ALooperRoster gLooperRoster;
+
 AMessage::AMessage(uint32_t what, ALooper::handler_id target)
     : mWhat(what),
       mTarget(target),
@@ -227,11 +229,30 @@
 }
 
 void AMessage::post(int64_t delayUs) {
-    extern ALooperRoster gLooperRoster;
-
     gLooperRoster.postMessage(this, delayUs);
 }
 
+status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
+    return gLooperRoster.postAndAwaitResponse(this, response);
+}
+
+void AMessage::postReply(uint32_t replyID) {
+    gLooperRoster.postReply(replyID, this);
+}
+
+bool AMessage::senderAwaitsResponse(uint32_t *replyID) const {
+    int32_t tmp;
+    bool found = findInt32("replyID", &tmp);
+
+    if (!found) {
+        return false;
+    }
+
+    *replyID = static_cast<uint32_t>(tmp);
+
+    return true;
+}
+
 sp<AMessage> AMessage::dup() const {
     sp<AMessage> msg = new AMessage(mWhat, mTarget);
     msg->mNumItems = mNumItems;
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index 2e66a2c..ce07e32 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -136,25 +136,29 @@
 void AnotherPacketSource::queueDiscontinuity(
         ATSParser::DiscontinuityType type,
         const sp<AMessage> &extra) {
+    Mutex::Autolock autoLock(mLock);
+
+    // Leave only discontinuities in the queue.
+    List<sp<ABuffer> >::iterator it = mBuffers.begin();
+    while (it != mBuffers.end()) {
+        sp<ABuffer> oldBuffer = *it;
+
+        int32_t oldDiscontinuityType;
+        if (!oldBuffer->meta()->findInt32(
+                    "discontinuity", &oldDiscontinuityType)) {
+            it = mBuffers.erase(it);
+            continue;
+        }
+
+        ++it;
+    }
+
+    mEOSResult = OK;
+
     sp<ABuffer> buffer = new ABuffer(0);
     buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type));
     buffer->meta()->setMessage("extra", extra);
 
-    Mutex::Autolock autoLock(mLock);
-
-#if 0
-    if (type == ATSParser::DISCONTINUITY_SEEK
-            || type == ATSParser::DISCONTINUITY_FORMATCHANGE) {
-        // XXX Fix this: This will also clear any pending discontinuities,
-        // If there's a pending DISCONTINUITY_FORMATCHANGE and the new
-        // discontinuity is "just" a DISCONTINUITY_SEEK, this will effectively
-        // downgrade the type of discontinuity received by the client.
-
-        mBuffers.clear();
-        mEOSResult = OK;
-    }
-#endif
-
     mBuffers.push_back(buffer);
     mCondition.signal();
 }
diff --git a/media/libstagefright/tests/Android.mk b/media/libstagefright/tests/Android.mk
index 3ea8f39..357feb1 100644
--- a/media/libstagefright/tests/Android.mk
+++ b/media/libstagefright/tests/Android.mk
@@ -19,12 +19,13 @@
 	libbinder \
 	libcutils \
 	libgui \
-	libstlport \
-	libui \
-	libutils \
+	libmedia \
 	libstagefright \
 	libstagefright_omx \
 	libstagefright_foundation \
+	libstlport \
+	libui \
+	libutils \
 
 LOCAL_STATIC_LIBRARIES := \
 	libgtest \
diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
index 5b32b68..d643a0b 100644
--- a/media/libstagefright/tests/SurfaceMediaSource_test.cpp
+++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
@@ -14,14 +14,17 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "SurfaceMediaSource_test"
 // #define LOG_NDEBUG 0
+#define LOG_TAG "SurfaceMediaSource_test"
 
 #include <gtest/gtest.h>
 #include <utils/String8.h>
 #include <utils/Errors.h>
+#include <fcntl.h>
+#include <unistd.h>
 
 #include <media/stagefright/SurfaceMediaSource.h>
+#include <media/mediarecorder.h>
 
 #include <gui/SurfaceTextureClient.h>
 #include <ui/GraphicBuffer.h>
@@ -33,24 +36,322 @@
 #include <ui/FramebufferNativeWindow.h>
 
 #include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/MPEG4Writer.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/OMXCodec.h>
 #include <OMX_Component.h>
 
 #include "DummyRecorder.h"
 
+
 namespace android {
 
+class GLTest : public ::testing::Test {
+protected:
 
+    GLTest():
+            mEglDisplay(EGL_NO_DISPLAY),
+            mEglSurface(EGL_NO_SURFACE),
+            mEglContext(EGL_NO_CONTEXT) {
+    }
+
+    virtual void SetUp() {
+        LOGV("GLTest::SetUp()");
+        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
+
+        EGLint majorVersion;
+        EGLint minorVersion;
+        EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        RecordProperty("EglVersionMajor", majorVersion);
+        RecordProperty("EglVersionMajor", minorVersion);
+
+        EGLint numConfigs = 0;
+        EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig,
+                1, &numConfigs));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS");
+        if (displaySecsEnv != NULL) {
+            mDisplaySecs = atoi(displaySecsEnv);
+            if (mDisplaySecs < 0) {
+                mDisplaySecs = 0;
+            }
+        } else {
+            mDisplaySecs = 0;
+        }
+
+        if (mDisplaySecs > 0) {
+            mComposerClient = new SurfaceComposerClient;
+            ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
+
+            mSurfaceControl = mComposerClient->createSurface(
+                    String8("Test Surface"), 0,
+                    getSurfaceWidth(), getSurfaceHeight(),
+                    PIXEL_FORMAT_RGB_888, 0);
+
+            ASSERT_TRUE(mSurfaceControl != NULL);
+            ASSERT_TRUE(mSurfaceControl->isValid());
+
+            SurfaceComposerClient::openGlobalTransaction();
+            ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
+            ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
+            SurfaceComposerClient::closeGlobalTransaction();
+
+            sp<ANativeWindow> window = mSurfaceControl->getSurface();
+            mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
+                    window.get(), NULL);
+        } else {
+            EGLint pbufferAttribs[] = {
+                EGL_WIDTH, getSurfaceWidth(),
+                EGL_HEIGHT, getSurfaceHeight(),
+                EGL_NONE };
+
+            mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig,
+                    pbufferAttribs);
+        }
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
+
+        mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT,
+                getContextAttribs());
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
+
+        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+                mEglContext));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        EGLint w, h;
+        EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        RecordProperty("EglSurfaceWidth", w);
+        RecordProperty("EglSurfaceHeight", h);
+
+        glViewport(0, 0, w, h);
+        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+    }
+
+    virtual void TearDown() {
+        // Display the result
+        if (mDisplaySecs > 0 && mEglSurface != EGL_NO_SURFACE) {
+            eglSwapBuffers(mEglDisplay, mEglSurface);
+            sleep(mDisplaySecs);
+        }
+
+        if (mComposerClient != NULL) {
+            mComposerClient->dispose();
+        }
+        if (mEglContext != EGL_NO_CONTEXT) {
+            eglDestroyContext(mEglDisplay, mEglContext);
+        }
+        if (mEglSurface != EGL_NO_SURFACE) {
+            eglDestroySurface(mEglDisplay, mEglSurface);
+        }
+        if (mEglDisplay != EGL_NO_DISPLAY) {
+            eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+                    EGL_NO_CONTEXT);
+            eglTerminate(mEglDisplay);
+        }
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    }
+
+    virtual EGLint const* getConfigAttribs() {
+        LOGV("GLTest getConfigAttribs");
+        static EGLint sDefaultConfigAttribs[] = {
+            EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+            EGL_RED_SIZE, 8,
+            EGL_GREEN_SIZE, 8,
+            EGL_BLUE_SIZE, 8,
+            EGL_ALPHA_SIZE, 8,
+            EGL_DEPTH_SIZE, 16,
+            EGL_STENCIL_SIZE, 8,
+            EGL_NONE };
+
+        return sDefaultConfigAttribs;
+    }
+
+    virtual EGLint const* getContextAttribs() {
+        static EGLint sDefaultContextAttribs[] = {
+            EGL_CONTEXT_CLIENT_VERSION, 2,
+            EGL_NONE };
+
+        return sDefaultContextAttribs;
+    }
+
+    virtual EGLint getSurfaceWidth() {
+        return 512;
+    }
+
+    virtual EGLint getSurfaceHeight() {
+        return 512;
+    }
+
+    void loadShader(GLenum shaderType, const char* pSource, GLuint* outShader) {
+        GLuint shader = glCreateShader(shaderType);
+        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+        if (shader) {
+            glShaderSource(shader, 1, &pSource, NULL);
+            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+            glCompileShader(shader);
+            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+            GLint compiled = 0;
+            glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+            if (!compiled) {
+                GLint infoLen = 0;
+                glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+                ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+                if (infoLen) {
+                    char* buf = (char*) malloc(infoLen);
+                    if (buf) {
+                        glGetShaderInfoLog(shader, infoLen, NULL, buf);
+                        printf("Shader compile log:\n%s\n", buf);
+                        free(buf);
+                        FAIL();
+                    }
+                } else {
+                    char* buf = (char*) malloc(0x1000);
+                    if (buf) {
+                        glGetShaderInfoLog(shader, 0x1000, NULL, buf);
+                        printf("Shader compile log:\n%s\n", buf);
+                        free(buf);
+                        FAIL();
+                    }
+                }
+                glDeleteShader(shader);
+                shader = 0;
+            }
+        }
+        ASSERT_TRUE(shader != 0);
+        *outShader = shader;
+    }
+
+    void createProgram(const char* pVertexSource, const char* pFragmentSource,
+            GLuint* outPgm) {
+        GLuint vertexShader, fragmentShader;
+        {
+            SCOPED_TRACE("compiling vertex shader");
+            loadShader(GL_VERTEX_SHADER, pVertexSource, &vertexShader);
+            if (HasFatalFailure()) {
+                return;
+            }
+        }
+        {
+            SCOPED_TRACE("compiling fragment shader");
+            loadShader(GL_FRAGMENT_SHADER, pFragmentSource, &fragmentShader);
+            if (HasFatalFailure()) {
+                return;
+            }
+        }
+
+        GLuint program = glCreateProgram();
+        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+        if (program) {
+            glAttachShader(program, vertexShader);
+            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+            glAttachShader(program, fragmentShader);
+            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+            glLinkProgram(program);
+            GLint linkStatus = GL_FALSE;
+            glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+            if (linkStatus != GL_TRUE) {
+                GLint bufLength = 0;
+                glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
+                if (bufLength) {
+                    char* buf = (char*) malloc(bufLength);
+                    if (buf) {
+                        glGetProgramInfoLog(program, bufLength, NULL, buf);
+                        printf("Program link log:\n%s\n", buf);
+                        free(buf);
+                        FAIL();
+                    }
+                }
+                glDeleteProgram(program);
+                program = 0;
+            }
+        }
+        glDeleteShader(vertexShader);
+        glDeleteShader(fragmentShader);
+        ASSERT_TRUE(program != 0);
+        *outPgm = program;
+    }
+
+    static int abs(int value) {
+        return value > 0 ? value : -value;
+    }
+
+    ::testing::AssertionResult checkPixel(int x, int y, int r,
+            int g, int b, int a, int tolerance=2) {
+        GLubyte pixel[4];
+        String8 msg;
+        glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+        GLenum err = glGetError();
+        if (err != GL_NO_ERROR) {
+            msg += String8::format("error reading pixel: %#x", err);
+            while ((err = glGetError()) != GL_NO_ERROR) {
+                msg += String8::format(", %#x", err);
+            }
+            fprintf(stderr, "pixel check failure: %s\n", msg.string());
+            return ::testing::AssertionFailure(
+                    ::testing::Message(msg.string()));
+        }
+        if (r >= 0 && abs(r - int(pixel[0])) > tolerance) {
+            msg += String8::format("r(%d isn't %d)", pixel[0], r);
+        }
+        if (g >= 0 && abs(g - int(pixel[1])) > tolerance) {
+            if (!msg.isEmpty()) {
+                msg += " ";
+            }
+            msg += String8::format("g(%d isn't %d)", pixel[1], g);
+        }
+        if (b >= 0 && abs(b - int(pixel[2])) > tolerance) {
+            if (!msg.isEmpty()) {
+                msg += " ";
+            }
+            msg += String8::format("b(%d isn't %d)", pixel[2], b);
+        }
+        if (a >= 0 && abs(a - int(pixel[3])) > tolerance) {
+            if (!msg.isEmpty()) {
+                msg += " ";
+            }
+            msg += String8::format("a(%d isn't %d)", pixel[3], a);
+        }
+        if (!msg.isEmpty()) {
+            fprintf(stderr, "pixel check failure: %s\n", msg.string());
+            return ::testing::AssertionFailure(
+                    ::testing::Message(msg.string()));
+        } else {
+            return ::testing::AssertionSuccess();
+        }
+    }
+
+    int mDisplaySecs;
+    sp<SurfaceComposerClient> mComposerClient;
+    sp<SurfaceControl> mSurfaceControl;
+
+    EGLDisplay mEglDisplay;
+    EGLSurface mEglSurface;
+    EGLContext mEglContext;
+    EGLConfig  mGlConfig;
+};
+
+///////////////////////////////////////////////////////////////////////
+//    Class for  the NON-GL tests
+///////////////////////////////////////////////////////////////////////
 class SurfaceMediaSourceTest : public ::testing::Test {
 public:
 
-    SurfaceMediaSourceTest( ): mYuvTexWidth(64), mYuvTexHeight(66) { }
-    sp<MPEG4Writer>  setUpWriter(OMXClient &client );
+    SurfaceMediaSourceTest( ): mYuvTexWidth(176), mYuvTexHeight(144) { }
     void oneBufferPass(int width, int height );
+    void oneBufferPassNoFill(int width, int height );
     static void fillYV12Buffer(uint8_t* buf, int w, int h, int stride) ;
     static void fillYV12BufferRect(uint8_t* buf, int w, int h,
                         int stride, const android_native_rect_t& rect) ;
@@ -62,10 +363,8 @@
         mSMS->setSynchronousMode(true);
         mSTC = new SurfaceTextureClient(mSMS);
         mANW = mSTC;
-
     }
 
-
     virtual void TearDown() {
         mSMS.clear();
         mSTC.clear();
@@ -78,11 +377,142 @@
     sp<SurfaceMediaSource> mSMS;
     sp<SurfaceTextureClient> mSTC;
     sp<ANativeWindow> mANW;
-
 };
 
+///////////////////////////////////////////////////////////////////////
+//    Class for  the GL tests
+///////////////////////////////////////////////////////////////////////
+class SurfaceMediaSourceGLTest : public GLTest {
+public:
+
+    SurfaceMediaSourceGLTest( ): mYuvTexWidth(176), mYuvTexHeight(144) { }
+    virtual EGLint const* getConfigAttribs();
+    void oneBufferPassGL(int num = 0);
+    static sp<MediaRecorder> setUpMediaRecorder(int fileDescriptor, int videoSource,
+        int outputFormat, int videoEncoder, int width, int height, int fps);
+protected:
+
+    virtual void SetUp() {
+        LOGV("SMS-GLTest::SetUp()");
+        android::ProcessState::self()->startThreadPool();
+        mSMS = new SurfaceMediaSource(mYuvTexWidth, mYuvTexHeight);
+        mSTC = new SurfaceTextureClient(mSMS);
+        mANW = mSTC;
+
+        // Doing the setup related to the GL Side
+        GLTest::SetUp();
+    }
+
+    virtual void TearDown() {
+        mSMS.clear();
+        mSTC.clear();
+        mANW.clear();
+        GLTest::TearDown();
+        eglDestroySurface(mEglDisplay, mSmsEglSurface);
+    }
+
+    void setUpEGLSurfaceFromMediaRecorder(sp<MediaRecorder>& mr);
+
+    const int mYuvTexWidth;
+    const int mYuvTexHeight;
+
+    sp<SurfaceMediaSource> mSMS;
+    sp<SurfaceTextureClient> mSTC;
+    sp<ANativeWindow> mANW;
+    EGLConfig  mSMSGlConfig;
+    EGLSurface  mSmsEglSurface;
+};
+
+/////////////////////////////////////////////////////////////////////
+// Methods in SurfaceMediaSourceGLTest
+/////////////////////////////////////////////////////////////////////
+EGLint const* SurfaceMediaSourceGLTest::getConfigAttribs() {
+        LOGV("SurfaceMediaSourceGLTest getConfigAttribs");
+    static EGLint sDefaultConfigAttribs[] = {
+        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+        EGL_RED_SIZE, 8,
+        EGL_GREEN_SIZE, 8,
+        EGL_BLUE_SIZE, 8,
+        EGL_RECORDABLE_ANDROID, EGL_TRUE,
+        EGL_NONE };
+
+    return sDefaultConfigAttribs;
+}
+
+// One pass of dequeuing and queuing a GLBuffer
+void SurfaceMediaSourceGLTest::oneBufferPassGL(int num) {
+    int d = num % 50;
+    float f = 0.2f; // 0.1f * d;
+
+    glClearColor(0, 0.3, 0, 0.6);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glEnable(GL_SCISSOR_TEST);
+    glScissor(4 + d, 4 + d, 4, 4);
+    glClearColor(1.0 - f, f, f, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glScissor(24 + d, 48 + d, 4, 4);
+    glClearColor(f, 1.0 - f, f, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glScissor(37 + d, 17 + d, 4, 4);
+    glClearColor(f, f, 1.0 - f, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    // The following call dequeues and queues the buffer
+    eglSwapBuffers(mEglDisplay, mSmsEglSurface);
+    glDisable(GL_SCISSOR_TEST);
+}
+
+// Set up the MediaRecorder which runs in the same process as mediaserver
+sp<MediaRecorder> SurfaceMediaSourceGLTest::setUpMediaRecorder(int fd, int videoSource,
+        int outputFormat, int videoEncoder, int width, int height, int fps) {
+    sp<MediaRecorder> mr = new MediaRecorder();
+    mr->setVideoSource(videoSource);
+    mr->setOutputFormat(outputFormat);
+    mr->setVideoEncoder(videoEncoder);
+    mr->setOutputFile(fd, 0, 0);
+    mr->setVideoSize(width, height);
+    mr->setVideoFrameRate(fps);
+    mr->prepare();
+    LOGV("Starting MediaRecorder...");
+    CHECK_EQ(OK, mr->start());
+    return mr;
+}
+
+// query the mediarecorder for a surfacemeidasource and create an egl surface with that
+void SurfaceMediaSourceGLTest::setUpEGLSurfaceFromMediaRecorder(sp<MediaRecorder>& mr) {
+    sp<ISurfaceTexture> iST = mr->querySurfaceMediaSourceFromMediaServer();
+    mSTC = new SurfaceTextureClient(iST);
+    mANW = mSTC;
+
+    EGLint numConfigs = 0;
+    EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mSMSGlConfig,
+            1, &numConfigs));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    LOGV("Native Window = %p, mSTC = %p", mANW.get(), mSTC.get());
+
+    mSmsEglSurface = eglCreateWindowSurface(mEglDisplay, mSMSGlConfig,
+                                mANW.get(), NULL);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_NE(EGL_NO_SURFACE, mSmsEglSurface) ;
+
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mSmsEglSurface, mSmsEglSurface,
+            mEglContext));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Methods in SurfaceMediaSourceTest
+/////////////////////////////////////////////////////////////////////
+
+// One pass of dequeuing and queuing the buffer. Fill it in with
+// cpu YV12 buffer
 void SurfaceMediaSourceTest::oneBufferPass(int width, int height ) {
-    LOGV("One Buffer Pass");
     ANativeWindowBuffer* anb;
     ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
     ASSERT_TRUE(anb != NULL);
@@ -99,42 +529,16 @@
     ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
 }
 
-sp<MPEG4Writer> SurfaceMediaSourceTest::setUpWriter(OMXClient &client ) {
-    // Writing to a file
-    const char *fileName = "/sdcard/outputSurfEnc.mp4";
-    sp<MetaData> enc_meta = new MetaData;
-    enc_meta->setInt32(kKeyBitRate, 300000);
-    enc_meta->setInt32(kKeyFrameRate, 30);
+// Dequeuing and queuing the buffer without really filling it in.
+void SurfaceMediaSourceTest::oneBufferPassNoFill(int width, int height ) {
+    ANativeWindowBuffer* anb;
+    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    ASSERT_TRUE(anb != NULL);
 
-    enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
-
-    sp<MetaData> meta = mSMS->getFormat();
-
-    int32_t width, height, stride, sliceHeight, colorFormat;
-    CHECK(meta->findInt32(kKeyWidth, &width));
-    CHECK(meta->findInt32(kKeyHeight, &height));
-    CHECK(meta->findInt32(kKeyStride, &stride));
-    CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
-    CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
-
-    enc_meta->setInt32(kKeyWidth, width);
-    enc_meta->setInt32(kKeyHeight, height);
-    enc_meta->setInt32(kKeyIFramesInterval, 1);
-    enc_meta->setInt32(kKeyStride, stride);
-    enc_meta->setInt32(kKeySliceHeight, sliceHeight);
-    // TODO: overwriting the colorformat since the format set by GRAlloc
-    // could be wrong or not be read by OMX
-    enc_meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
-
-
-    sp<MediaSource> encoder =
-        OMXCodec::Create(
-                client.interface(), enc_meta, true /* createEncoder */, mSMS);
-
-    sp<MPEG4Writer> writer = new MPEG4Writer(fileName);
-    writer->addSource(encoder);
-
-    return writer;
+    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+    // ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
+    // We do not fill the buffer in. Just queue it back.
+    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
 }
 
 // Fill a YV12 buffer with a multi-colored checkerboard pattern
@@ -216,46 +620,53 @@
             return OK;
         }
 };
-
 ///////////////////////////////////////////////////////////////////
 //           TESTS
+// SurfaceMediaSourceTest class contains tests that fill the buffers
+// using the cpu calls
+// SurfaceMediaSourceGLTest class contains tests that fill the buffers
+// using the GL calls.
+// TODO: None of the tests actually verify the encoded images.. so at this point,
+// these are mostly functionality tests + visual inspection
+//////////////////////////////////////////////////////////////////////
+
 // Just pass one buffer from the native_window to the SurfaceMediaSource
-TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotOneBufferPass) {
+// Dummy Encoder
+static int testId = 1;
+TEST_F(SurfaceMediaSourceTest, DISABLED_DummyEncodingFromCpuFilledYV12BufferNpotOneBufferPass) {
+    LOGV("Test # %d", testId++);
     LOGV("Testing OneBufferPass ******************************");
 
-    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
-            0, 0, HAL_PIXEL_FORMAT_YV12));
-    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
-            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
-
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+            HAL_PIXEL_FORMAT_YV12));
     oneBufferPass(mYuvTexWidth, mYuvTexHeight);
 }
 
 // Pass the buffer with the wrong height and weight and should not be accepted
-TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotWrongSizeBufferPass) {
+// Dummy Encoder
+TEST_F(SurfaceMediaSourceTest, DISABLED_DummyEncodingFromCpuFilledYV12BufferNpotWrongSizeBufferPass) {
+    LOGV("Test # %d", testId++);
     LOGV("Testing Wrong size BufferPass ******************************");
 
     // setting the client side buffer size different than the server size
-    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
-             10, 10, HAL_PIXEL_FORMAT_YV12));
-    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
-            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+             10, 10));
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+            HAL_PIXEL_FORMAT_YV12));
 
     ANativeWindowBuffer* anb;
 
-    // make sure we get an error back when dequeuing!
+    // Note: make sure we get an ERROR back when dequeuing!
     ASSERT_NE(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
 }
 
-
 // pass multiple buffers from the native_window the SurfaceMediaSource
-// A dummy writer is used to simulate actual MPEG4Writer
-TEST_F(SurfaceMediaSourceTest,  EncodingFromCpuFilledYV12BufferNpotMultiBufferPass) {
+// Dummy Encoder
+TEST_F(SurfaceMediaSourceTest,  DISABLED_DummyEncodingFromCpuFilledYV12BufferNpotMultiBufferPass) {
+    LOGV("Test # %d", testId++);
     LOGV("Testing MultiBufferPass, Dummy Recorder *********************");
-    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
-            0, 0, HAL_PIXEL_FORMAT_YV12));
-    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
-            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+            HAL_PIXEL_FORMAT_YV12));
 
     SimpleDummyRecorder writer(mSMS);
     writer.start();
@@ -272,14 +683,13 @@
 }
 
 // Delayed pass of multiple buffers from the native_window the SurfaceMediaSource
-// A dummy writer is used to simulate actual MPEG4Writer
-TEST_F(SurfaceMediaSourceTest,  EncodingFromCpuFilledYV12BufferNpotMultiBufferPassLag) {
+// Dummy Encoder
+TEST_F(SurfaceMediaSourceTest,  DISABLED_DummyLagEncodingFromCpuFilledYV12BufferNpotMultiBufferPass) {
+    LOGV("Test # %d", testId++);
     LOGV("Testing MultiBufferPass, Dummy Recorder Lagging **************");
 
-    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
-            0, 0, HAL_PIXEL_FORMAT_YV12));
-    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
-            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+            HAL_PIXEL_FORMAT_YV12));
 
     SimpleDummyRecorder writer(mSMS);
     writer.start();
@@ -299,12 +709,11 @@
 
 // pass multiple buffers from the native_window the SurfaceMediaSource
 // A dummy writer (MULTITHREADED) is used to simulate actual MPEG4Writer
-TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPassThreaded) {
+TEST_F(SurfaceMediaSourceTest, DISABLED_DummyThreadedEncodingFromCpuFilledYV12BufferNpotMultiBufferPass) {
+    LOGV("Test # %d", testId++);
     LOGV("Testing MultiBufferPass, Dummy Recorder Multi-Threaded **********");
-    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
-            0, 0, HAL_PIXEL_FORMAT_YV12));
-    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
-            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+            HAL_PIXEL_FORMAT_YV12));
 
     DummyRecorder writer(mSMS);
     writer.start();
@@ -318,32 +727,210 @@
     writer.stop();
 }
 
-// Test to examine the actual encoding. Temporarily disabled till the
-// colorformat and encoding from GRAlloc data is resolved
-TEST_F(SurfaceMediaSourceTest, DISABLED_EncodingFromCpuFilledYV12BufferNpotWrite) {
-    LOGV("Testing the whole pipeline with actual Recorder");
-    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
-            0, 0, HAL_PIXEL_FORMAT_YV12));
-    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
-            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
-    OMXClient client;
-    CHECK_EQ(OK, client.connect());
+// Test to examine actual encoding using mediarecorder
+// We use the mediaserver to create a mediarecorder and send
+// it back to us. So SurfaceMediaSource lives in the same process
+// as the mediaserver.
+// Very close to the actual camera, except that the
+// buffers are filled and queueud by the CPU instead of GL.
+TEST_F(SurfaceMediaSourceTest, DISABLED_EncodingFromCpuYV12BufferNpotWriteMediaServer) {
+    LOGV("Test # %d", testId++);
+    LOGV("************** Testing the whole pipeline with actual MediaRecorder ***********");
+    LOGV("************** SurfaceMediaSource is same process as mediaserver    ***********");
 
-    sp<MPEG4Writer> writer = setUpWriter(client);
-    int64_t start = systemTime();
-    CHECK_EQ(OK, writer->start());
+    const char *fileName = "/sdcard/outputSurfEncMSource.mp4";
+    int fd = open(fileName, O_RDWR | O_CREAT, 0744);
+    if (fd < 0) {
+        LOGE("ERROR: Could not open the the file %s, fd = %d !!", fileName, fd);
+    }
+    CHECK(fd >= 0);
+
+    sp<MediaRecorder> mr = SurfaceMediaSourceGLTest::setUpMediaRecorder(fd,
+            VIDEO_SOURCE_GRALLOC_BUFFER,
+            OUTPUT_FORMAT_MPEG_4, VIDEO_ENCODER_H264, mYuvTexWidth,
+            mYuvTexHeight, 30);
+    // get the reference to the surfacemediasource living in
+    // mediaserver that is created by stagefrightrecorder
+    sp<ISurfaceTexture> iST = mr->querySurfaceMediaSourceFromMediaServer();
+    mSTC = new SurfaceTextureClient(iST);
+    mANW = mSTC;
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+                                                HAL_PIXEL_FORMAT_YV12));
 
     int32_t nFramesCount = 0;
     while (nFramesCount <= 300) {
-        oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+        oneBufferPassNoFill(mYuvTexWidth, mYuvTexHeight);
         nFramesCount++;
+        LOGV("framesCount = %d", nFramesCount);
     }
 
-    CHECK_EQ(OK, writer->stop());
-    writer.clear();
-    int64_t end = systemTime();
-    client.disconnect();
+    ASSERT_EQ(NO_ERROR, native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU));
+    LOGV("Stopping MediaRecorder...");
+    CHECK_EQ(OK, mr->stop());
+    mr.clear();
+    close(fd);
 }
 
+//////////////////////////////////////////////////////////////////////
+// GL tests
+/////////////////////////////////////////////////////////////////////
 
+// Test to examine whether we can choose the Recordable Android GLConfig
+// DummyRecorder used- no real encoding here
+TEST_F(SurfaceMediaSourceGLTest, ChooseAndroidRecordableEGLConfigDummyWrite) {
+    LOGV("Test # %d", testId++);
+    LOGV("Test to verify creating a surface w/ right config *********");
+
+    mSMS = new SurfaceMediaSource(mYuvTexWidth, mYuvTexHeight);
+    mSTC = new SurfaceTextureClient(mSMS);
+    mANW = mSTC;
+
+    DummyRecorder writer(mSMS);
+    writer.start();
+
+    EGLint numConfigs = 0;
+    EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mSMSGlConfig,
+            1, &numConfigs));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    mSmsEglSurface = eglCreateWindowSurface(mEglDisplay, mSMSGlConfig,
+                                mANW.get(), NULL);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_NE(EGL_NO_SURFACE, mSmsEglSurface) ;
+
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mSmsEglSurface, mSmsEglSurface,
+            mEglContext));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    int32_t nFramesCount = 0;
+    while (nFramesCount <= 300) {
+        oneBufferPassGL();
+        nFramesCount++;
+        LOGV("framesCount = %d", nFramesCount);
+    }
+
+    ASSERT_EQ(NO_ERROR, native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL));
+    writer.stop();
+}
+// Test to examine whether we can render GL buffers in to the surface
+// created with the native window handle
+TEST_F(SurfaceMediaSourceGLTest, RenderingToRecordableEGLSurfaceWorks) {
+    LOGV("Test # %d", testId++);
+    LOGV("RenderingToRecordableEGLSurfaceWorks *********************");
+    // Do the producer side of things
+    glClearColor(0.6, 0.6, 0.6, 0.6);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glEnable(GL_SCISSOR_TEST);
+    glScissor(4, 4, 4, 4);
+    glClearColor(1.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glScissor(24, 48, 4, 4);
+    glClearColor(0.0, 1.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glScissor(37, 17, 4, 4);
+    glClearColor(0.0, 0.0, 1.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    EXPECT_TRUE(checkPixel( 0,  0, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(63,  0, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153));
+
+    EXPECT_TRUE(checkPixel( 4,  7, 255,   0,   0, 255));
+    EXPECT_TRUE(checkPixel(25, 51,   0, 255,   0, 255));
+    EXPECT_TRUE(checkPixel(40, 19,   0,   0, 255, 255));
+    EXPECT_TRUE(checkPixel(29, 51, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel( 5, 32, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(13,  8, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(46,  3, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(30, 33, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel( 6, 52, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(55, 33, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(16, 29, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel( 1, 30, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(41, 37, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(46, 29, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(15, 25, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
+}
+
+// Test to examine the actual encoding with GL buffers
+// Actual encoder, Actual GL Buffers Filled SurfaceMediaSource
+// The same pattern is rendered every frame
+TEST_F(SurfaceMediaSourceGLTest, EncodingFromGLRgbaSameImageEachBufNpotWrite) {
+    LOGV("Test # %d", testId++);
+    LOGV("************** Testing the whole pipeline with actual Recorder ***********");
+    LOGV("************** GL Filling the buffers ***********");
+    // Note: No need to set the colorformat for the buffers. The colorformat is
+    // in the GRAlloc buffers itself.
+
+    const char *fileName = "/sdcard/outputSurfEncMSourceGL.mp4";
+    int fd = open(fileName, O_RDWR | O_CREAT, 0744);
+    if (fd < 0) {
+        LOGE("ERROR: Could not open the the file %s, fd = %d !!", fileName, fd);
+    }
+    CHECK(fd >= 0);
+
+    sp<MediaRecorder> mr = setUpMediaRecorder(fd, VIDEO_SOURCE_GRALLOC_BUFFER,
+            OUTPUT_FORMAT_MPEG_4, VIDEO_ENCODER_H264, mYuvTexWidth, mYuvTexHeight, 30);
+
+    // get the reference to the surfacemediasource living in
+    // mediaserver that is created by stagefrightrecorder
+    setUpEGLSurfaceFromMediaRecorder(mr);
+
+    int32_t nFramesCount = 0;
+    while (nFramesCount <= 300) {
+        oneBufferPassGL();
+        nFramesCount++;
+        LOGV("framesCount = %d", nFramesCount);
+    }
+
+    ASSERT_EQ(NO_ERROR, native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL));
+    LOGV("Stopping MediaRecorder...");
+    CHECK_EQ(OK, mr->stop());
+    mr.clear();
+    close(fd);
+}
+
+// Test to examine the actual encoding from the GL Buffers
+// Actual encoder, Actual GL Buffers Filled SurfaceMediaSource
+// A different pattern is rendered every frame
+TEST_F(SurfaceMediaSourceGLTest, EncodingFromGLRgbaDiffImageEachBufNpotWrite) {
+    LOGV("Test # %d", testId++);
+    LOGV("************** Testing the whole pipeline with actual Recorder ***********");
+    LOGV("************** Diff GL Filling the buffers ***********");
+    // Note: No need to set the colorformat for the buffers. The colorformat is
+    // in the GRAlloc buffers itself.
+
+    const char *fileName = "/sdcard/outputSurfEncMSourceGLDiff.mp4";
+    int fd = open(fileName, O_RDWR | O_CREAT, 0744);
+    if (fd < 0) {
+        LOGE("ERROR: Could not open the the file %s, fd = %d !!", fileName, fd);
+    }
+    CHECK(fd >= 0);
+
+    sp<MediaRecorder> mr = setUpMediaRecorder(fd, VIDEO_SOURCE_GRALLOC_BUFFER,
+            OUTPUT_FORMAT_MPEG_4, VIDEO_ENCODER_H264, mYuvTexWidth, mYuvTexHeight, 30);
+
+    // get the reference to the surfacemediasource living in
+    // mediaserver that is created by stagefrightrecorder
+    setUpEGLSurfaceFromMediaRecorder(mr);
+
+    int32_t nFramesCount = 0;
+    while (nFramesCount <= 300) {
+        oneBufferPassGL(nFramesCount);
+        nFramesCount++;
+        LOGV("framesCount = %d", nFramesCount);
+    }
+
+    ASSERT_EQ(NO_ERROR, native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL));
+    LOGV("Stopping MediaRecorder...");
+    CHECK_EQ(OK, mr->stop());
+    mr.clear();
+    close(fd);
+}
 } // namespace android
diff --git a/opengl/java/android/opengl/GLUtils.java b/opengl/java/android/opengl/GLUtils.java
index f30a4cd4..125c56e 100644
--- a/opengl/java/android/opengl/GLUtils.java
+++ b/opengl/java/android/opengl/GLUtils.java
@@ -16,9 +16,11 @@
 
 package android.opengl;
 
-import javax.microedition.khronos.opengles.GL10;
 import android.graphics.Bitmap;
 
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGL11;
+
 /**
  *
  * Utility class to help bridging OpenGL ES and Android APIs.
@@ -222,6 +224,51 @@
         }
     }
 
+    /**
+     * Return a string for the EGL error code, or the hex representation
+     * if the error is unknown.
+     * 
+     * @param error The EGL error to convert into a String.
+     * 
+     * @return An error string corresponding to the EGL error code.
+     */
+    public static String getEGLErrorString(int error) {
+        switch (error) {
+            case EGL10.EGL_SUCCESS:
+                return "EGL_SUCCESS";
+            case EGL10.EGL_NOT_INITIALIZED:
+                return "EGL_NOT_INITIALIZED";
+            case EGL10.EGL_BAD_ACCESS:
+                return "EGL_BAD_ACCESS";
+            case EGL10.EGL_BAD_ALLOC:
+                return "EGL_BAD_ALLOC";
+            case EGL10.EGL_BAD_ATTRIBUTE:
+                return "EGL_BAD_ATTRIBUTE";
+            case EGL10.EGL_BAD_CONFIG:
+                return "EGL_BAD_CONFIG";
+            case EGL10.EGL_BAD_CONTEXT:
+                return "EGL_BAD_CONTEXT";
+            case EGL10.EGL_BAD_CURRENT_SURFACE:
+                return "EGL_BAD_CURRENT_SURFACE";
+            case EGL10.EGL_BAD_DISPLAY:
+                return "EGL_BAD_DISPLAY";
+            case EGL10.EGL_BAD_MATCH:
+                return "EGL_BAD_MATCH";
+            case EGL10.EGL_BAD_NATIVE_PIXMAP:
+                return "EGL_BAD_NATIVE_PIXMAP";
+            case EGL10.EGL_BAD_NATIVE_WINDOW:
+                return "EGL_BAD_NATIVE_WINDOW";
+            case EGL10.EGL_BAD_PARAMETER:
+                return "EGL_BAD_PARAMETER";
+            case EGL10.EGL_BAD_SURFACE:
+                return "EGL_BAD_SURFACE";
+            case EGL11.EGL_CONTEXT_LOST:
+                return "EGL_CONTEXT_LOST";
+            default:
+                return "0x" + Integer.toHexString(error);
+        }
+    }
+
     native private static void nativeClassInit();
 
     native private static int native_getInternalFormat(Bitmap bitmap);
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 10cea22..7e85230 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -454,13 +454,6 @@
     EGLBoolean result = s->cnx->egl.eglDestroySurface(
             dp->disp[s->impl].dpy, s->surface);
     if (result == EGL_TRUE) {
-        ANativeWindow* const window = s->win.get();
-        if (window != NULL) {
-            native_window_set_buffers_format(window, 0);
-            if (native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL)) {
-                LOGE("EGLNativeWindowType %p disconnected failed", window);
-            }
-        }
         _s.terminate();
     }
     return result;
@@ -682,6 +675,9 @@
             setGLHooksThreadSpecific(&gHooksNoContext);
             egl_tls_t::setContext(EGL_NO_CONTEXT);
         }
+    } else {
+        // this will LOGE the error
+        result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
     }
     return result;
 }
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 3459a8a..d2b7378 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -125,7 +125,15 @@
 
 class egl_surface_t: public egl_object_t {
 protected:
-    ~egl_surface_t() {}
+    ~egl_surface_t() {
+        ANativeWindow* const window = win.get();
+        if (window != NULL) {
+            native_window_set_buffers_format(window, 0);
+            if (native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL)) {
+                LOGE("EGLNativeWindowType %p disconnected failed", window);
+            }
+        }
+    }
 public:
     typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
 
@@ -232,4 +240,3 @@
 // ----------------------------------------------------------------------------
 
 #endif // ANDROID_EGL_OBJECT_H
-
diff --git a/packages/SystemUI/res/anim/recent_appear.xml b/packages/SystemUI/res/anim/recent_appear.xml
index 4400d9d..20fe052 100644
--- a/packages/SystemUI/res/anim/recent_appear.xml
+++ b/packages/SystemUI/res/anim/recent_appear.xml
@@ -16,5 +16,5 @@
 
 <alpha xmlns:android="http://schemas.android.com/apk/res/android"
     android:fromAlpha="0.0" android:toAlpha="1.0"
-    android:duration="@android:integer/config_shortAnimTime"
+    android:duration="@android:integer/config_mediumAnimTime"
     />
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
index 5736d46..d7a591c 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png
deleted file mode 100644
index ddbd3d7..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png
new file mode 100644
index 0000000..64b8f4f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_bg_tile.png b/packages/SystemUI/res/drawable-hdpi/status_bar_bg_tile.png
index 37cad22..aee197c 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_bg_tile.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_bg_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png
deleted file mode 100644
index 364cf75..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png
new file mode 100644
index 0000000..1d44294
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_bg_tile.png b/packages/SystemUI/res/drawable-mdpi/status_bar_bg_tile.png
index 83d106d..6579ff9 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_bg_tile.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_bg_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_default.png
index 1a9d88c..47f0745c 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_default.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_pressed.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_pressed.png
index a6d7507..490504e 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_pressed.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_default.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_default.png
index 1e1324a..348afb5 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_default.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_pressed.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_pressed.png
index e4e13c5..2f20d67 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_pressed.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_alarm.png
new file mode 100644
index 0000000..6b3ab3e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_alarm.png
new file mode 100644
index 0000000..dd6651e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_ime_default.png
new file mode 100644
index 0000000..d670177
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_ime_pressed.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_ime_pressed.png
new file mode 100644
index 0000000..c9f0302
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_ime_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_zoom_default.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_zoom_default.png
new file mode 100644
index 0000000..dd8c498
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_zoom_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_zoom_pressed.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_zoom_pressed.png
new file mode 100644
index 0000000..dc42157
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_zoom_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_alarm.png
new file mode 100644
index 0000000..b42b713
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
index 4cb305d..16c5ca1 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_pressed.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_pressed.png
new file mode 100644
index 0000000..3e59c8d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
index 85df060..c13abf0 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png
index 97a07fa..3c4ce69 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
index 31d35c8..16ea9f6a 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
index 334213b..1f76128 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
index 7c21c48..b7f6c11 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
index 1fe6b91..a5d3c6a 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
index f0cc341d..ad26f6c 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
index 7e8504c..39fc827 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_notify_more.png b/packages/SystemUI/res/drawable-xhdpi/stat_notify_more.png
new file mode 100644
index 0000000..16bf510
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_notify_more.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png
new file mode 100644
index 0000000..192d4af
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/status_bar_bg_tile.png b/packages/SystemUI/res/drawable-xhdpi/status_bar_bg_tile.png
index 9e21348..d01b117 100644
--- a/packages/SystemUI/res/drawable-xhdpi/status_bar_bg_tile.png
+++ b/packages/SystemUI/res/drawable-xhdpi/status_bar_bg_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/values-xhdpi/dimens.xml b/packages/SystemUI/res/values-xhdpi/dimens.xml
new file mode 100644
index 0000000..aa75c20
--- /dev/null
+++ b/packages/SystemUI/res/values-xhdpi/dimens.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<resources>
+    <!-- thickness (height) of each notification row, including any separators or padding -->
+    <!-- note: this is the same value as in values/dimens.xml; the value is overridden in
+         values-hdpi/dimens.xml and so we need to re-assert the general value here -->
+    <dimen name="notification_height">65dp</dimen>
+
+    <!-- thickness (height) of dividers between each notification row -->
+    <!-- same as in values/dimens.xml; see note at notification_height -->
+    <dimen name="notification_divider_height">1dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 6db5fc4..f633825c 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -63,4 +63,28 @@
 
     <!-- thickness (height) of dividers between each notification row -->
     <dimen name="notification_divider_height">1dp</dimen>
+
+    <!-- Notification drawer tuning parameters (phone UI) -->
+    <!-- Initial velocity of the shade when expanding on its own -->
+    <dimen name="self_expand_velocity">2000dp</dimen>
+    <!-- Initial velocity of the shade when collapsing on its own -->
+    <dimen name="self_collapse_velocity">2000dp</dimen>
+    <!-- Minimum final velocity of gestures interpreted as expand requests -->
+    <dimen name="fling_expand_min_velocity">200dp</dimen>
+    <!-- Minimum final velocity of gestures interpreted as collapse requests -->
+    <dimen name="fling_collapse_min_velocity">200dp</dimen>
+    <!-- Cap on contribution of x dimension of gesture to overall velocity -->
+    <dimen name="fling_gesture_max_x_velocity">200dp</dimen>
+
+    <!-- Minimum fraction of the display a gesture must travel, at any velocity, to qualify as a
+         collapse request -->
+    <item type="dimen" name="collapse_min_display_fraction">10%</item>
+    <!-- Minimum fraction of the display a gesture must travel to qualify as an expand request -->
+    <item type="dimen" name="expand_min_display_fraction">50%</item>
+
+    <!-- Initial acceleration of an expand animation after fling -->
+    <dimen name="expand_accel">2000dp</dimen>
+    <!-- Initial acceleration of an collapse animation after fling -->
+    <dimen name="collapse_accel">2000dp</dimen>
+
 </resources>
diff --git a/packages/SystemUI/res/values/donottranslate.xml b/packages/SystemUI/res/values/donottranslate.xml
index c25a5b7..93ec481 100644
--- a/packages/SystemUI/res/values/donottranslate.xml
+++ b/packages/SystemUI/res/values/donottranslate.xml
@@ -17,8 +17,9 @@
  */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default,
-         but this may be overridden on a per-locale basis if necessary. -->
-    <string name="status_bar_date_formatter">%1$s\n%2$s</string>
+    <!-- For formatting day of week and date in DateView.  %1$s is DOW, %2$s is date.
+         In Roman locales we now show only the date, but DOW is available for other locales if
+         necessary. -->
+    <string name="status_bar_date_formatter">%2$s</string>
 
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index e1231a5..492f3c2 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -16,41 +16,65 @@
 
 package com.android.systemui;
 
-import java.io.IOException;
-
+import android.app.ActivityManager;
 import android.app.WallpaperManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.Region.Op;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
+import android.opengl.GLUtils;
+import android.renderscript.Matrix4f;
 import android.service.wallpaper.WallpaperService;
 import android.util.Log;
-import android.util.Slog;
+import android.view.Display;
 import android.view.MotionEvent;
 import android.view.SurfaceHolder;
-import android.content.Context;
-import android.content.IntentFilter;
-import android.content.Intent;
-import android.content.BroadcastReceiver;
+import android.view.WindowManager;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.egl.EGLSurface;
+import javax.microedition.khronos.opengles.GL;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import static android.opengl.GLES20.*;
+import static javax.microedition.khronos.egl.EGL10.*;
 
 /**
  * Default built-in wallpaper that simply shows a static image.
  */
+@SuppressWarnings({"UnusedDeclaration"})
 public class ImageWallpaper extends WallpaperService {
     private static final String TAG = "ImageWallpaper";
+    private static final String GL_LOG_TAG = "ImageWallpaperGL";
     private static final boolean DEBUG = false;
 
     static final boolean FIXED_SIZED_SURFACE = true;
+    static final boolean USE_OPENGL = true;
 
     WallpaperManager mWallpaperManager;
-    private Handler mHandler;
+
+    boolean mIsHwAccelerated;
 
     @Override
     public void onCreate() {
         super.onCreate();
         mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE);
-        mHandler = new Handler();
+
+        //noinspection PointlessBooleanExpression,ConstantConditions
+        if (FIXED_SIZED_SURFACE && USE_OPENGL) {
+            WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+            Display display = windowManager.getDefaultDisplay();
+            mIsHwAccelerated = ActivityManager.isHighEndGfx(display);
+        }
     }
 
     public Engine onCreateEngine() {
@@ -58,9 +82,16 @@
     }
 
     class DrawableEngine extends Engine {
-        private final Object mLock = new Object();
+        static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+        static final int EGL_OPENGL_ES2_BIT = 4;
+
+        private final Object mLock = new Object[0];
+
+        // TODO: Not currently used, keeping around until we know we don't need it
+        @SuppressWarnings({"UnusedDeclaration"})
         private WallpaperObserver mReceiver;
-        Drawable mBackground;
+
+        Bitmap mBackground;
         int mBackgroundWidth = -1, mBackgroundHeight = -1;
         float mXOffset;
         float mYOffset;
@@ -71,6 +102,35 @@
         int mLastXTranslation;
         int mLastYTranslation;
 
+        private EGL10 mEgl;
+        private EGLDisplay mEglDisplay;
+        private EGLConfig mEglConfig;
+        private EGLContext mEglContext;
+        private EGLSurface mEglSurface;
+        private GL mGL;
+
+        private static final String sSimpleVS =
+                "attribute vec4 position;\n" +
+                "attribute vec2 texCoords;\n" +
+                "varying vec2 outTexCoords;\n" +
+                "uniform mat4 projection;\n" +
+                "\nvoid main(void) {\n" +
+                "    outTexCoords = texCoords;\n" +
+                "    gl_Position = projection * position;\n" +
+                "}\n\n";
+        private static final String sSimpleFS =
+                "precision mediump float;\n\n" +
+                "varying vec2 outTexCoords;\n" +
+                "uniform sampler2D texture;\n" +
+                "\nvoid main(void) {\n" +
+                "    gl_FragColor = texture2D(texture, outTexCoords);\n" +
+                "}\n\n";
+    
+        private static final int FLOAT_SIZE_BYTES = 4;
+        private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
+        private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
+        private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
+
         class WallpaperObserver extends BroadcastReceiver {
             public void onReceive(Context context, Intent intent) {
                 if (DEBUG) {
@@ -94,7 +154,7 @@
 
             super.onCreate(surfaceHolder);
             
-            // Don't need this currently because the wallpaper service
+            // TODO: Don't need this currently because the wallpaper service
             // will restart the image wallpaper whenever the image changes.
             //IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
             //mReceiver = new WallpaperObserver();
@@ -221,8 +281,7 @@
             int yPixels = availh < 0 ? (int)(availh * mYOffset + .5f) : (availh / 2);
 
             mOffsetsChanged = false;
-            if (!mRedrawNeeded
-                    && xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
+            if (!mRedrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
                 if (DEBUG) {
                     Log.d(TAG, "Suppressed drawFrame since the image has not "
                             + "actually moved an integral number of pixels.");
@@ -240,27 +299,12 @@
                 updateWallpaperLocked();
             }
 
-            //Slog.i(TAG, "************** DRAWING WALLAPER ******************");
-            Canvas c = sh.lockCanvas();
-            if (c != null) {
-                try {
-                    if (DEBUG) {
-                        Log.d(TAG, "Redrawing: xPixels=" + xPixels + ", yPixels=" + yPixels);
-                    }
-
-                    c.translate(xPixels, yPixels);
-                    if (availw < 0 || availh < 0) {
-                        c.save(Canvas.CLIP_SAVE_FLAG);
-                        c.clipRect(0, 0, mBackgroundWidth, mBackgroundHeight, Op.DIFFERENCE);
-                        c.drawColor(0xff000000);
-                        c.restore();
-                    }
-                    if (mBackground != null) {
-                        mBackground.draw(c);
-                    }
-                } finally {
-                    sh.unlockCanvasAndPost(c);
+            if (mIsHwAccelerated) {
+                if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) {
+                    drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
                 }
+            } else {
+                drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
             }
 
             if (FIXED_SIZED_SURFACE) {
@@ -274,15 +318,15 @@
         }
 
         void updateWallpaperLocked() {
-            //Slog.i(TAG, "************** LOADING WALLAPER ******************");
             Throwable exception = null;
             try {
-                mBackground = mWallpaperManager.getFastDrawable();
+                mBackground = mWallpaperManager.getBitmap();
             } catch (RuntimeException e) {
                 exception = e;
             } catch (OutOfMemoryError e) {
                 exception = e;
             }
+
             if (exception != null) {
                 mBackground = null;
                 // Note that if we do fail at this, and the default wallpaper can't
@@ -296,8 +340,282 @@
                     Log.w(TAG, "Unable reset to default wallpaper!", ex);
                 }
             }
-            mBackgroundWidth = mBackground != null ? mBackground.getIntrinsicWidth() : 0;
-            mBackgroundHeight = mBackground != null ? mBackground.getIntrinsicHeight() : 0;
+
+            mBackgroundWidth = mBackground != null ? mBackground.getWidth() : 0;
+            mBackgroundHeight = mBackground != null ? mBackground.getHeight() : 0;
+        }
+
+        private void drawWallpaperWithCanvas(SurfaceHolder sh, int w, int h, int x, int y) {
+            Canvas c = sh.lockCanvas();
+            if (c != null) {
+                try {
+                    if (DEBUG) {
+                        Log.d(TAG, "Redrawing: x=" + x + ", y=" + y);
+                    }
+
+                    c.translate(x, y);
+                    if (w < 0 || h < 0) {
+                        c.save(Canvas.CLIP_SAVE_FLAG);
+                        c.clipRect(0, 0, mBackgroundWidth, mBackgroundHeight, Op.DIFFERENCE);
+                        c.drawColor(0xff000000);
+                        c.restore();
+                    }
+                    if (mBackground != null) {
+                        c.drawBitmap(mBackground, 0, 0, null);
+                    }
+                } finally {
+                    sh.unlockCanvasAndPost(c);
+                }
+            }
+        }
+
+        private boolean drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left, int top) {
+            if (!initGL(sh)) return false;
+
+            final float right = left + mBackgroundWidth;
+            final float bottom = top + mBackgroundHeight;
+
+            final Rect frame = sh.getSurfaceFrame();
+
+            final Matrix4f ortho = new Matrix4f();
+            ortho.loadOrtho(0.0f, frame.width(), frame.height(), 0.0f, -1.0f, 1.0f);
+
+            final FloatBuffer triangleVertices = createMesh(left, top, right, bottom);
+
+            final int texture = loadTexture(mBackground);
+            final int program = buildProgram(sSimpleVS, sSimpleFS);
+    
+            final int attribPosition = glGetAttribLocation(program, "position");
+            final int attribTexCoords = glGetAttribLocation(program, "texCoords");
+            final int uniformTexture = glGetUniformLocation(program, "texture");
+            final int uniformProjection = glGetUniformLocation(program, "projection");
+
+            checkGlError();
+
+            glViewport(0, 0, frame.width(), frame.height());
+            glBindTexture(GL_TEXTURE_2D, texture);
+
+            glUseProgram(program);
+            glEnableVertexAttribArray(attribPosition);
+            glEnableVertexAttribArray(attribTexCoords);
+            glUniform1i(uniformTexture, 0);
+            glUniformMatrix4fv(uniformProjection, 1, false, ortho.getArray(), 0);
+
+            checkGlError();
+
+            if (w < 0 || h < 0) {
+                glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+                glClear(GL_COLOR_BUFFER_BIT);
+            }
+    
+            // drawQuad
+            triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
+            glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false,
+                    TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
+
+            triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
+            glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false,
+                    TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
+
+            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    
+            if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
+                throw new RuntimeException("Cannot swap buffers");
+            }
+            checkEglError();
+    
+            finishGL();
+
+            return true;
+        }
+
+        private FloatBuffer createMesh(int left, int top, float right, float bottom) {
+            final float[] verticesData = {
+                    // X, Y, Z, U, V
+                     left,  bottom, 0.0f, 0.0f, 1.0f,
+                     right, bottom, 0.0f, 1.0f, 1.0f,
+                     left,  top,    0.0f, 0.0f, 0.0f,
+                     right, top,    0.0f, 1.0f, 0.0f,
+            };
+
+            final int bytes = verticesData.length * FLOAT_SIZE_BYTES;
+            final FloatBuffer triangleVertices = ByteBuffer.allocateDirect(bytes).order(
+                    ByteOrder.nativeOrder()).asFloatBuffer();
+            triangleVertices.put(verticesData).position(0);
+            return triangleVertices;
+        }
+
+        private int loadTexture(Bitmap bitmap) {
+            int[] textures = new int[1];
+    
+            glActiveTexture(GL_TEXTURE0);
+            glGenTextures(1, textures, 0);
+            checkGlError();
+    
+            int texture = textures[0];
+            glBindTexture(GL_TEXTURE_2D, texture);
+            checkGlError();
+            
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    
+            GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0);
+            checkGlError();
+
+            bitmap.recycle();
+    
+            return texture;
+        }
+        
+        private int buildProgram(String vertex, String fragment) {
+            int vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
+            if (vertexShader == 0) return 0;
+    
+            int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
+            if (fragmentShader == 0) return 0;
+    
+            int program = glCreateProgram();
+            glAttachShader(program, vertexShader);
+            checkGlError();
+    
+            glAttachShader(program, fragmentShader);
+            checkGlError();
+    
+            glLinkProgram(program);
+            checkGlError();
+    
+            int[] status = new int[1];
+            glGetProgramiv(program, GL_LINK_STATUS, status, 0);
+            if (status[0] != GL_TRUE) {
+                String error = glGetProgramInfoLog(program);
+                Log.d(GL_LOG_TAG, "Error while linking program:\n" + error);
+                glDeleteShader(vertexShader);
+                glDeleteShader(fragmentShader);
+                glDeleteProgram(program);
+                return 0;
+            }
+    
+            return program;
+        }
+        
+        private int buildShader(String source, int type) {
+            int shader = glCreateShader(type);
+    
+            glShaderSource(shader, source);
+            checkGlError();
+    
+            glCompileShader(shader);
+            checkGlError();
+    
+            int[] status = new int[1];
+            glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0);
+            if (status[0] != GL_TRUE) {
+                String error = glGetShaderInfoLog(shader);
+                Log.d(GL_LOG_TAG, "Error while compiling shader:\n" + error);
+                glDeleteShader(shader);
+                return 0;
+            }
+            
+            return shader;
+        }
+    
+        private void checkEglError() {
+            int error = mEgl.eglGetError();
+            if (error != EGL_SUCCESS) {
+                Log.w(GL_LOG_TAG, "EGL error = " + GLUtils.getEGLErrorString(error));
+            }
+        }
+    
+        private void checkGlError() {
+            int error = glGetError();
+            if (error != GL_NO_ERROR) {
+                Log.w(GL_LOG_TAG, "GL error = 0x" + Integer.toHexString(error), new Throwable());
+            }
+        }
+    
+        private void finishGL() {
+            mEgl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+            mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
+            mEgl.eglDestroyContext(mEglDisplay, mEglContext);
+        }
+        
+        private boolean initGL(SurfaceHolder surfaceHolder) {
+            mEgl = (EGL10) EGLContext.getEGL();
+    
+            mEglDisplay = mEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+            if (mEglDisplay == EGL_NO_DISPLAY) {
+                throw new RuntimeException("eglGetDisplay failed " +
+                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
+            }
+            
+            int[] version = new int[2];
+            if (!mEgl.eglInitialize(mEglDisplay, version)) {
+                throw new RuntimeException("eglInitialize failed " +
+                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
+            }
+    
+            mEglConfig = chooseEglConfig();
+            if (mEglConfig == null) {
+                throw new RuntimeException("eglConfig not initialized");
+            }
+            
+            mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
+    
+            mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, null);
+    
+            if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
+                int error = mEgl.eglGetError();
+                if (error == EGL_BAD_NATIVE_WINDOW) {
+                    Log.e(GL_LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
+                    return false;
+                }
+                throw new RuntimeException("createWindowSurface failed " +
+                        GLUtils.getEGLErrorString(error));
+            }
+    
+            if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+                throw new RuntimeException("eglMakeCurrent failed " +
+                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
+            }
+    
+            mGL = mEglContext.getGL();
+
+            return true;
+        }
+        
+    
+        EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
+            int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+            return egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, attrib_list);            
+        }
+    
+        private EGLConfig chooseEglConfig() {
+            int[] configsCount = new int[1];
+            EGLConfig[] configs = new EGLConfig[1];
+            int[] configSpec = getConfig();
+            if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) {
+                throw new IllegalArgumentException("eglChooseConfig failed " +
+                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
+            } else if (configsCount[0] > 0) {
+                return configs[0];
+            }
+            return null;
+        }
+
+        private int[] getConfig() {
+            return new int[] {
+                    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+                    EGL_RED_SIZE, 8,
+                    EGL_GREEN_SIZE, 8,
+                    EGL_BLUE_SIZE, 8,
+                    EGL_ALPHA_SIZE, 0,
+                    EGL_DEPTH_SIZE, 0,
+                    EGL_STENCIL_SIZE, 0,
+                    EGL_NONE
+            };
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
index 2d327c4..9749a1d 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
@@ -29,6 +29,7 @@
     // should group this into a multi-property animation
     private static final int OPEN_DURATION = 136;
     private static final int CLOSE_DURATION = 250;
+    private static final int SCRIM_DURATION = 400;
     private static final String TAG = RecentsPanelView.TAG;
     private static final boolean DEBUG = RecentsPanelView.DEBUG;
 
@@ -71,12 +72,14 @@
         posAnim.setInterpolator(appearing
                 ? new android.view.animation.DecelerateInterpolator(2.5f)
                 : new android.view.animation.AccelerateInterpolator(2.5f));
+        posAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
 
         Animator glowAnim = ObjectAnimator.ofFloat(mContentView, "alpha",
                 mContentView.getAlpha(), appearing ? 1.0f : 0.0f);
         glowAnim.setInterpolator(appearing
                 ? new android.view.animation.AccelerateInterpolator(1.0f)
                 : new android.view.animation.DecelerateInterpolator(1.0f));
+        glowAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
 
         mContentAnim = new AnimatorSet();
         final Builder builder = mContentAnim.play(glowAnim).with(posAnim);
@@ -84,9 +87,9 @@
         if (background != null) {
             Animator bgAnim = ObjectAnimator.ofInt(background,
                 "alpha", appearing ? 0 : 255, appearing ? 255 : 0);
+            bgAnim.setDuration(appearing ? SCRIM_DURATION : CLOSE_DURATION);
             builder.with(bgAnim);
         }
-        mContentAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
         mContentAnim.addListener(this);
         if (mListener != null) {
             mContentAnim.addListener(mListener);
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 8c03ef8..9cc2c29 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -39,7 +39,6 @@
 import android.graphics.Shader.TileMode;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Handler;
@@ -497,7 +496,7 @@
         synchronized (ad) {
             ad.mLabel = label;
             ad.mIcon = icon;
-            ad.setThumbnail(thumbs.mainThumbnail);
+            ad.setThumbnail(thumbs != null ? thumbs.mainThumbnail : null);
         }
     }
 
@@ -591,7 +590,7 @@
                             ActivityDescription ad = descriptions.get(i);
                             loadActivityDescription(ad, i);
                             long now = SystemClock.uptimeMillis();
-                            nextTime += 200;
+                            nextTime += 150;
                             if (nextTime > now) {
                                 try {
                                     Thread.sleep(nextTime-now);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
index 61da1f5..37c77f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar;
 
+import android.app.ActivityManager;
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
@@ -26,6 +27,7 @@
 import android.os.ServiceManager;
 import android.util.Slog;
 import android.util.Log;
+import android.view.Display;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
@@ -117,6 +119,15 @@
                     | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                     | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.RGBX_8888);
+        
+        // the status bar should be in an overlay if possible
+        final Display defaultDisplay 
+            = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
+                .getDefaultDisplay();
+        if (ActivityManager.isHighEndGfx(defaultDisplay)) {
+            lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+        }
+
         lp.gravity = getStatusBarGravity();
         lp.setTitle("StatusBar");
         lp.packageName = mContext.getPackageName();
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 fe9eceb..6e6567b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -112,6 +112,18 @@
     // will likely move to a resource or other tunable param at some point
     private static final int INTRUDER_ALERT_DECAY_MS = 10000;
 
+    // fling gesture tuning parameters, scaled to display density
+    private float mSelfExpandVelocityPx; // classic value: 2000px/s
+    private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
+    private float mFlingExpandMinVelocityPx; // classic value: 200px/s
+    private float mFlingCollapseMinVelocityPx; // classic value: 200px/s
+    private float mCollapseMinDisplayFraction; // classic value: 0.08 (25px/min(320px,480px) on G1)
+    private float mExpandMinDisplayFraction; // classic value: 0.5 (drag open halfway to expand)
+    private float mFlingGestureMaxXVelocityPx; // classic value: 150px/s
+
+    private float mExpandAccelPx; // classic value: 2000px/s/s
+    private float mCollapseAccelPx; // classic value: 2000px/s/s (will be negated to collapse "up")
+
     PhoneStatusBarPolicy mIconPolicy;
 
     // These are no longer handled by the policy, because we need custom strategies for them
@@ -475,6 +487,10 @@
                     | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                     | WindowManager.LayoutParams.FLAG_SLIPPERY,
                 PixelFormat.OPAQUE);
+        // this will allow the navbar to run in an overlay on devices that support this
+        if (ActivityManager.isHighEndGfx(mDisplay)) {
+            lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+        }
 
         lp.setTitle("NavigationBar");
         switch (rotation) {
@@ -1175,7 +1191,7 @@
         }
 
         prepareTracking(0, true);
-        performFling(0, 2000.0f, true);
+        performFling(0, mSelfExpandVelocityPx, true);
     }
 
     public void animateCollapse() {
@@ -1211,7 +1227,7 @@
         // and doesn't try to re-open the windowshade.
         mExpanded = true;
         prepareTracking(y, false);
-        performFling(y, -2000.0f, true);
+        performFling(y, -mSelfCollapseVelocityPx, true);
     }
 
     void performExpand() {
@@ -1327,8 +1343,8 @@
         mTracking = true;
         mVelocityTracker = VelocityTracker.obtain();
         if (opening) {
-            mAnimAccel = 2000.0f;
-            mAnimVel = 200;
+            mAnimAccel = mExpandAccelPx;
+            mAnimVel = mFlingExpandMinVelocityPx;
             mAnimY = mStatusBarView.getHeight();
             updateExpandedViewPos((int)mAnimY);
             mAnimating = true;
@@ -1366,29 +1382,31 @@
 
         if (mExpanded) {
             if (!always && (
-                    vel > 200.0f
-                    || (y > (mDisplayMetrics.heightPixels-25) && vel > -200.0f))) {
+                    vel > mFlingCollapseMinVelocityPx
+                    || (y > (mDisplayMetrics.heightPixels*(1f-mCollapseMinDisplayFraction)) &&
+                        vel > -mFlingExpandMinVelocityPx))) {
                 // We are expanded, but they didn't move sufficiently to cause
                 // us to retract.  Animate back to the expanded position.
-                mAnimAccel = 2000.0f;
+                mAnimAccel = mExpandAccelPx;
                 if (vel < 0) {
                     mAnimVel = 0;
                 }
             }
             else {
                 // We are expanded and are now going to animate away.
-                mAnimAccel = -2000.0f;
+                mAnimAccel = -mCollapseAccelPx;
                 if (vel > 0) {
                     mAnimVel = 0;
                 }
             }
         } else {
             if (always || (
-                    vel > 200.0f
-                    || (y > (mDisplayMetrics.heightPixels/2) && vel > -200.0f))) {
+                    vel > mFlingExpandMinVelocityPx
+                    || (y > (mDisplayMetrics.heightPixels*(1f-mExpandMinDisplayFraction)) &&
+                        vel > -mFlingCollapseMinVelocityPx))) {
                 // We are collapsed, and they moved enough to allow us to
                 // expand.  Animate in the notifications.
-                mAnimAccel = 2000.0f;
+                mAnimAccel = mExpandAccelPx;
                 if (vel < 0) {
                     mAnimVel = 0;
                 }
@@ -1396,7 +1414,7 @@
             else {
                 // We are collapsed, but they didn't move sufficiently to cause
                 // us to retract.  Animate back to the collapsed position.
-                mAnimAccel = -2000.0f;
+                mAnimAccel = -mCollapseAccelPx;
                 if (vel > 0) {
                     mAnimVel = 0;
                 }
@@ -1476,8 +1494,8 @@
                 if (xVel < 0) {
                     xVel = -xVel;
                 }
-                if (xVel > 150.0f) {
-                    xVel = 150.0f; // limit how much we care about the x axis
+                if (xVel > mFlingGestureMaxXVelocityPx) {
+                    xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
                 }
 
                 float vel = (float)Math.hypot(yVel, xVel);
@@ -1485,6 +1503,14 @@
                     vel = -vel;
                 }
 
+                if (CHATTY) {
+                    Slog.d(TAG, String.format("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f", 
+                        mVelocityTracker.getXVelocity(), 
+                        mVelocityTracker.getYVelocity(),
+                        xVel, yVel,
+                        vel));
+                }
+
                 performFling((int)event.getRawY(), vel, false);
             }
 
@@ -2129,6 +2155,19 @@
 
         mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
 
+        mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity);
+        mSelfCollapseVelocityPx = res.getDimension(R.dimen.self_collapse_velocity);
+        mFlingExpandMinVelocityPx = res.getDimension(R.dimen.fling_expand_min_velocity);
+        mFlingCollapseMinVelocityPx = res.getDimension(R.dimen.fling_collapse_min_velocity);
+
+        mCollapseMinDisplayFraction = res.getFraction(R.dimen.collapse_min_display_fraction, 1, 1);
+        mExpandMinDisplayFraction = res.getFraction(R.dimen.expand_min_display_fraction, 1, 1);
+
+        mExpandAccelPx = res.getDimension(R.dimen.expand_accel);
+        mCollapseAccelPx = res.getDimension(R.dimen.collapse_accel);
+
+        mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity);
+
         if (false) Slog.v(TAG, "updateResources");
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 322a8c8..ee270f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -161,7 +161,7 @@
         mService.setIconVisibility("bluetooth", mBluetoothEnabled);
 
         // Alarm clock
-        mService.setIcon("alarm_clock", R.drawable.stat_notify_alarm, 0, null);
+        mService.setIcon("alarm_clock", R.drawable.stat_sys_alarm, 0, null);
         mService.setIconVisibility("alarm_clock", false);
 
         // Sync state
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index a171514..d3f9525 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -91,7 +91,7 @@
         final Context context = getContext();
         Date now = new Date();
         CharSequence dow = DateFormat.format("EEEE", now);
-        CharSequence date = DateFormat.getMediumDateFormat(getContext()).format(now);
+        CharSequence date = DateFormat.getLongDateFormat(context).format(now);
         setText(context.getString(R.string.status_bar_date_formatter, dow, date));
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 6368d1d..840087c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -60,6 +60,7 @@
     Drawable mGlowBG;
     float mGlowAlpha = 0f, mGlowScale = 1f, mDrawingAlpha = 1f;
     boolean mSupportsLongpress = true;
+    RectF mRect = new RectF(0f,0f,0f,0f);
 
     Runnable mCheckLongPress = new Runnable() {
         public void run() {
@@ -120,8 +121,9 @@
             mGlowBG.setAlpha((int)(mGlowAlpha * 255));
             mGlowBG.draw(canvas);
             canvas.restore();
-
-            canvas.saveLayerAlpha(null, (int)(mDrawingAlpha * 255), Canvas.ALL_SAVE_FLAG);
+            mRect.right = w;
+            mRect.bottom = h;
+            canvas.saveLayerAlpha(mRect, (int)(mDrawingAlpha * 255), Canvas.ALL_SAVE_FLAG);
         }
         super.onDraw(canvas);
         if (mGlowBG != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 16db1d7..60dfdac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -225,7 +225,7 @@
     public void addSignalCluster(SignalCluster cluster) {
         mSignalClusters.add(cluster);
         cluster.setWifiIndicators(
-                mWifiEnabled,
+                mWifiConnected, // only show wifi in the cluster if connected
                 mWifiIconId,
                 mWifiActivityIconId);
         cluster.setMobileDataIndicators(
@@ -862,7 +862,7 @@
             // NB: the mLast*s will be updated later
             for (SignalCluster cluster : mSignalClusters) {
                 cluster.setWifiIndicators(
-                        mWifiEnabled,
+                        mWifiConnected, // only show wifi in the cluster if connected
                         mWifiIconId,
                         mWifiActivityIconId);
                 cluster.setMobileDataIndicators(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index dd59667..2ab667d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -879,12 +879,11 @@
             removeNotificationViews(key);
             addNotificationViews(key, notification);
         }
-        // fullScreenIntent doesn't happen on updates.  You need to clear & repost a new
-        // notification.
-        final boolean immersive = isImmersive();
-        if (false && immersive) {
-            // TODO: immersive mode
-        } else {
+
+        // Restart the ticker if it's still running
+        if (notification.notification.tickerText != null
+                && !TextUtils.equals(notification.notification.tickerText,
+                    oldEntry.notification.notification.tickerText)) {
             tick(key, notification, false);
         }
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index be129a8..dfd1b00 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -124,6 +124,7 @@
 import android.view.WindowManagerImpl;
 import android.view.WindowManagerPolicy;
 import android.view.KeyCharacterMap.FallbackAction;
+import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.media.IAudioService;
@@ -3104,7 +3105,29 @@
         mHandler.post(new Runnable() {
             @Override public void run() {
                 if (mBootMsgDialog == null) {
-                    mBootMsgDialog = new ProgressDialog(mContext);
+                    mBootMsgDialog = new ProgressDialog(mContext) {
+                        // This dialog will consume all events coming in to
+                        // it, to avoid it trying to do things too early in boot.
+                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
+                            return true;
+                        }
+                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+                            return true;
+                        }
+                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
+                            return true;
+                        }
+                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
+                            return true;
+                        }
+                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
+                            return true;
+                        }
+                        @Override public boolean dispatchPopulateAccessibilityEvent(
+                                AccessibilityEvent event) {
+                            return true;
+                        }
+                    };
                     mBootMsgDialog.setTitle(R.string.android_upgrading_title);
                     mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                     mBootMsgDialog.setIndeterminate(true);
diff --git a/preloaded-classes b/preloaded-classes
index 8136f8e..31d49ce 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -7,6 +7,9 @@
 android.accounts.Account$1
 android.accounts.AccountManager
 android.accounts.AccountManager$12
+android.accounts.AccountManager$AmsTask
+android.accounts.AccountManager$AmsTask$1
+android.accounts.AccountManager$AmsTask$Response
 android.accounts.AccountManagerFuture
 android.accounts.IAccountManager
 android.accounts.IAccountManager$Stub
@@ -15,10 +18,17 @@
 android.accounts.IAccountManagerResponse$Stub
 android.animation.Animator
 android.animation.Animator$AnimatorListener
+android.animation.AnimatorListenerAdapter
 android.animation.FloatEvaluator
+android.animation.FloatKeyframeSet
 android.animation.IntEvaluator
+android.animation.Keyframe
+android.animation.Keyframe$FloatKeyframe
+android.animation.KeyframeSet
 android.animation.LayoutTransition$TransitionListener
+android.animation.ObjectAnimator
 android.animation.PropertyValuesHolder
+android.animation.PropertyValuesHolder$FloatPropertyValuesHolder
 android.animation.TimeInterpolator
 android.animation.TypeEvaluator
 android.animation.ValueAnimator
@@ -27,10 +37,10 @@
 android.animation.ValueAnimator$3
 android.animation.ValueAnimator$4
 android.animation.ValueAnimator$5
+android.animation.ValueAnimator$AnimationHandler
 android.app.ActionBar
 android.app.ActionBar$LayoutParams
 android.app.Activity
-android.app.Activity$NonConfigurationInstances
 android.app.ActivityManager
 android.app.ActivityManagerNative
 android.app.ActivityManagerNative$1
@@ -54,7 +64,6 @@
 android.app.ActivityThread$ServiceArgsData
 android.app.ActivityThread$StopInfo
 android.app.AlertDialog
-android.app.AlertDialog$Builder
 android.app.AppGlobals
 android.app.Application
 android.app.ApplicationErrorReport$CrashInfo
@@ -62,7 +71,6 @@
 android.app.ApplicationPackageManager
 android.app.ApplicationPackageManager$ResourceName
 android.app.ApplicationThreadNative
-android.app.BackStackRecord
 android.app.ContextImpl
 android.app.ContextImpl$1
 android.app.ContextImpl$10
@@ -87,6 +95,10 @@
 android.app.ContextImpl$28
 android.app.ContextImpl$29
 android.app.ContextImpl$3
+android.app.ContextImpl$30
+android.app.ContextImpl$31
+android.app.ContextImpl$32
+android.app.ContextImpl$33
 android.app.ContextImpl$4
 android.app.ContextImpl$5
 android.app.ContextImpl$6
@@ -99,12 +111,9 @@
 android.app.Dialog
 android.app.Dialog$1
 android.app.Dialog$ListenersHandler
-android.app.Fragment
 android.app.FragmentManager
-android.app.FragmentManager$BackStackEntry
 android.app.FragmentManagerImpl
 android.app.FragmentManagerImpl$1
-android.app.FragmentTransaction
 android.app.IActivityManager
 android.app.IActivityManager$ContentProviderHolder
 android.app.IActivityManager$ContentProviderHolder$1
@@ -114,15 +123,29 @@
 android.app.IApplicationThread
 android.app.IInstrumentationWatcher
 android.app.IInstrumentationWatcher$Stub
+android.app.INotificationManager
+android.app.INotificationManager$Stub
+android.app.INotificationManager$Stub$Proxy
+android.app.ISearchManager
+android.app.ISearchManager$Stub
+android.app.IServiceConnection
+android.app.IServiceConnection$Stub
 android.app.Instrumentation
 android.app.IntentReceiverLeaked
-android.app.ListActivity
+android.app.IntentService
+android.app.IntentService$ServiceHandler
 android.app.LoadedApk
 android.app.LoadedApk$ReceiverDispatcher
 android.app.LoadedApk$ReceiverDispatcher$Args
 android.app.LoadedApk$ReceiverDispatcher$InnerReceiver
+android.app.LoadedApk$ServiceDispatcher
+android.app.LoadedApk$ServiceDispatcher$ConnectionInfo
+android.app.LoadedApk$ServiceDispatcher$DeathMonitor
+android.app.LoadedApk$ServiceDispatcher$InnerConnection
+android.app.LoadedApk$ServiceDispatcher$RunConnection
 android.app.LoadedApk$WarningContextClassLoader
 android.app.NativeActivity
+android.app.NotificationManager
 android.app.PendingIntent
 android.app.PendingIntent$1
 android.app.QueuedWork
@@ -130,6 +153,7 @@
 android.app.ResultInfo
 android.app.ResultInfo$1
 android.app.Service
+android.app.ServiceConnectionLeaked
 android.app.SharedPreferencesImpl
 android.app.SharedPreferencesImpl$1
 android.app.SharedPreferencesImpl$2
@@ -143,6 +167,8 @@
 android.app.backup.BackupHelperDispatcher
 android.app.backup.BackupHelperDispatcher$Header
 android.app.backup.FileBackupHelperBase
+android.app.backup.FullBackup
+android.appwidget.AppWidgetManager
 android.bluetooth.BluetoothAudioGateway
 android.bluetooth.BluetoothSocket
 android.bluetooth.HeadsetBase
@@ -153,6 +179,7 @@
 android.content.BroadcastReceiver
 android.content.BroadcastReceiver$PendingResult
 android.content.ComponentCallbacks
+android.content.ComponentCallbacks2
 android.content.ComponentName
 android.content.ComponentName$1
 android.content.ContentProvider
@@ -161,6 +188,7 @@
 android.content.ContentProviderProxy
 android.content.ContentResolver
 android.content.ContentResolver$CursorWrapperInner
+android.content.ContentResolver$ParcelFileDescriptorInner
 android.content.ContentUris
 android.content.ContentValues
 android.content.ContentValues$1
@@ -226,6 +254,7 @@
 android.content.res.ColorStateList$1
 android.content.res.CompatibilityInfo
 android.content.res.CompatibilityInfo$1
+android.content.res.CompatibilityInfo$2
 android.content.res.Configuration
 android.content.res.Configuration$1
 android.content.res.ObbInfo
@@ -235,6 +264,7 @@
 android.content.res.Resources$1
 android.content.res.Resources$Theme
 android.content.res.StringBlock
+android.content.res.StringBlock$StyleIDs
 android.content.res.TypedArray
 android.content.res.XmlBlock
 android.content.res.XmlBlock$Parser
@@ -252,6 +282,8 @@
 android.database.ContentObserver$Transport
 android.database.CrossProcessCursor
 android.database.Cursor
+android.database.CursorToBulkCursorAdaptor
+android.database.CursorToBulkCursorAdaptor$ContentObserverProxy
 android.database.CursorWindow
 android.database.CursorWindow$1
 android.database.CursorWrapper
@@ -263,6 +295,8 @@
 android.database.IBulkCursor
 android.database.IContentObserver
 android.database.IContentObserver$Stub
+android.database.IContentObserver$Stub$Proxy
+android.database.MatrixCursor
 android.database.Observable
 android.database.sqlite.DatabaseObjectNotClosedException
 android.database.sqlite.SQLiteClosable
@@ -272,8 +306,8 @@
 android.database.sqlite.SQLiteDatabase
 android.database.sqlite.SQLiteDatabase$1
 android.database.sqlite.SQLiteDatabase$CustomFunction
+android.database.sqlite.SQLiteDatabase$DatabaseReentrantLock
 android.database.sqlite.SQLiteDebug
-android.database.sqlite.SQLiteDebug$DbStats
 android.database.sqlite.SQLiteDebug$PagerStats
 android.database.sqlite.SQLiteDirectCursorDriver
 android.database.sqlite.SQLiteOpenHelper
@@ -342,7 +376,9 @@
 android.graphics.PixelFormat
 android.graphics.PixelXorXfermode
 android.graphics.Point
+android.graphics.Point$1
 android.graphics.PointF
+android.graphics.PointF$1
 android.graphics.PorterDuff$Mode
 android.graphics.PorterDuffColorFilter
 android.graphics.PorterDuffXfermode
@@ -362,6 +398,7 @@
 android.graphics.SurfaceTexture
 android.graphics.SweepGradient
 android.graphics.TableMaskFilter
+android.graphics.TemporaryBuffer
 android.graphics.Typeface
 android.graphics.Xfermode
 android.graphics.YuvImage
@@ -378,6 +415,7 @@
 android.graphics.drawable.ColorDrawable$ColorState
 android.graphics.drawable.Drawable
 android.graphics.drawable.Drawable$Callback
+android.graphics.drawable.Drawable$Callback2
 android.graphics.drawable.Drawable$ConstantState
 android.graphics.drawable.DrawableContainer
 android.graphics.drawable.DrawableContainer$1
@@ -392,13 +430,25 @@
 android.graphics.drawable.NinePatchDrawable$NinePatchState
 android.graphics.drawable.RotateDrawable
 android.graphics.drawable.RotateDrawable$RotateState
+android.graphics.drawable.ScaleDrawable
+android.graphics.drawable.ScaleDrawable$ScaleState
+android.graphics.drawable.ShapeDrawable
+android.graphics.drawable.ShapeDrawable$ShapeState
 android.graphics.drawable.StateListDrawable
 android.graphics.drawable.StateListDrawable$StateListState
 android.graphics.drawable.TransitionDrawable
 android.graphics.drawable.TransitionDrawable$TransitionState
+android.graphics.drawable.shapes.RectShape
+android.graphics.drawable.shapes.RoundRectShape
+android.graphics.drawable.shapes.Shape
 android.hardware.Camera
 android.hardware.Camera$CameraInfo
+android.hardware.Camera$Face
+android.hardware.Camera$Parameters
 android.hardware.SensorManager
+android.hardware.usb.UsbDevice
+android.hardware.usb.UsbDeviceConnection
+android.hardware.usb.UsbRequest
 android.inputmethodservice.ExtractEditText
 android.location.GpsSatellite
 android.location.GpsStatus
@@ -407,26 +457,40 @@
 android.location.ILocationManager$Stub
 android.location.ILocationManager$Stub$Proxy
 android.location.Location
+android.location.Location$1
+android.location.LocationListener
 android.location.LocationManager
 android.media.AudioFormat
 android.media.AudioManager
 android.media.AudioManager$1
+android.media.AudioManager$2
 android.media.AudioManager$FocusEventHandlerDelegate
 android.media.AudioManager$FocusEventHandlerDelegate$1
 android.media.AudioRecord
 android.media.AudioSystem
 android.media.AudioTrack
-android.media.CamcorderProfile
+android.media.CameraProfile
 android.media.DecoderCapabilities
 android.media.IAudioFocusDispatcher
 android.media.IAudioFocusDispatcher$Stub
+android.media.IAudioService
+android.media.IAudioService$Stub
+android.media.IAudioService$Stub$Proxy
+android.media.IRemoteControlClientDispatcher
+android.media.IRemoteControlClientDispatcher$Stub
 android.media.JetPlayer
+android.media.MediaFile
 android.media.MediaPlayer
+android.media.MediaPlayer$OnBufferingUpdateListener
+android.media.MediaPlayer$OnCompletionListener
+android.media.MediaPlayer$OnErrorListener
+android.media.MediaPlayer$OnInfoListener
+android.media.MediaPlayer$OnPreparedListener
+android.media.MediaScanner
 android.media.ToneGenerator
 android.net.ConnectivityManager
 android.net.Credentials
-android.net.DhcpInfo
-android.net.DhcpInfo$1
+android.net.DhcpInfoInternal
 android.net.IConnectivityManager
 android.net.IConnectivityManager$Stub
 android.net.IConnectivityManager$Stub$Proxy
@@ -441,8 +505,9 @@
 android.net.NetworkInfo$State
 android.net.NetworkUtils
 android.net.Proxy
-android.net.ProxyProperties
-android.net.ProxyProperties$1
+android.net.SSLCertificateSocketFactory
+android.net.SSLCertificateSocketFactory$1
+android.net.SSLSessionCache
 android.net.TrafficStats
 android.net.Uri
 android.net.Uri$1
@@ -450,12 +515,18 @@
 android.net.Uri$AbstractPart
 android.net.Uri$Builder
 android.net.Uri$HierarchicalUri
+android.net.Uri$OpaqueUri
 android.net.Uri$Part
 android.net.Uri$Part$EmptyPart
 android.net.Uri$PathPart
 android.net.Uri$PathSegments
 android.net.Uri$PathSegmentsBuilder
 android.net.Uri$StringUri
+android.net.WebAddress
+android.net.http.AndroidHttpClient
+android.net.http.AndroidHttpClient$1
+android.net.http.AndroidHttpClient$2
+android.net.http.AndroidHttpClient$CurlLogger
 android.net.wifi.WifiNative
 android.nfc.NdefMessage
 android.nfc.NdefRecord
@@ -477,6 +548,7 @@
 android.os.AsyncTask$SerialExecutor$1
 android.os.AsyncTask$Status
 android.os.AsyncTask$WorkerRunnable
+android.os.BatteryStats
 android.os.Binder
 android.os.BinderProxy
 android.os.Build
@@ -510,6 +582,7 @@
 android.os.ParcelFileDescriptor
 android.os.ParcelFileDescriptor$1
 android.os.Parcelable
+android.os.Parcelable$ClassLoaderCreator
 android.os.Parcelable$Creator
 android.os.PatternMatcher
 android.os.PatternMatcher$1
@@ -535,6 +608,7 @@
 android.os.StrictMode$AndroidBlockGuardPolicy$1
 android.os.StrictMode$AndroidCloseGuardReporter
 android.os.StrictMode$InstanceCountViolation
+android.os.StrictMode$InstanceTracker
 android.os.StrictMode$LogStackTrace
 android.os.StrictMode$Span
 android.os.StrictMode$StrictModeDiskReadViolation
@@ -548,7 +622,11 @@
 android.os.SystemClock
 android.os.SystemProperties
 android.os.UEventObserver
-android.pim.EventRecurrence
+android.os.Vibrator
+android.os.storage.IMountService
+android.os.storage.IMountService$Stub
+android.os.storage.IMountService$Stub$Proxy
+android.preference.PreferenceActivity
 android.preference.PreferenceManager
 android.provider.BaseColumns
 android.provider.Settings$NameValueCache
@@ -559,6 +637,7 @@
 android.server.BluetoothA2dpService
 android.server.BluetoothEventLoop
 android.server.BluetoothService
+android.telephony.PhoneNumberUtils
 android.telephony.TelephonyManager
 android.text.AndroidBidi
 android.text.AndroidCharacter
@@ -585,6 +664,7 @@
 android.text.ParcelableSpan
 android.text.Selection
 android.text.Selection$END
+android.text.Selection$PositionIterator
 android.text.Selection$START
 android.text.SpanWatcher
 android.text.Spannable
@@ -595,6 +675,16 @@
 android.text.Spanned
 android.text.SpannedString
 android.text.StaticLayout
+android.text.TextDirectionHeuristic
+android.text.TextDirectionHeuristics
+android.text.TextDirectionHeuristics$1
+android.text.TextDirectionHeuristics$AnyStrong
+android.text.TextDirectionHeuristics$CharCount
+android.text.TextDirectionHeuristics$FirstStrong
+android.text.TextDirectionHeuristics$TextDirectionAlgorithm
+android.text.TextDirectionHeuristics$TextDirectionHeuristicImpl
+android.text.TextDirectionHeuristics$TextDirectionHeuristicInternal
+android.text.TextDirectionHeuristics$TriState
 android.text.TextLine
 android.text.TextPaint
 android.text.TextUtils
@@ -603,12 +693,14 @@
 android.text.TextUtils$TruncateAt
 android.text.TextWatcher
 android.text.format.Time
+android.text.method.AllCapsTransformationMethod
 android.text.method.ArrowKeyMovementMethod
 android.text.method.BaseKeyListener
 android.text.method.BaseMovementMethod
 android.text.method.KeyListener
 android.text.method.MetaKeyKeyListener
 android.text.method.MovementMethod
+android.text.method.QwertyKeyListener
 android.text.method.ReplacementTransformationMethod
 android.text.method.ReplacementTransformationMethod$ReplacementCharSequence
 android.text.method.ReplacementTransformationMethod$SpannedReplacementCharSequence
@@ -616,6 +708,9 @@
 android.text.method.TextKeyListener
 android.text.method.TextKeyListener$Capitalize
 android.text.method.TransformationMethod
+android.text.method.TransformationMethod2
+android.text.method.WordIterator
+android.text.method.WordIterator$1
 android.text.style.AlignmentSpan
 android.text.style.CharacterStyle
 android.text.style.LeadingMarginSpan
@@ -624,29 +719,35 @@
 android.text.style.MetricAffectingSpan
 android.text.style.ParagraphStyle
 android.text.style.ReplacementSpan
+android.text.style.StyleSpan
+android.text.style.SuggestionSpan
 android.text.style.UpdateAppearance
 android.text.style.UpdateLayout
 android.text.style.WrapTogetherSpan
 android.util.AndroidException
 android.util.AndroidRuntimeException
 android.util.AttributeSet
-android.util.DebugUtils
 android.util.DisplayMetrics
 android.util.EventLog
 android.util.EventLog$Event
 android.util.FinitePool
 android.util.FloatMath
+android.util.FloatProperty
+android.util.LocaleUtil
 android.util.Log
 android.util.Log$1
 android.util.Log$TerribleFailureHandler
 android.util.LongSparseArray
+android.util.LruCache
 android.util.Pair
 android.util.Patterns
 android.util.Pool
 android.util.Poolable
 android.util.PoolableManager
 android.util.Pools
+android.util.Property
 android.util.Singleton
+android.util.Slog
 android.util.SparseArray
 android.util.SparseBooleanArray
 android.util.SparseIntArray
@@ -659,24 +760,36 @@
 android.view.AbsSavedState$2
 android.view.ActionMode
 android.view.ActionMode$Callback
+android.view.CompatibilityInfoHolder
 android.view.ContextMenu
 android.view.ContextMenu$ContextMenuInfo
 android.view.ContextThemeWrapper
 android.view.Display
+android.view.DisplayList
 android.view.FallbackEventHandler
 android.view.FocusFinder
 android.view.FocusFinder$1
 android.view.FocusFinder$SequentialFocusComparator
 android.view.GLES20Canvas
 android.view.GLES20Canvas$CanvasFinalizer
+android.view.GLES20DisplayList
+android.view.GLES20DisplayList$DisplayListFinalizer
+android.view.GLES20Layer
+android.view.GLES20Layer$Finalizer
+android.view.GLES20RecordingCanvas
+android.view.GLES20RecordingCanvas$1
+android.view.GLES20RenderLayer
+android.view.GestureDetector$OnDoubleTapListener
+android.view.GestureDetector$OnGestureListener
 android.view.Gravity
 android.view.HardwareCanvas
+android.view.HardwareLayer
 android.view.HardwareRenderer
 android.view.HardwareRenderer$Gl20Renderer
 android.view.HardwareRenderer$GlRenderer
-android.view.HardwareRenderer$GlRenderer$ComponentSizeChooser
-android.view.HardwareRenderer$GlRenderer$EglConfigChooser
 android.view.HardwareRenderer$HardwareDrawCallbacks
+android.view.IRotationWatcher
+android.view.IRotationWatcher$Stub
 android.view.IWindow
 android.view.IWindow$Stub
 android.view.IWindowManager
@@ -689,6 +802,8 @@
 android.view.InputChannel$1
 android.view.InputEvent
 android.view.InputEvent$1
+android.view.InputEventConsistencyVerifier
+android.view.InputEventConsistencyVerifier$KeyState
 android.view.InputHandler
 android.view.InputQueue
 android.view.InputQueue$Callback
@@ -702,12 +817,17 @@
 android.view.LayoutInflater
 android.view.LayoutInflater$Factory
 android.view.LayoutInflater$Factory2
+android.view.LayoutInflater$Filter
 android.view.Menu
 android.view.MenuInflater
 android.view.MenuInflater$MenuState
 android.view.MenuItem
 android.view.MotionEvent
 android.view.MotionEvent$1
+android.view.MotionEvent$PointerCoords
+android.view.MotionEvent$PointerProperties
+android.view.PointerIcon
+android.view.PointerIcon$1
 android.view.Surface
 android.view.Surface$1
 android.view.Surface$CompatibleCanvas
@@ -719,10 +839,22 @@
 android.view.SurfaceView$1
 android.view.SurfaceView$2
 android.view.SurfaceView$3
+android.view.SurfaceView$4
+android.view.SurfaceView$MyWindow
+android.view.TextureView
 android.view.VelocityTracker
 android.view.VelocityTracker$1
-android.view.VelocityTracker$Pointer
 android.view.View
+android.view.View$10
+android.view.View$11
+android.view.View$12
+android.view.View$13
+android.view.View$4
+android.view.View$5
+android.view.View$6
+android.view.View$7
+android.view.View$8
+android.view.View$9
 android.view.View$AttachInfo
 android.view.View$AttachInfo$Callbacks
 android.view.View$BaseSavedState
@@ -733,29 +865,31 @@
 android.view.View$OnCreateContextMenuListener
 android.view.View$OnFocusChangeListener
 android.view.View$OnKeyListener
+android.view.View$OnLayoutChangeListener
 android.view.View$OnLongClickListener
 android.view.View$OnTouchListener
 android.view.View$PerformClick
 android.view.View$ScrollabilityCache
 android.view.View$UnsetPressedState
 android.view.ViewConfiguration
-android.view.ViewDebug
 android.view.ViewGroup
 android.view.ViewGroup$3
 android.view.ViewGroup$LayoutParams
 android.view.ViewGroup$MarginLayoutParams
+android.view.ViewGroup$OnHierarchyChangeListener
 android.view.ViewGroup$TouchTarget
 android.view.ViewManager
 android.view.ViewParent
-android.view.ViewRoot
-android.view.ViewRoot$1
-android.view.ViewRoot$2
-android.view.ViewRoot$InputMethodCallback
-android.view.ViewRoot$ResizedInfo
-android.view.ViewRoot$RunQueue
-android.view.ViewRoot$RunQueue$HandlerAction
-android.view.ViewRoot$TrackballAxis
-android.view.ViewRoot$W
+android.view.ViewRootImpl
+android.view.ViewRootImpl$2
+android.view.ViewRootImpl$3
+android.view.ViewRootImpl$AccessibilityInteractionConnectionManager
+android.view.ViewRootImpl$InputMethodCallback
+android.view.ViewRootImpl$ResizedInfo
+android.view.ViewRootImpl$RunQueue
+android.view.ViewRootImpl$RunQueue$HandlerAction
+android.view.ViewRootImpl$TrackballAxis
+android.view.ViewRootImpl$W
 android.view.ViewStub
 android.view.ViewTreeObserver
 android.view.ViewTreeObserver$InternalInsetsInfo
@@ -771,17 +905,21 @@
 android.view.WindowManager$LayoutParams
 android.view.WindowManager$LayoutParams$1
 android.view.WindowManagerImpl
+android.view.WindowManagerImpl$CompatModeWrapper
 android.view.accessibility.AccessibilityEvent
 android.view.accessibility.AccessibilityEventSource
 android.view.accessibility.AccessibilityManager
 android.view.accessibility.AccessibilityManager$1
+android.view.accessibility.AccessibilityManager$AccessibilityStateChangeListener
 android.view.accessibility.AccessibilityManager$MyHandler
+android.view.accessibility.AccessibilityRecord
 android.view.accessibility.IAccessibilityManager
 android.view.accessibility.IAccessibilityManager$Stub
 android.view.accessibility.IAccessibilityManager$Stub$Proxy
 android.view.accessibility.IAccessibilityManagerClient
 android.view.accessibility.IAccessibilityManagerClient$Stub
 android.view.animation.AccelerateDecelerateInterpolator
+android.view.animation.AccelerateInterpolator
 android.view.animation.AlphaAnimation
 android.view.animation.Animation
 android.view.animation.AnimationUtils
@@ -794,27 +932,30 @@
 android.view.inputmethod.EditorInfo
 android.view.inputmethod.EditorInfo$1
 android.view.inputmethod.ExtractedText
-android.view.inputmethod.ExtractedTextRequest
-android.view.inputmethod.ExtractedTextRequest$1
+android.view.inputmethod.ExtractedText$1
 android.view.inputmethod.InputConnection
 android.view.inputmethod.InputMethodManager
 android.view.inputmethod.InputMethodManager$1
 android.view.inputmethod.InputMethodManager$ControlledInputConnectionWrapper
 android.view.inputmethod.InputMethodManager$H
-android.webkit.LoadListener
+android.webkit.JniUtil
 android.webkit.PluginManager
+android.webkit.WebTextView
 android.webkit.WebView
-android.webkit.WebView$HitTestResult
 android.webkit.WebViewCore
-android.webkit.WebViewCore$TouchUpData
 android.widget.AbsListView
+android.widget.AbsListView$1
 android.widget.AbsListView$2
 android.widget.AbsListView$AdapterDataSetObserver
+android.widget.AbsListView$CheckForTap
 android.widget.AbsListView$LayoutParams
 android.widget.AbsListView$OnScrollListener
+android.widget.AbsListView$PerformClick
 android.widget.AbsListView$RecycleBin
 android.widget.AbsListView$SavedState
 android.widget.AbsListView$SavedState$1
+android.widget.AbsListView$SelectionBoundsAdjuster
+android.widget.AbsListView$WindowRunnnable
 android.widget.AbsSpinner
 android.widget.AbsSpinner$RecycleBin
 android.widget.Adapter
@@ -825,21 +966,30 @@
 android.widget.AdapterViewAnimator
 android.widget.ArrayAdapter
 android.widget.AutoCompleteTextView
+android.widget.AutoCompleteTextView$DropDownItemClickListener
+android.widget.AutoCompleteTextView$MyWatcher
+android.widget.AutoCompleteTextView$PassThroughClickListener
 android.widget.BaseAdapter
 android.widget.Button
 android.widget.CheckBox
 android.widget.Checkable
+android.widget.CheckedTextView
 android.widget.CompoundButton
+android.widget.CursorAdapter
+android.widget.CursorFilter$CursorFilterClient
 android.widget.EdgeGlow
 android.widget.EditText
 android.widget.ExpandableListView
 android.widget.Filter
 android.widget.Filter$FilterListener
+android.widget.Filter$ResultsHandler
 android.widget.Filterable
 android.widget.FrameLayout
 android.widget.FrameLayout$LayoutParams
 android.widget.Gallery
+android.widget.GridLayout
 android.widget.GridView
+android.widget.HorizontalScrollView
 android.widget.ImageButton
 android.widget.ImageView
 android.widget.ImageView$ScaleType
@@ -848,62 +998,81 @@
 android.widget.ListAdapter
 android.widget.ListPopupWindow
 android.widget.ListPopupWindow$ListSelectorHider
+android.widget.ListPopupWindow$PopupDataSetObserver
 android.widget.ListPopupWindow$PopupScrollListener
 android.widget.ListPopupWindow$PopupTouchInterceptor
 android.widget.ListPopupWindow$ResizePopupRunnable
 android.widget.ListView
 android.widget.ListView$ArrowScrollFocusResult
+android.widget.NumberPicker
 android.widget.OverScroller
 android.widget.OverScroller$SplineOverScroller
 android.widget.PopupWindow
 android.widget.PopupWindow$1
 android.widget.ProgressBar
+android.widget.ProgressBar$SavedState
+android.widget.ProgressBar$SavedState$1
 android.widget.RelativeLayout
 android.widget.RelativeLayout$DependencyGraph
 android.widget.RelativeLayout$DependencyGraph$Node
 android.widget.RelativeLayout$DependencyGraph$Node$1
 android.widget.RelativeLayout$LayoutParams
+android.widget.RemoteViews
+android.widget.RemoteViews$1
+android.widget.RemoteViews$Action
+android.widget.RemoteViews$MemoryUsageCounter
+android.widget.RemoteViews$ReflectionAction
 android.widget.RemoteViewsAdapter$RemoteAdapterConnectionCallback
 android.widget.ScrollBarDrawable
 android.widget.ScrollView
 android.widget.Scroller
+android.widget.SearchView
+android.widget.Spinner
 android.widget.SpinnerAdapter
-android.widget.Switch
+android.widget.StackView
+android.widget.TabHost
 android.widget.TabWidget
 android.widget.TableLayout
 android.widget.TableRow
 android.widget.TextView
 android.widget.TextView$3
+android.widget.TextView$Blink
 android.widget.TextView$BufferType
 android.widget.TextView$ChangeWatcher
 android.widget.TextView$CharWrapper
 android.widget.TextView$Drawables
 android.widget.TextView$InputContentType
+android.widget.TextView$InputMethodState
 android.widget.TextView$OnEditorActionListener
 android.widget.TextView$SavedState
-android.widget.TextView$SavedState$1
+android.widget.TextView$TextAlign
+android.widget.VideoView
+android.widget.ViewAnimator
+com.android.i18n.phonenumbers.AsYouTypeFormatter
+com.android.i18n.phonenumbers.PhoneNumberUtil
 com.android.internal.R$styleable
 com.android.internal.app.ActionBarImpl
 com.android.internal.app.ActionBarImpl$1
 com.android.internal.app.ActionBarImpl$2
-com.android.internal.app.ActionBarImpl$3
-com.android.internal.app.ActionBarImpl$4
 com.android.internal.app.AlertController
 com.android.internal.app.AlertController$1
 com.android.internal.app.AlertController$ButtonHandler
 com.android.internal.appwidget.IAppWidgetService
 com.android.internal.appwidget.IAppWidgetService$Stub
-com.android.internal.graphics.NativeUtils
+com.android.internal.appwidget.IAppWidgetService$Stub$Proxy
+com.android.internal.content.NativeLibraryHelper
 com.android.internal.logging.AndroidConfig
 com.android.internal.logging.AndroidHandler
 com.android.internal.logging.AndroidHandler$1
 com.android.internal.os.AndroidPrintStream
+com.android.internal.os.BatteryStatsImpl
 com.android.internal.os.BinderInternal
 com.android.internal.os.BinderInternal$GcWatcher
 com.android.internal.os.LoggingPrintStream
 com.android.internal.os.LoggingPrintStream$1
 com.android.internal.os.RuntimeInit
 com.android.internal.os.RuntimeInit$1
+com.android.internal.os.RuntimeInit$Arguments
 com.android.internal.os.RuntimeInit$UncaughtHandler
 com.android.internal.os.SamplingProfilerIntegration
 com.android.internal.os.ZygoteConnection
@@ -916,19 +1085,24 @@
 com.android.internal.policy.impl.PhoneLayoutInflater
 com.android.internal.policy.impl.PhoneWindow
 com.android.internal.policy.impl.PhoneWindow$1
-com.android.internal.policy.impl.PhoneWindow$2
+com.android.internal.policy.impl.PhoneWindow$ActionMenuPresenterCallback
 com.android.internal.policy.impl.PhoneWindow$DecorView
 com.android.internal.policy.impl.PhoneWindow$DialogMenuCallback
 com.android.internal.policy.impl.PhoneWindow$PanelFeatureState
 com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState
 com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState$1
+com.android.internal.policy.impl.PhoneWindow$RotationWatcher
+com.android.internal.policy.impl.PhoneWindow$RotationWatcher$1
 com.android.internal.policy.impl.Policy
+com.android.internal.telephony.ITelephony
+com.android.internal.telephony.ITelephony$Stub
 com.android.internal.telephony.ITelephonyRegistry
 com.android.internal.telephony.ITelephonyRegistry$Stub
 com.android.internal.telephony.ITelephonyRegistry$Stub$Proxy
 com.android.internal.telephony.Phone$State
 com.android.internal.util.ArrayUtils
 com.android.internal.util.FastXmlSerializer
+com.android.internal.util.Preconditions
 com.android.internal.util.XmlUtils
 com.android.internal.view.BaseIWindow
 com.android.internal.view.IInputConnectionWrapper
@@ -951,21 +1125,136 @@
 com.android.internal.view.InputBindResult$1
 com.android.internal.view.RootViewSurfaceTaker
 com.android.internal.view.menu.ActionMenuItem
+com.android.internal.view.menu.ActionMenuItemView
+com.android.internal.view.menu.ActionMenuPresenter
+com.android.internal.view.menu.ActionMenuPresenter$OverflowMenuButton
+com.android.internal.view.menu.ActionMenuPresenter$PopupPresenterCallback
 com.android.internal.view.menu.ActionMenuView
-com.android.internal.view.menu.ActionMenuView$1
-com.android.internal.view.menu.ActionMenuView$OverflowMenuButton
+com.android.internal.view.menu.ActionMenuView$ActionMenuChildView
+com.android.internal.view.menu.ActionMenuView$LayoutParams
+com.android.internal.view.menu.BaseMenuPresenter
 com.android.internal.view.menu.MenuBuilder
 com.android.internal.view.menu.MenuBuilder$Callback
 com.android.internal.view.menu.MenuBuilder$ItemInvoker
-com.android.internal.view.menu.MenuBuilder$MenuType
 com.android.internal.view.menu.MenuItemImpl
+com.android.internal.view.menu.MenuPresenter
+com.android.internal.view.menu.MenuPresenter$Callback
 com.android.internal.view.menu.MenuView
+com.android.internal.view.menu.MenuView$ItemView
+com.android.internal.widget.AbsActionBarView
+com.android.internal.widget.AbsActionBarView$VisibilityAnimListener
 com.android.internal.widget.ActionBarContainer
 com.android.internal.widget.ActionBarContextView
 com.android.internal.widget.ActionBarView
 com.android.internal.widget.ActionBarView$1
 com.android.internal.widget.ActionBarView$2
+com.android.internal.widget.ActionBarView$3
+com.android.internal.widget.ActionBarView$ExpandedActionViewMenuPresenter
+com.android.internal.widget.ActionBarView$HomeView
+com.android.internal.widget.ActionBarView$SavedState
+com.android.internal.widget.ActionBarView$SavedState$1
 com.android.internal.widget.DialogTitle
+com.android.internal.widget.EditableInputConnection
+com.android.internal.widget.ScrollingTabContainerView
+com.android.org.bouncycastle.asn1.ASN1Choice
+com.android.org.bouncycastle.asn1.ASN1Encodable
+com.android.org.bouncycastle.asn1.ASN1EncodableVector
+com.android.org.bouncycastle.asn1.ASN1InputStream
+com.android.org.bouncycastle.asn1.ASN1Integer
+com.android.org.bouncycastle.asn1.ASN1Null
+com.android.org.bouncycastle.asn1.ASN1Object
+com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier
+com.android.org.bouncycastle.asn1.ASN1OctetString
+com.android.org.bouncycastle.asn1.ASN1OctetStringParser
+com.android.org.bouncycastle.asn1.ASN1Sequence
+com.android.org.bouncycastle.asn1.ASN1Set
+com.android.org.bouncycastle.asn1.ASN1StreamParser
+com.android.org.bouncycastle.asn1.ASN1String
+com.android.org.bouncycastle.asn1.ASN1TaggedObject
+com.android.org.bouncycastle.asn1.ASN1TaggedObjectParser
+com.android.org.bouncycastle.asn1.DERBitString
+com.android.org.bouncycastle.asn1.DERBoolean
+com.android.org.bouncycastle.asn1.DEREncodable
+com.android.org.bouncycastle.asn1.DEREncodableVector
+com.android.org.bouncycastle.asn1.DERFactory
+com.android.org.bouncycastle.asn1.DERIA5String
+com.android.org.bouncycastle.asn1.DERInteger
+com.android.org.bouncycastle.asn1.DERNull
+com.android.org.bouncycastle.asn1.DERObject
+com.android.org.bouncycastle.asn1.DERObjectIdentifier
+com.android.org.bouncycastle.asn1.DEROctetString
+com.android.org.bouncycastle.asn1.DEROutputStream
+com.android.org.bouncycastle.asn1.DERPrintableString
+com.android.org.bouncycastle.asn1.DERSequence
+com.android.org.bouncycastle.asn1.DERSet
+com.android.org.bouncycastle.asn1.DERString
+com.android.org.bouncycastle.asn1.DERT61String
+com.android.org.bouncycastle.asn1.DERTaggedObject
+com.android.org.bouncycastle.asn1.DERTags
+com.android.org.bouncycastle.asn1.DERUniversalString
+com.android.org.bouncycastle.asn1.DefiniteLengthInputStream
+com.android.org.bouncycastle.asn1.InMemoryRepresentable
+com.android.org.bouncycastle.asn1.IndefiniteLengthInputStream
+com.android.org.bouncycastle.asn1.LimitedInputStream
+com.android.org.bouncycastle.asn1.OIDTokenizer
+com.android.org.bouncycastle.asn1.bc.BCObjectIdentifiers
+com.android.org.bouncycastle.asn1.iana.IANAObjectIdentifiers
+com.android.org.bouncycastle.asn1.nist.NISTObjectIdentifiers
+com.android.org.bouncycastle.asn1.oiw.OIWObjectIdentifiers
+com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers
+com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier
+com.android.org.bouncycastle.asn1.x509.BasicConstraints
+com.android.org.bouncycastle.asn1.x509.DigestInfo
+com.android.org.bouncycastle.asn1.x509.GeneralName
+com.android.org.bouncycastle.asn1.x509.GeneralNames
+com.android.org.bouncycastle.asn1.x509.RSAPublicKeyStructure
+com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
+com.android.org.bouncycastle.asn1.x509.X509Extensions
+com.android.org.bouncycastle.asn1.x509.X509Name
+com.android.org.bouncycastle.asn1.x509.X509ObjectIdentifiers
+com.android.org.bouncycastle.asn1.x9.X9ObjectIdentifiers
+com.android.org.bouncycastle.crypto.AsymmetricBlockCipher
+com.android.org.bouncycastle.crypto.CipherParameters
+com.android.org.bouncycastle.crypto.Digest
+com.android.org.bouncycastle.crypto.ExtendedDigest
+com.android.org.bouncycastle.crypto.digests.GeneralDigest
+com.android.org.bouncycastle.crypto.digests.SHA1Digest
+com.android.org.bouncycastle.crypto.encodings.PKCS1Encoding
+com.android.org.bouncycastle.crypto.encodings.PKCS1Encoding$1
+com.android.org.bouncycastle.crypto.engines.RSABlindedEngine
+com.android.org.bouncycastle.crypto.engines.RSACoreEngine
+com.android.org.bouncycastle.crypto.params.AsymmetricKeyParameter
+com.android.org.bouncycastle.crypto.params.ParametersWithRandom
+com.android.org.bouncycastle.crypto.params.RSAKeyParameters
+com.android.org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters
+com.android.org.bouncycastle.crypto.util.Pack
+com.android.org.bouncycastle.jce.interfaces.BCKeyStore
+com.android.org.bouncycastle.jce.interfaces.ConfigurableProvider
+com.android.org.bouncycastle.jce.provider.BouncyCastleProvider
+com.android.org.bouncycastle.jce.provider.BouncyCastleProvider$1
+com.android.org.bouncycastle.jce.provider.CertPathValidatorUtilities
+com.android.org.bouncycastle.jce.provider.JCERSAPublicKey
+com.android.org.bouncycastle.jce.provider.JDKDigestSignature
+com.android.org.bouncycastle.jce.provider.JDKDigestSignature$SHA1WithRSAEncryption
+com.android.org.bouncycastle.jce.provider.JDKKeyFactory
+com.android.org.bouncycastle.jce.provider.JDKKeyFactory$RSA
+com.android.org.bouncycastle.jce.provider.JDKKeyStore
+com.android.org.bouncycastle.jce.provider.PKIXCRLUtil
+com.android.org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi
+com.android.org.bouncycastle.jce.provider.PKIXNameConstraintValidator
+com.android.org.bouncycastle.jce.provider.PKIXPolicyNode
+com.android.org.bouncycastle.jce.provider.RFC3280CertPathUtilities
+com.android.org.bouncycastle.jce.provider.RSAUtil
+com.android.org.bouncycastle.jce.provider.asymmetric.EC$Mappings
+com.android.org.bouncycastle.jce.provider.symmetric.AES$Mappings
+com.android.org.bouncycastle.jce.provider.symmetric.ARC4$Mappings
+com.android.org.bouncycastle.jce.provider.symmetric.Blowfish$Mappings
+com.android.org.bouncycastle.jce.provider.symmetric.DESede$Mappings
+com.android.org.bouncycastle.util.io.Streams
+com.android.org.bouncycastle.x509.ExtendedPKIXParameters
+com.android.server.NetworkManagementSocketTagger
+com.android.server.NetworkManagementSocketTagger$1
+com.android.server.NetworkManagementSocketTagger$SocketTags
 com.android.server.Watchdog
 com.google.android.collect.Lists
 com.google.android.collect.Maps
@@ -975,23 +1264,25 @@
 com.google.android.gles_jni.EGLImpl
 com.google.android.gles_jni.EGLSurfaceImpl
 com.google.android.gles_jni.GLImpl
-com.android.i18n.phonenumbers.PhoneNumberUtil
+dalvik.system.BaseDexClassLoader
 dalvik.system.BlockGuard
 dalvik.system.BlockGuard$1
 dalvik.system.BlockGuard$2
 dalvik.system.BlockGuard$BlockGuardPolicyException
 dalvik.system.BlockGuard$Policy
-dalvik.system.BlockGuard$WrappedFileSystem
-dalvik.system.BlockGuard$WrappedNetworkSystem
 dalvik.system.CloseGuard
 dalvik.system.CloseGuard$DefaultReporter
 dalvik.system.CloseGuard$Reporter
 dalvik.system.DalvikLogHandler
 dalvik.system.DalvikLogging
 dalvik.system.DexFile
+dalvik.system.DexPathList
+dalvik.system.DexPathList$Element
 dalvik.system.NativeStart
 dalvik.system.PathClassLoader
-dalvik.system.TouchDex
+dalvik.system.SocketTagger
+dalvik.system.SocketTagger$1
+dalvik.system.StaleDexCacheError
 dalvik.system.VMDebug
 dalvik.system.VMRuntime
 dalvik.system.VMStack
@@ -1019,58 +1310,78 @@
 java.io.IOException
 java.io.InputStream
 java.io.InputStreamReader
-java.io.InterruptedIOException
 java.io.ObjectStreamClass
 java.io.ObjectStreamField
 java.io.OutputStream
 java.io.OutputStreamWriter
 java.io.PrintStream
 java.io.PrintWriter
-java.io.PushbackInputStream
 java.io.RandomAccessFile
 java.io.Reader
 java.io.Serializable
 java.io.StringWriter
 java.io.Writer
+java.lang.AbstractMethodError
 java.lang.AbstractStringBuilder
 java.lang.Appendable
+java.lang.ArithmeticException
 java.lang.ArrayIndexOutOfBoundsException
+java.lang.ArrayStoreException
+java.lang.AutoCloseable
 java.lang.Boolean
 java.lang.BootClassLoader
 java.lang.Byte
 java.lang.CaseMapper
 java.lang.CharSequence
 java.lang.Character
+java.lang.Character$UnicodeBlock
 java.lang.Class
-java.lang.ClassCache
-java.lang.ClassCache$EnumComparator
 java.lang.ClassCastException
+java.lang.ClassCircularityError
+java.lang.ClassFormatError
 java.lang.ClassLoader
 java.lang.ClassLoader$SystemClassLoader
 java.lang.ClassNotFoundException
 java.lang.Cloneable
 java.lang.Comparable
+java.lang.Daemons
+java.lang.Daemons$Daemon
+java.lang.Daemons$FinalizerDaemon
+java.lang.Daemons$FinalizerWatchdogDaemon
+java.lang.Daemons$ReferenceQueueDaemon
 java.lang.Double
 java.lang.Enum
+java.lang.Enum$1
 java.lang.Error
 java.lang.Exception
 java.lang.ExceptionInInitializerError
 java.lang.Float
+java.lang.IllegalAccessError
+java.lang.IllegalAccessException
 java.lang.IllegalArgumentException
+java.lang.IllegalMonitorStateException
 java.lang.IllegalStateException
+java.lang.IllegalThreadStateException
+java.lang.IncompatibleClassChangeError
 java.lang.IndexOutOfBoundsException
+java.lang.InstantiationError
+java.lang.InstantiationException
 java.lang.Integer
 java.lang.IntegralToString
 java.lang.IntegralToString$1
 java.lang.InternalError
 java.lang.InterruptedException
 java.lang.Iterable
-java.lang.LangAccessImpl
 java.lang.LinkageError
 java.lang.Long
 java.lang.Math
+java.lang.NegativeArraySizeException
 java.lang.NoClassDefFoundError
+java.lang.NoSuchFieldError
+java.lang.NoSuchFieldException
+java.lang.NoSuchMethodError
 java.lang.NoSuchMethodException
+java.lang.NullPointerException
 java.lang.Number
 java.lang.NumberFormatException
 java.lang.Object
@@ -1082,7 +1393,6 @@
 java.lang.Runtime
 java.lang.RuntimeException
 java.lang.RuntimePermission
-java.lang.SecurityException
 java.lang.Short
 java.lang.StackOverflowError
 java.lang.StackTraceElement
@@ -1091,8 +1401,10 @@
 java.lang.String$CaseInsensitiveComparator
 java.lang.StringBuffer
 java.lang.StringBuilder
+java.lang.StringIndexOutOfBoundsException
+java.lang.StringToReal
+java.lang.StringToReal$StringExponentPair
 java.lang.System
-java.lang.SystemProperties
 java.lang.Thread
 java.lang.Thread$State
 java.lang.Thread$UncaughtExceptionHandler
@@ -1100,15 +1412,18 @@
 java.lang.ThreadLocal
 java.lang.ThreadLocal$Values
 java.lang.Throwable
+java.lang.TypeNotPresentException
 java.lang.UnsafeByteSequence
 java.lang.UnsatisfiedLinkError
 java.lang.UnsupportedOperationException
 java.lang.VMClassLoader
 java.lang.VMThread
+java.lang.VerifyError
 java.lang.VirtualMachineError
 java.lang.Void
 java.lang.annotation.Annotation
-java.lang.ref.PhantomReference
+java.lang.ref.FinalizerReference
+java.lang.ref.FinalizerReference$Sentinel
 java.lang.ref.Reference
 java.lang.ref.ReferenceQueue
 java.lang.ref.SoftReference
@@ -1118,6 +1433,7 @@
 java.lang.reflect.Array
 java.lang.reflect.Constructor
 java.lang.reflect.Field
+java.lang.reflect.Field$1
 java.lang.reflect.GenericDeclaration
 java.lang.reflect.InvocationHandler
 java.lang.reflect.Member
@@ -1125,46 +1441,39 @@
 java.lang.reflect.Method$1
 java.lang.reflect.Modifier
 java.lang.reflect.Proxy
-java.lang.reflect.ReflectionAccessImpl
 java.lang.reflect.Type
 java.math.BigDecimal
 java.math.BigInt
 java.math.BigInteger
+java.math.Multiplication
 java.math.NativeBN
 java.math.RoundingMode
 java.net.AddressCache
-java.net.AddressCache$1
 java.net.AddressCache$AddressCacheEntry
 java.net.ContentHandler
-java.net.DatagramPacket
 java.net.HttpURLConnection
 java.net.Inet4Address
+java.net.Inet6Address
 java.net.InetAddress
-java.net.InetAddress$1
-java.net.InetAddress$WaitReachable
 java.net.InetSocketAddress
-java.net.InterfaceAddress
 java.net.JarURLConnection
-java.net.MulticastGroupRequest
-java.net.NetPermission
-java.net.NetworkInterface
+java.net.PlainSocketImpl
 java.net.Proxy
 java.net.Proxy$Type
 java.net.ProxySelector
 java.net.ProxySelectorImpl
 java.net.Socket
 java.net.SocketAddress
-java.net.SocketException
 java.net.SocketImpl
-java.net.SocketImplFactory
 java.net.SocketOptions
-java.net.SocketTimeoutException
 java.net.URI
-java.net.URIEncoderDecoder
+java.net.URI$1
+java.net.URI$PartEncoder
 java.net.URL
 java.net.URLConnection
 java.net.URLConnection$DefaultContentHandler
 java.net.URLEncoder
+java.net.URLEncoder$1
 java.net.URLStreamHandler
 java.nio.BaseByteBuffer
 java.nio.Buffer
@@ -1182,11 +1491,9 @@
 java.nio.ReadWriteCharArrayBuffer
 java.nio.ReadWriteDirectByteBuffer
 java.nio.ReadWriteHeapByteBuffer
-java.nio.WriteOnlyFileChannel
 java.nio.channels.ByteChannel
 java.nio.channels.Channel
 java.nio.channels.FileChannel
-java.nio.channels.FileChannel$MapMode
 java.nio.channels.GatheringByteChannel
 java.nio.channels.InterruptibleChannel
 java.nio.channels.ReadableByteChannel
@@ -1195,54 +1502,83 @@
 java.nio.channels.spi.AbstractInterruptibleChannel
 java.nio.channels.spi.AbstractInterruptibleChannel$1
 java.nio.charset.Charset
-java.nio.charset.Charset$1
 java.nio.charset.CharsetDecoder
+java.nio.charset.CharsetDecoderICU
 java.nio.charset.CharsetEncoder
+java.nio.charset.CharsetEncoderICU
+java.nio.charset.CharsetICU
 java.nio.charset.Charsets
 java.nio.charset.CoderResult
 java.nio.charset.CodingErrorAction
 java.nio.charset.ModifiedUtf8
-java.security.AccessControlContext
 java.security.AccessController
 java.security.BasicPermission
+java.security.GeneralSecurityException
 java.security.Guard
 java.security.Key
+java.security.KeyFactory
+java.security.KeyFactorySpi
 java.security.KeyStore
-java.security.KeyStore$1
 java.security.KeyStoreSpi
+java.security.MessageDigest
+java.security.MessageDigestSpi
+java.security.NoSuchAlgorithmException
 java.security.Permission
 java.security.Principal
 java.security.PrivilegedAction
-java.security.PrivilegedExceptionAction
-java.security.ProtectionDomain
 java.security.Provider
 java.security.Provider$Service
-java.security.Provider$Service$1
+java.security.PublicKey
 java.security.SecureRandom
 java.security.SecureRandomSpi
 java.security.Security
-java.security.Security$1
 java.security.Security$SecurityDoor
+java.security.Signature
+java.security.Signature$SignatureImpl
+java.security.SignatureSpi
+java.security.cert.CertPath
 java.security.cert.CertPathParameters
 java.security.cert.CertPathValidator
+java.security.cert.CertPathValidatorResult
 java.security.cert.CertPathValidatorSpi
+java.security.cert.CertSelector
 java.security.cert.Certificate
 java.security.cert.CertificateFactory
 java.security.cert.CertificateFactorySpi
+java.security.cert.PKIXCertPathValidatorResult
 java.security.cert.PKIXParameters
+java.security.cert.PolicyNode
 java.security.cert.TrustAnchor
+java.security.cert.X509CertSelector
 java.security.cert.X509Certificate
 java.security.cert.X509Extension
+java.security.interfaces.DSAKey
+java.security.interfaces.DSAPublicKey
+java.security.interfaces.RSAKey
+java.security.interfaces.RSAPublicKey
+java.security.spec.EncodedKeySpec
 java.security.spec.KeySpec
+java.security.spec.RSAPublicKeySpec
+java.security.spec.X509EncodedKeySpec
+java.text.AttributedCharacterIterator$Attribute
+java.text.Bidi
+java.text.Bidi$Run
+java.text.BreakIterator
+java.text.CharacterIterator
 java.text.DateFormat
 java.text.DateFormatSymbols
 java.text.DecimalFormat
 java.text.DecimalFormat$1
 java.text.DecimalFormatSymbols
+java.text.FieldPosition
 java.text.Format
+java.text.Format$Field
 java.text.NumberFormat
+java.text.NumberFormat$Field
 java.text.ParsePosition
+java.text.RuleBasedBreakIterator
 java.text.SimpleDateFormat
+java.text.StringCharacterIterator
 java.util.AbstractCollection
 java.util.AbstractList
 java.util.AbstractList$FullListIterator
@@ -1256,10 +1592,11 @@
 java.util.ArrayList$ArrayListIterator
 java.util.Arrays
 java.util.Arrays$ArrayList
-java.util.BitSet
 java.util.Calendar
 java.util.Collection
 java.util.Collections
+java.util.Collections$1
+java.util.Collections$2
 java.util.Collections$EmptyList
 java.util.Collections$EmptyMap
 java.util.Collections$EmptySet
@@ -1277,7 +1614,6 @@
 java.util.Deque
 java.util.Dictionary
 java.util.EnumMap
-java.util.EnumSet
 java.util.Enumeration
 java.util.EventObject
 java.util.Formattable
@@ -1306,6 +1642,7 @@
 java.util.Hashtable$Values
 java.util.Iterator
 java.util.LinkedHashMap
+java.util.LinkedHashMap$EntryIterator
 java.util.LinkedHashMap$KeyIterator
 java.util.LinkedHashMap$LinkedEntry
 java.util.LinkedHashMap$LinkedHashIterator
@@ -1321,7 +1658,6 @@
 java.util.NavigableMap
 java.util.NavigableSet
 java.util.Properties
-java.util.PropertyPermission
 java.util.Queue
 java.util.Random
 java.util.RandomAccess
@@ -1341,6 +1677,8 @@
 java.util.TreeMap$Bound$3
 java.util.TreeMap$EntrySet
 java.util.TreeMap$EntrySet$1
+java.util.TreeMap$KeySet
+java.util.TreeMap$KeySet$1
 java.util.TreeMap$MapIterator
 java.util.TreeMap$Node
 java.util.TreeMap$Relation
@@ -1349,11 +1687,17 @@
 java.util.Vector$1
 java.util.WeakHashMap
 java.util.WeakHashMap$Entry
+java.util.WeakHashMap$Entry$Type
+java.util.WeakHashMap$HashIterator
 java.util.concurrent.AbstractExecutorService
 java.util.concurrent.BlockingQueue
 java.util.concurrent.Callable
+java.util.concurrent.ConcurrentHashMap
+java.util.concurrent.ConcurrentHashMap$HashEntry
+java.util.concurrent.ConcurrentHashMap$Segment
 java.util.concurrent.ConcurrentLinkedQueue
 java.util.concurrent.ConcurrentLinkedQueue$Node
+java.util.concurrent.ConcurrentMap
 java.util.concurrent.CopyOnWriteArrayList
 java.util.concurrent.CopyOnWriteArrayList$CowIterator
 java.util.concurrent.CountDownLatch
@@ -1400,6 +1744,7 @@
 java.util.concurrent.locks.ReentrantLock$NonfairSync
 java.util.concurrent.locks.ReentrantLock$Sync
 java.util.concurrent.locks.ReentrantReadWriteLock
+java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync
 java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock
 java.util.concurrent.locks.ReentrantReadWriteLock$Sync
 java.util.concurrent.locks.ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter
@@ -1420,9 +1765,6 @@
 java.util.logging.Level
 java.util.logging.LogManager
 java.util.logging.LogManager$1
-java.util.logging.LogManager$2
-java.util.logging.LogManager$2$1
-java.util.logging.LogManager$4
 java.util.logging.Logger
 java.util.logging.Logger$1
 java.util.logging.LoggingPermission
@@ -1437,12 +1779,13 @@
 java.util.zip.CRC32
 java.util.zip.Checksum
 java.util.zip.Deflater
+java.util.zip.GZIPInputStream
 java.util.zip.Inflater
 java.util.zip.InflaterInputStream
 java.util.zip.ZipConstants
 java.util.zip.ZipEntry
 java.util.zip.ZipFile
-java.util.zip.ZipFile$2
+java.util.zip.ZipFile$1
 java.util.zip.ZipFile$RAFStream
 java.util.zip.ZipFile$ZipInflaterInputStream
 javax.microedition.khronos.egl.EGL
@@ -1463,30 +1806,19 @@
 javax.net.ssl.HttpsURLConnection
 javax.net.ssl.KeyManager
 javax.net.ssl.KeyManagerFactory
-javax.net.ssl.KeyManagerFactory$1
 javax.net.ssl.KeyManagerFactorySpi
 javax.net.ssl.SSLContextSpi
+javax.net.ssl.SSLSession
 javax.net.ssl.SSLSessionContext
 javax.net.ssl.SSLSocket
 javax.net.ssl.SSLSocketFactory
-javax.net.ssl.SSLSocketFactory$1
 javax.net.ssl.TrustManager
 javax.net.ssl.TrustManagerFactory
-javax.net.ssl.TrustManagerFactory$1
 javax.net.ssl.TrustManagerFactorySpi
 javax.net.ssl.X509ExtendedKeyManager
 javax.net.ssl.X509KeyManager
 javax.net.ssl.X509TrustManager
 javax.security.auth.x500.X500Principal
-libcore.base.CollectionUtils
-libcore.base.CollectionUtils$1
-libcore.base.CollectionUtils$1$1
-libcore.base.EmptyArray
-libcore.base.Objects
-libcore.base.Streams
-libcore.icu.CharsetDecoderICU
-libcore.icu.CharsetEncoderICU
-libcore.icu.CharsetICU
 libcore.icu.ErrorCode
 libcore.icu.ICU
 libcore.icu.LocaleData
@@ -1499,59 +1831,82 @@
 libcore.icu.NativeNormalizer
 libcore.icu.NativePluralRules
 libcore.icu.TimeZones
-libcore.icu.TimeZones$CachedTimeZones
+libcore.internal.StringPool
+libcore.io.AsynchronousCloseMonitor
+libcore.io.Base64
+libcore.io.BlockGuardOs
 libcore.io.BufferIterator
+libcore.io.ErrnoException
+libcore.io.ForwardingOs
+libcore.io.GaiException
 libcore.io.HeapBufferIterator
+libcore.io.IoBridge
 libcore.io.IoUtils
+libcore.io.Libcore
+libcore.io.Memory
 libcore.io.MemoryMappedFile
 libcore.io.NioBufferIterator
-libcore.math.MathUtils
+libcore.io.Os
+libcore.io.OsConstants
+libcore.io.Posix
+libcore.io.Streams
+libcore.io.StructAddrinfo
+libcore.io.StructFlock
+libcore.io.StructGroupReq
+libcore.io.StructLinger
+libcore.io.StructPasswd
+libcore.io.StructPollfd
+libcore.io.StructStat
+libcore.io.StructStatFs
+libcore.io.StructTimeval
+libcore.io.StructUtsname
 libcore.net.MimeUtils
 libcore.net.RawSocket
+libcore.net.UriCodec
+libcore.net.url.FileHandler
+libcore.net.url.FileURLConnection
+libcore.net.url.JarHandler
+libcore.net.url.JarURLConnectionImpl
+libcore.net.url.JarURLConnectionImpl$JarURLConnectionInputStream
+libcore.net.url.UrlUtils
+libcore.util.BasicLruCache
+libcore.util.CollectionUtils
+libcore.util.CollectionUtils$1
+libcore.util.CollectionUtils$1$1
+libcore.util.EmptyArray
+libcore.util.MutableInt
+libcore.util.MutableLong
+libcore.util.Objects
+libcore.util.ZoneInfo
+libcore.util.ZoneInfoDB
 org.apache.commons.logging.Log
 org.apache.commons.logging.LogFactory
 org.apache.commons.logging.impl.Jdk14Logger
 org.apache.commons.logging.impl.WeakHashtable
-org.apache.harmony.archive.util.Util
 org.apache.harmony.dalvik.NativeTestTarget
 org.apache.harmony.dalvik.ddmc.Chunk
 org.apache.harmony.dalvik.ddmc.ChunkHandler
 org.apache.harmony.dalvik.ddmc.DdmServer
-org.apache.harmony.kernel.vm.LangAccess
-org.apache.harmony.kernel.vm.ReflectionAccess
 org.apache.harmony.lang.annotation.AnnotationFactory
 org.apache.harmony.lang.annotation.AnnotationMember
-org.apache.harmony.luni.internal.net.www.protocol.file.FileURLConnection
-org.apache.harmony.luni.internal.net.www.protocol.file.Handler
-org.apache.harmony.luni.internal.net.www.protocol.jar.Handler
-org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnectionImpl
-org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnectionImpl$JarURLConnectionInputStream
 org.apache.harmony.luni.internal.util.TimezoneGetter
-org.apache.harmony.luni.internal.util.ZoneInfo
-org.apache.harmony.luni.internal.util.ZoneInfoDB
-org.apache.harmony.luni.net.PlainSocketImpl
-org.apache.harmony.luni.net.SocketInputStream
-org.apache.harmony.luni.net.SocketOutputStream
-org.apache.harmony.luni.platform.IFileSystem
-org.apache.harmony.luni.platform.INetworkSystem
-org.apache.harmony.luni.platform.OSFileSystem
-org.apache.harmony.luni.platform.OSMemory
-org.apache.harmony.luni.platform.OSNetworkSystem
-org.apache.harmony.luni.platform.Platform
-org.apache.harmony.luni.util.FloatingPointParser
-org.apache.harmony.luni.util.FloatingPointParser$StringExponentPair
-org.apache.harmony.luni.util.PriviAction
 org.apache.harmony.luni.util.TwoKeyHashMap
 org.apache.harmony.luni.util.TwoKeyHashMap$Entry
 org.apache.harmony.luni.util.TwoKeyHashMap$EntryIteratorImpl
 org.apache.harmony.luni.util.TwoKeyHashMap$ValueIteratorImpl
 org.apache.harmony.luni.util.TwoKeyHashMap$ValuesCollectionImpl
-org.apache.harmony.luni.util.Util
-org.apache.harmony.security.Util
 org.apache.harmony.security.asn1.ASN1Any
+org.apache.harmony.security.asn1.ASN1BitString
+org.apache.harmony.security.asn1.ASN1BitString$ASN1NamedBitList
+org.apache.harmony.security.asn1.ASN1Boolean
 org.apache.harmony.security.asn1.ASN1Choice
 org.apache.harmony.security.asn1.ASN1Constants
-org.apache.harmony.security.asn1.ASN1Constructured
+org.apache.harmony.security.asn1.ASN1Constructed
+org.apache.harmony.security.asn1.ASN1Explicit
+org.apache.harmony.security.asn1.ASN1GeneralizedTime
+org.apache.harmony.security.asn1.ASN1Implicit
+org.apache.harmony.security.asn1.ASN1Integer
+org.apache.harmony.security.asn1.ASN1OctetString
 org.apache.harmony.security.asn1.ASN1Oid
 org.apache.harmony.security.asn1.ASN1Oid$1
 org.apache.harmony.security.asn1.ASN1Primitive
@@ -1566,26 +1921,34 @@
 org.apache.harmony.security.asn1.ASN1StringType$5
 org.apache.harmony.security.asn1.ASN1StringType$6
 org.apache.harmony.security.asn1.ASN1StringType$7
+org.apache.harmony.security.asn1.ASN1Time
 org.apache.harmony.security.asn1.ASN1Type
 org.apache.harmony.security.asn1.ASN1TypeCollection
+org.apache.harmony.security.asn1.ASN1UTCTime
 org.apache.harmony.security.asn1.ASN1ValueCollection
 org.apache.harmony.security.asn1.BerInputStream
+org.apache.harmony.security.asn1.BerOutputStream
+org.apache.harmony.security.asn1.BitString
 org.apache.harmony.security.asn1.DerInputStream
+org.apache.harmony.security.asn1.DerOutputStream
+org.apache.harmony.security.asn1.ObjectIdentifier
 org.apache.harmony.security.fortress.Engine
 org.apache.harmony.security.fortress.Engine$ServiceCacheEntry
 org.apache.harmony.security.fortress.Engine$SpiAndProvider
 org.apache.harmony.security.fortress.SecurityAccess
-org.apache.harmony.security.fortress.SecurityUtils
 org.apache.harmony.security.fortress.Services
-org.apache.harmony.security.fortress.Services$1
+org.apache.harmony.security.pkcs7.ContentInfo
+org.apache.harmony.security.pkcs7.ContentInfo$1
 org.apache.harmony.security.provider.cert.Cache
 org.apache.harmony.security.provider.cert.DRLCertFactory
-org.apache.harmony.security.provider.cert.DRLCertFactory$1
 org.apache.harmony.security.provider.cert.X509CertFactoryImpl
+org.apache.harmony.security.provider.cert.X509CertImpl
+org.apache.harmony.security.provider.cert.X509CertPathImpl
+org.apache.harmony.security.provider.cert.X509CertPathImpl$1
+org.apache.harmony.security.provider.cert.X509CertPathImpl$2
+org.apache.harmony.security.provider.cert.X509CertPathImpl$3
 org.apache.harmony.security.provider.crypto.CryptoProvider
-org.apache.harmony.security.provider.crypto.CryptoProvider$1
 org.apache.harmony.security.provider.crypto.RandomBitsSupplier
-org.apache.harmony.security.provider.crypto.RandomBitsSupplier$1
 org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl
 org.apache.harmony.security.provider.crypto.SHA1_Data
 org.apache.harmony.security.utils.AlgNameMapper
@@ -1599,53 +1962,89 @@
 org.apache.harmony.security.x501.DirectoryString$1
 org.apache.harmony.security.x501.Name
 org.apache.harmony.security.x501.Name$1
+org.apache.harmony.security.x509.AlgorithmIdentifier
+org.apache.harmony.security.x509.AlgorithmIdentifier$1
+org.apache.harmony.security.x509.BasicConstraints
+org.apache.harmony.security.x509.BasicConstraints$1
+org.apache.harmony.security.x509.Certificate
+org.apache.harmony.security.x509.Certificate$1
+org.apache.harmony.security.x509.EDIPartyName
+org.apache.harmony.security.x509.EDIPartyName$1
+org.apache.harmony.security.x509.Extension
+org.apache.harmony.security.x509.Extension$1
+org.apache.harmony.security.x509.Extension$2
+org.apache.harmony.security.x509.ExtensionValue
+org.apache.harmony.security.x509.Extensions
+org.apache.harmony.security.x509.Extensions$1
 org.apache.harmony.security.x509.GeneralName
-org.apache.harmony.text.BidiRun
-org.apache.harmony.text.NativeBidi
+org.apache.harmony.security.x509.GeneralName$1
+org.apache.harmony.security.x509.GeneralNames
+org.apache.harmony.security.x509.GeneralNames$1
+org.apache.harmony.security.x509.KeyUsage
+org.apache.harmony.security.x509.ORAddress
+org.apache.harmony.security.x509.ORAddress$1
+org.apache.harmony.security.x509.ORAddress$2
+org.apache.harmony.security.x509.OtherName
+org.apache.harmony.security.x509.OtherName$1
+org.apache.harmony.security.x509.SubjectPublicKeyInfo
+org.apache.harmony.security.x509.SubjectPublicKeyInfo$1
+org.apache.harmony.security.x509.TBSCertificate
+org.apache.harmony.security.x509.TBSCertificate$1
+org.apache.harmony.security.x509.Time
+org.apache.harmony.security.x509.Time$1
+org.apache.harmony.security.x509.Validity
+org.apache.harmony.security.x509.Validity$1
 org.apache.harmony.xml.ExpatAttributes
 org.apache.harmony.xml.ExpatParser
-org.apache.harmony.xml.ExpatParser$ClonedAttributes
-org.apache.harmony.xml.ExpatParser$CurrentAttributes
-org.apache.harmony.xml.ExpatParser$ExpatLocator
-org.apache.harmony.xml.ExpatPullParser
-org.apache.harmony.xml.ExpatPullParser$ByteDocument
-org.apache.harmony.xml.ExpatPullParser$Document
-org.apache.harmony.xml.ExpatPullParser$Document$SaxHandler
-org.apache.harmony.xml.ExpatPullParser$EndTagEvent
-org.apache.harmony.xml.ExpatPullParser$Event
-org.apache.harmony.xml.ExpatPullParser$NamespaceStack
-org.apache.harmony.xml.ExpatPullParser$NamespaceStack$Builder
-org.apache.harmony.xml.ExpatPullParser$StartDocumentEvent
-org.apache.harmony.xml.ExpatPullParser$StartTagEvent
-org.apache.harmony.xml.ExpatPullParser$TextEvent
-org.apache.harmony.xml.ExpatReader
 org.apache.harmony.xnet.provider.jsse.AbstractSessionContext
 org.apache.harmony.xnet.provider.jsse.AbstractSessionContext$1
+org.apache.harmony.xnet.provider.jsse.ByteArray
 org.apache.harmony.xnet.provider.jsse.ClientSessionContext
+org.apache.harmony.xnet.provider.jsse.ClientSessionContext$HostAndPort
 org.apache.harmony.xnet.provider.jsse.DefaultSSLContextImpl
-org.apache.harmony.xnet.provider.jsse.IndexedPKIXParameters
+org.apache.harmony.xnet.provider.jsse.FileClientSessionCache
+org.apache.harmony.xnet.provider.jsse.FileClientSessionCache$Impl
 org.apache.harmony.xnet.provider.jsse.JSSEProvider
-org.apache.harmony.xnet.provider.jsse.JSSEProvider$1
 org.apache.harmony.xnet.provider.jsse.KeyManagerFactoryImpl
-org.apache.harmony.xnet.provider.jsse.KeyManagerFactoryImpl$1
 org.apache.harmony.xnet.provider.jsse.KeyManagerImpl
 org.apache.harmony.xnet.provider.jsse.NativeCrypto
 org.apache.harmony.xnet.provider.jsse.NativeCrypto$SSLHandshakeCallbacks
 org.apache.harmony.xnet.provider.jsse.OpenSSLContextImpl
+org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK
+org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$MD5
+org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA1
 org.apache.harmony.xnet.provider.jsse.OpenSSLProvider
+org.apache.harmony.xnet.provider.jsse.OpenSSLSessionImpl
+org.apache.harmony.xnet.provider.jsse.OpenSSLSignature
+org.apache.harmony.xnet.provider.jsse.OpenSSLSignature$MD5RSA
+org.apache.harmony.xnet.provider.jsse.OpenSSLSignature$SHA1DSA
+org.apache.harmony.xnet.provider.jsse.OpenSSLSignature$SHA1RSA
+org.apache.harmony.xnet.provider.jsse.OpenSSLSignature$SHA256RSA
+org.apache.harmony.xnet.provider.jsse.OpenSSLSignature$SHA384RSA
+org.apache.harmony.xnet.provider.jsse.OpenSSLSignature$SHA512RSA
 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketFactoryImpl
 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl
+org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream
+org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLOutputStream
+org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImplWrapper
 org.apache.harmony.xnet.provider.jsse.ProtocolVersion
+org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache
 org.apache.harmony.xnet.provider.jsse.SSLContextImpl
 org.apache.harmony.xnet.provider.jsse.SSLParametersImpl
 org.apache.harmony.xnet.provider.jsse.ServerSessionContext
 org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl
-org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl$1
-org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl$2
 org.apache.harmony.xnet.provider.jsse.TrustManagerImpl
+org.apache.harmony.xnet.provider.jsse.TrustedCertificateIndex
+org.apache.harmony.xnet.provider.jsse.TrustedCertificateKeyStoreSpi
+org.apache.harmony.xnet.provider.jsse.TrustedCertificateStore
+org.apache.harmony.xnet.provider.jsse.TrustedCertificateStore$1
+org.apache.harmony.xnet.provider.jsse.TrustedCertificateStore$2
+org.apache.harmony.xnet.provider.jsse.TrustedCertificateStore$3
+org.apache.harmony.xnet.provider.jsse.TrustedCertificateStore$CertSelector
 org.apache.http.ConnectionReuseStrategy
 org.apache.http.FormattedHeader
 org.apache.http.Header
+org.apache.http.HeaderElement
 org.apache.http.HeaderElementIterator
 org.apache.http.HeaderIterator
 org.apache.http.HttpClientConnection
@@ -1662,6 +2061,7 @@
 org.apache.http.HttpResponseFactory
 org.apache.http.HttpResponseInterceptor
 org.apache.http.HttpVersion
+org.apache.http.NameValuePair
 org.apache.http.ProtocolVersion
 org.apache.http.ReasonPhraseCatalog
 org.apache.http.RequestLine
@@ -1678,6 +2078,9 @@
 org.apache.http.client.ResponseHandler
 org.apache.http.client.UserTokenHandler
 org.apache.http.client.methods.AbortableHttpRequest
+org.apache.http.client.methods.HttpEntityEnclosingRequestBase
+org.apache.http.client.methods.HttpGet
+org.apache.http.client.methods.HttpPost
 org.apache.http.client.methods.HttpRequestBase
 org.apache.http.client.methods.HttpUriRequest
 org.apache.http.client.params.HttpClientParams
@@ -1701,6 +2104,7 @@
 org.apache.http.conn.params.ConnManagerParams
 org.apache.http.conn.params.ConnManagerParams$1
 org.apache.http.conn.params.ConnPerRoute
+org.apache.http.conn.params.ConnPerRouteBean
 org.apache.http.conn.params.ConnRoutePNames
 org.apache.http.conn.params.ConnRouteParams
 org.apache.http.conn.routing.BasicRouteDirector
@@ -1727,6 +2131,7 @@
 org.apache.http.cookie.CookieSpecRegistry
 org.apache.http.entity.AbstractHttpEntity
 org.apache.http.entity.BasicHttpEntity
+org.apache.http.entity.ByteArrayEntity
 org.apache.http.entity.ContentLengthStrategy
 org.apache.http.entity.HttpEntityWrapper
 org.apache.http.impl.AbstractHttpClientConnection
@@ -1749,6 +2154,7 @@
 org.apache.http.impl.client.DefaultRequestDirector
 org.apache.http.impl.client.DefaultTargetAuthenticationHandler
 org.apache.http.impl.client.DefaultUserTokenHandler
+org.apache.http.impl.client.EntityEnclosingRequestWrapper
 org.apache.http.impl.client.RequestWrapper
 org.apache.http.impl.client.RoutedRequest
 org.apache.http.impl.conn.AbstractClientConnAdapter
@@ -1787,7 +2193,9 @@
 org.apache.http.impl.io.AbstractMessageWriter
 org.apache.http.impl.io.AbstractSessionInputBuffer
 org.apache.http.impl.io.AbstractSessionOutputBuffer
+org.apache.http.impl.io.ChunkedInputStream
 org.apache.http.impl.io.ContentLengthInputStream
+org.apache.http.impl.io.ContentLengthOutputStream
 org.apache.http.impl.io.HttpRequestWriter
 org.apache.http.impl.io.HttpTransportMetricsImpl
 org.apache.http.impl.io.SocketInputBuffer
@@ -1799,12 +2207,14 @@
 org.apache.http.io.SessionOutputBuffer
 org.apache.http.message.AbstractHttpMessage
 org.apache.http.message.BasicHeader
+org.apache.http.message.BasicHeaderElement
 org.apache.http.message.BasicHeaderElementIterator
 org.apache.http.message.BasicHeaderValueParser
 org.apache.http.message.BasicHttpResponse
 org.apache.http.message.BasicLineFormatter
 org.apache.http.message.BasicLineParser
 org.apache.http.message.BasicListHeaderIterator
+org.apache.http.message.BasicNameValuePair
 org.apache.http.message.BasicRequestLine
 org.apache.http.message.BasicStatusLine
 org.apache.http.message.BufferedHeader
@@ -1836,99 +2246,17 @@
 org.apache.http.util.ByteArrayBuffer
 org.apache.http.util.CharArrayBuffer
 org.apache.http.util.LangUtils
-com.android.org.bouncycastle.asn1.ASN1Choice
-com.android.org.bouncycastle.asn1.ASN1Collection
-com.android.org.bouncycastle.asn1.ASN1Collection$ASN1CollectionEnumeration
-com.android.org.bouncycastle.asn1.ASN1Encodable
-com.android.org.bouncycastle.asn1.ASN1EncodableVector
-com.android.org.bouncycastle.asn1.ASN1InputStream
-com.android.org.bouncycastle.asn1.ASN1Null
-com.android.org.bouncycastle.asn1.ASN1Object
-com.android.org.bouncycastle.asn1.ASN1OctetString
-com.android.org.bouncycastle.asn1.ASN1OctetStringParser
-com.android.org.bouncycastle.asn1.ASN1OutputStream
-com.android.org.bouncycastle.asn1.ASN1Sequence
-com.android.org.bouncycastle.asn1.ASN1SequenceParser
-com.android.org.bouncycastle.asn1.ASN1Set
-com.android.org.bouncycastle.asn1.ASN1StreamParser
-com.android.org.bouncycastle.asn1.ASN1TaggedObject
-com.android.org.bouncycastle.asn1.ASN1TaggedObjectParser
-com.android.org.bouncycastle.asn1.BERTaggedObjectParser
-com.android.org.bouncycastle.asn1.DERBitString
-com.android.org.bouncycastle.asn1.DERBoolean
-com.android.org.bouncycastle.asn1.DEREncodable
-com.android.org.bouncycastle.asn1.DEREncodableVector
-com.android.org.bouncycastle.asn1.DERFactory
-com.android.org.bouncycastle.asn1.DERIA5String
-com.android.org.bouncycastle.asn1.DERInteger
-com.android.org.bouncycastle.asn1.DERNull
-com.android.org.bouncycastle.asn1.DERObject
-com.android.org.bouncycastle.asn1.DERObjectIdentifier
-com.android.org.bouncycastle.asn1.DEROctetString
-com.android.org.bouncycastle.asn1.DEROctetStringParser
-com.android.org.bouncycastle.asn1.DEROutputStream
-com.android.org.bouncycastle.asn1.DERPrintableString
-com.android.org.bouncycastle.asn1.DERSequence
-com.android.org.bouncycastle.asn1.DERSequenceParser
-com.android.org.bouncycastle.asn1.DERSet
-com.android.org.bouncycastle.asn1.DERString
-com.android.org.bouncycastle.asn1.DERT61String
-com.android.org.bouncycastle.asn1.DERTaggedObject
-com.android.org.bouncycastle.asn1.DERTags
-com.android.org.bouncycastle.asn1.DERUTCTime
-com.android.org.bouncycastle.asn1.DERUTF8String
-com.android.org.bouncycastle.asn1.DERUniversalString
-com.android.org.bouncycastle.asn1.DefiniteLengthInputStream
-com.android.org.bouncycastle.asn1.IndefiniteLengthInputStream
-com.android.org.bouncycastle.asn1.LimitedInputStream
-com.android.org.bouncycastle.asn1.OIDTokenizer
-com.android.org.bouncycastle.asn1.OrderedTable
-com.android.org.bouncycastle.asn1.bc.BCObjectIdentifiers
-com.android.org.bouncycastle.asn1.iana.IANAObjectIdentifiers
-com.android.org.bouncycastle.asn1.nist.NISTObjectIdentifiers
-com.android.org.bouncycastle.asn1.oiw.OIWObjectIdentifiers
-com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers
-com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier
-com.android.org.bouncycastle.asn1.x509.BasicConstraints
-com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
-com.android.org.bouncycastle.asn1.x509.TBSCertificateStructure
-com.android.org.bouncycastle.asn1.x509.Time
-com.android.org.bouncycastle.asn1.x509.X509CertificateStructure
-com.android.org.bouncycastle.asn1.x509.X509Extension
-com.android.org.bouncycastle.asn1.x509.X509Extensions
-com.android.org.bouncycastle.asn1.x509.X509Name
-com.android.org.bouncycastle.asn1.x509.X509NameElementList
-com.android.org.bouncycastle.asn1.x509.X509ObjectIdentifiers
-com.android.org.bouncycastle.asn1.x9.X9ObjectIdentifiers
-com.android.org.bouncycastle.crypto.Digest
-com.android.org.bouncycastle.crypto.ExtendedDigest
-com.android.org.bouncycastle.crypto.Mac
-com.android.org.bouncycastle.crypto.digests.OpenSSLDigest
-com.android.org.bouncycastle.crypto.digests.OpenSSLDigest$MD5
-com.android.org.bouncycastle.crypto.digests.OpenSSLDigest$SHA1
-com.android.org.bouncycastle.crypto.macs.HMac
-com.android.org.bouncycastle.jce.ProviderConfigurationPermission
-com.android.org.bouncycastle.jce.interfaces.BCKeyStore
-com.android.org.bouncycastle.jce.interfaces.ConfigurableProvider
-com.android.org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier
-com.android.org.bouncycastle.jce.provider.BouncyCastleProvider
-com.android.org.bouncycastle.jce.provider.BouncyCastleProvider$1
-com.android.org.bouncycastle.jce.provider.JDKKeyStore
-com.android.org.bouncycastle.jce.provider.JDKKeyStore$StoreEntry
-com.android.org.bouncycastle.jce.provider.JDKX509CertificateFactory
-com.android.org.bouncycastle.jce.provider.PEMUtil
-com.android.org.bouncycastle.jce.provider.PKCS12BagAttributeCarrierImpl
-com.android.org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi
-com.android.org.bouncycastle.jce.provider.ProviderUtil
-com.android.org.bouncycastle.jce.provider.X509CertificateObject
-com.android.org.bouncycastle.jce.provider.asymmetric.ECMappings
-com.android.org.bouncycastle.jce.provider.symmetric.AESMappings
-com.android.org.bouncycastle.util.Strings
-com.android.org.bouncycastle.util.io.Streams
+org.kxml2.io.KXmlParser
+org.kxml2.io.KXmlParser$ValueContext
 org.xml.sax.Attributes
 org.xml.sax.ContentHandler
+org.xml.sax.DTDHandler
+org.xml.sax.EntityResolver
+org.xml.sax.ErrorHandler
+org.xml.sax.InputSource
 org.xml.sax.Locator
 org.xml.sax.XMLReader
+org.xml.sax.helpers.DefaultHandler
 org.xmlpull.v1.XmlPullParser
 org.xmlpull.v1.XmlSerializer
 sun.misc.Unsafe
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 643866b..bfcf8e0 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -2188,6 +2188,7 @@
     }
     nsecs_t downTime = mDownTime;
     bool buttonsChanged = currentButtonState != lastButtonState;
+    bool buttonsPressed = currentButtonState & ~lastButtonState;
 
     float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
     float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
@@ -2249,7 +2250,7 @@
     // the device in your pocket.
     // TODO: Use the input device configuration to control this behavior more finely.
     uint32_t policyFlags = 0;
-    if (getDevice()->isExternal()) {
+    if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
         policyFlags |= POLICY_FLAG_WAKE_DROPPED;
     }
 
@@ -3345,9 +3346,12 @@
 
         // Handle policy on initial down or hover events.
         uint32_t policyFlags = 0;
-        if (mLastRawPointerData.pointerCount == 0 && mCurrentRawPointerData.pointerCount != 0) {
+        bool initialDown = mLastRawPointerData.pointerCount == 0
+                && mCurrentRawPointerData.pointerCount != 0;
+        bool buttonsPressed = mCurrentButtonState & ~mLastButtonState;
+        if (initialDown || buttonsPressed) {
+            // If this is a touch screen, hide the pointer on an initial down.
             if (mDeviceMode == DEVICE_MODE_DIRECT) {
-                // If this is a touch screen, hide the pointer on an initial down.
                 getContext()->fadePointer();
             }
 
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 5e54d61..5ffcdc50 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -764,12 +764,18 @@
         
         public void scheduleTimeTickEvent() {
             Calendar calendar = Calendar.getInstance();
-            calendar.setTimeInMillis(System.currentTimeMillis());
+            final long currentTime = System.currentTimeMillis();
+            calendar.setTimeInMillis(currentTime);
             calendar.add(Calendar.MINUTE, 1);
             calendar.set(Calendar.SECOND, 0);
             calendar.set(Calendar.MILLISECOND, 0);
-      
-            set(AlarmManager.RTC, calendar.getTimeInMillis(), mTimeTickSender);
+
+            // Schedule this event for the amount of time that it would take to get to
+            // the top of the next minute.
+            final long tickEventDelay = calendar.getTimeInMillis() - currentTime;
+
+            set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay,
+                    mTimeTickSender);
         }
 	
         public void scheduleDateChangedEvent() {
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 6b64dd0..38bcebc 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -619,10 +619,7 @@
     }
 
     void updateImeWindowStatusLocked() {
-        if (mStatusBar != null) {
-            mStatusBar.setImeWindowStatus(mCurToken, mImeWindowVis,
-                    mBackDisposition);
-        }
+        setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition);
     }
 
     @Override
@@ -995,6 +992,8 @@
                 sessionState.session.finishSession();
             } catch (RemoteException e) {
                 Slog.w(TAG, "Session failed to close due to remote exception", e);
+                mImeWindowVis = 0;
+                updateImeWindowStatusLocked();
             }
         }
     }
@@ -1121,6 +1120,7 @@
         }
     }
 
+    @SuppressWarnings("deprecation")
     @Override
     public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
         int uid = Binder.getCallingUid();
@@ -2018,8 +2018,9 @@
         if (DEBUG) Slog.v(TAG, "Show switching menu");
 
         final Context context = mContext;
-
         final PackageManager pm = context.getPackageManager();
+        final boolean isScreenLocked = mKeyguardManager != null
+                && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure();
 
         String lastInputMethodId = Settings.Secure.getString(context
                 .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
@@ -2075,7 +2076,7 @@
                         final String subtypeHashCode = String.valueOf(subtype.hashCode());
                         // We show all enabled IMEs and subtypes when an IME is shown.
                         if (enabledSubtypeSet.contains(subtypeHashCode)
-                                && (mInputShown || !subtype.isAuxiliary())) {
+                                && ((mInputShown && !isScreenLocked) || !subtype.isAuxiliary())) {
                             final CharSequence title;
                             final String mode = subtype.getMode();
                             title = TextUtils.concat(subtype.getDisplayName(context,
@@ -2162,8 +2163,7 @@
                         }
                     });
 
-            if (showSubtypes && mKeyguardManager != null && !(mKeyguardManager.isKeyguardLocked()
-                    && mKeyguardManager.isKeyguardSecure())) {
+            if (showSubtypes && !isScreenLocked) {
                 mDialogBuilder.setPositiveButton(
                         com.android.internal.R.string.configure_input_methods,
                         new DialogInterface.OnClickListener() {
@@ -2591,6 +2591,7 @@
     }
 
     // TODO: We should change the return type from List to List<Parcelable>
+    @SuppressWarnings("rawtypes")
     @Override
     public List getShortcutInputMethodsAndSubtypes() {
         synchronized (mMethodMap) {
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 06077dd..e72d09f 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -69,7 +69,8 @@
 /**
  * @hide
  */
-class NetworkManagementService extends INetworkManagementService.Stub implements Watchdog.Monitor {
+public class NetworkManagementService extends INetworkManagementService.Stub
+        implements Watchdog.Monitor {
     private static final String TAG = "NetworkManagementService";
     private static final boolean DBG = false;
     private static final String NETD_TAG = "NetdConnector";
@@ -87,6 +88,12 @@
     /** Path to {@code /proc/net/xt_qtaguid/iface_stat}. */
     private final File mStatsXtIface;
 
+    /**
+     * Name representing {@link #setGlobalAlert(long)} limit when delivered to
+     * {@link INetworkManagementEventObserver#limitReached(String, String)}.
+     */
+    public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
+
     /** {@link #mStatsXtUid} headers. */
     private static final String KEY_IFACE = "iface";
     private static final String KEY_UID = "uid_tag_int";
@@ -1056,8 +1063,12 @@
                     Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
                 }
             }
+        } catch (NullPointerException e) {
+            throw new IllegalStateException("problem parsing stats: " + e);
+        } catch (NumberFormatException e) {
+            throw new IllegalStateException("problem parsing stats: " + e);
         } catch (IOException e) {
-            Slog.w(TAG, "problem parsing stats: " + e);
+            throw new IllegalStateException("problem parsing stats: " + e);
         } finally {
             IoUtils.closeQuietly(reader);
         }
@@ -1338,8 +1349,12 @@
                     Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
                 }
             }
+        } catch (NullPointerException e) {
+            throw new IllegalStateException("problem parsing stats: " + e);
+        } catch (NumberFormatException e) {
+            throw new IllegalStateException("problem parsing stats: " + e);
         } catch (IOException e) {
-            Slog.w(TAG, "problem parsing stats: " + e);
+            throw new IllegalStateException("problem parsing stats: " + e);
         } finally {
             IoUtils.closeQuietly(reader);
         }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e6f92a5..d0e8b5e 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -182,7 +182,7 @@
 
             // only initialize the power service after we have started the
             // lights service, content providers and the battery service.
-            power.init(context, lights, ActivityManagerService.getDefault(), battery);
+            power.init(context, lights, ActivityManagerService.self(), battery);
 
             Slog.i(TAG, "Alarm Manager");
             alarm = new AlarmManagerService(context);
@@ -197,8 +197,7 @@
                     factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL);
             ServiceManager.addService(Context.WINDOW_SERVICE, wm);
 
-            ((ActivityManagerService)ServiceManager.getService("activity"))
-                    .setWindowManager(wm);
+            ActivityManagerService.self().setWindowManager(wm);
 
             // Skip Bluetooth if we have an emulator kernel
             // TODO: Use a more reliable check to see if this product should
@@ -265,7 +264,7 @@
         } catch (Throwable e) {
             reportWtf("making display ready", e);
         }
- 
+
         try {
             pm.performBootDexOpt();
         } catch (Throwable e) {
@@ -618,8 +617,7 @@
         // where third party code can really run (but before it has actually
         // started launching the initial applications), for us to complete our
         // initialization.
-        ((ActivityManagerService)ActivityManagerNative.getDefault())
-                .systemReady(new Runnable() {
+        ActivityManagerService.self().systemReady(new Runnable() {
             public void run() {
                 Slog.i(TAG, "Making services ready");
 
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index dd54c16..4447ad0 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -421,11 +421,13 @@
                 modified = true;
             }
             if (modified) {
-                Slog.d(TAG, "onDataConnectionStateChanged(" + state + ", " + networkType + ")");
+                Slog.d(TAG, "onDataConnectionStateChanged(" + mDataConnectionState
+                        + ", " + mDataConnectionNetworkType + ")");
                 for (Record r : mRecords) {
                     if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
                         try {
-                            r.callback.onDataConnectionStateChanged(state, networkType);
+                            r.callback.onDataConnectionStateChanged(mDataConnectionState,
+                                    mDataConnectionNetworkType);
                         } catch (RemoteException ex) {
                             mRemoveList.add(r.binder);
                         }
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index 18ddabd11..f6c369e 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -131,6 +131,11 @@
             if (DBG) Slog.d(TAG, "Add: " + compName);
             try {
                 final SpellCheckerInfo sci = new SpellCheckerInfo(context, ri);
+                if (sci.getSubtypeCount() <= 0) {
+                    Slog.w(TAG, "Skipping text service " + compName
+                            + ": it does not contain subtypes.");
+                    continue;
+                }
                 list.add(sci);
                 map.put(sci.getId(), sci);
             } catch (XmlPullParserException e) {
@@ -173,7 +178,7 @@
     @Override
     public SpellCheckerInfo getCurrentSpellChecker(String locale) {
         synchronized (mSpellCheckerMap) {
-            String curSpellCheckerId =
+            final String curSpellCheckerId =
                     Settings.Secure.getString(mContext.getContentResolver(),
                             Settings.Secure.SELECTED_SPELL_CHECKER);
             if (DBG) {
@@ -186,9 +191,11 @@
         }
     }
 
+    // TODO: Respect allowImplicitlySelectedSubtype
     // TODO: Save SpellCheckerSubtype by supported languages.
     @Override
-    public SpellCheckerSubtype getCurrentSpellCheckerSubtype(String locale) {
+    public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
+            String locale, boolean allowImplicitlySelectedSubtype) {
         synchronized (mSpellCheckerMap) {
             final String subtypeHashCodeStr =
                     Settings.Secure.getString(mContext.getContentResolver(),
@@ -197,21 +204,46 @@
                 Slog.w(TAG, "getCurrentSpellChecker: " + subtypeHashCodeStr);
             }
             final SpellCheckerInfo sci = getCurrentSpellChecker(null);
-            if (sci.getSubtypeCount() == 0) {
+            if (sci == null || sci.getSubtypeCount() == 0) {
+                if (DBG) {
+                    Slog.w(TAG, "Subtype not found.");
+                }
                 return null;
             }
-            if (TextUtils.isEmpty(subtypeHashCodeStr)) {
-                // Return the first Subtype if there is no settings for the current subtype.
-                return sci.getSubtypeAt(0);
+            final int hashCode;
+            if (!TextUtils.isEmpty(subtypeHashCodeStr)) {
+                hashCode = Integer.valueOf(subtypeHashCodeStr);
+            } else {
+                hashCode = 0;
             }
-            final int hashCode = Integer.valueOf(subtypeHashCodeStr);
+            if (hashCode == 0 && !allowImplicitlySelectedSubtype) {
+                return null;
+            }
+            final String systemLocale =
+                    mContext.getResources().getConfiguration().locale.toString();
+            SpellCheckerSubtype candidate = null;
             for (int i = 0; i < sci.getSubtypeCount(); ++i) {
                 final SpellCheckerSubtype scs = sci.getSubtypeAt(i);
-                if (scs.hashCode() == hashCode) {
+                if (hashCode == 0) {
+                    if (systemLocale.equals(locale)) {
+                        return scs;
+                    } else if (candidate == null) {
+                        final String scsLocale = scs.getLocale();
+                        if (systemLocale.length() >= 2
+                                && scsLocale.length() >= 2
+                                && systemLocale.substring(0, 2).equals(
+                                        scsLocale.substring(0, 2))) {
+                            candidate = scs;
+                        }
+                    }
+                } else if (scs.hashCode() == hashCode) {
+                    if (DBG) {
+                        Slog.w(TAG, "Return subtype " + scs.hashCode());
+                    }
                     return scs;
                 }
             }
-            return sci.getSubtypeAt(0);
+            return candidate;
         }
     }
 
@@ -283,6 +315,13 @@
         return;
     }
 
+    @Override
+    public boolean isSpellCheckerEnabled() {
+        synchronized(mSpellCheckerMap) {
+            return isSpellCheckerEnabledLocked();
+        }
+    }
+
     private void startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, String locale,
             ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener,
             int uid, Bundle bundle) {
@@ -354,7 +393,21 @@
                         "Requires permission "
                         + android.Manifest.permission.WRITE_SECURE_SETTINGS);
             }
-            setCurrentSpellCheckerLocked(hashCode);
+            setCurrentSpellCheckerSubtypeLocked(hashCode);
+        }
+    }
+
+    @Override
+    public void setSpellCheckerEnabled(boolean enabled) {
+        synchronized(mSpellCheckerMap) {
+            if (mContext.checkCallingOrSelfPermission(
+                    android.Manifest.permission.WRITE_SECURE_SETTINGS)
+                    != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException(
+                        "Requires permission "
+                        + android.Manifest.permission.WRITE_SECURE_SETTINGS);
+            }
+            setSpellCheckerEnabledLocked(enabled);
         }
     }
 
@@ -363,35 +416,64 @@
             Slog.w(TAG, "setCurrentSpellChecker: " + sciId);
         }
         if (TextUtils.isEmpty(sciId) || !mSpellCheckerMap.containsKey(sciId)) return;
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            Settings.Secure.putString(mContext.getContentResolver(),
-                    Settings.Secure.SELECTED_SPELL_CHECKER, sciId);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
-    private void setCurrentSpellCheckerLocked(int hashCode) {
-        if (DBG) {
-            Slog.w(TAG, "setCurrentSpellCheckerSubtype: " + hashCode);
-        }
-        final SpellCheckerInfo sci = getCurrentSpellChecker(null);
-        if (sci == null) return;
-        boolean found = false;
-        for (int i = 0; i < sci.getSubtypeCount(); ++i) {
-            if(sci.getSubtypeAt(i).hashCode() == hashCode) {
-                found = true;
-                break;
-            }
-        }
-        if (!found) {
+        final SpellCheckerInfo currentSci = getCurrentSpellChecker(null);
+        if (currentSci != null && currentSci.getId().equals(sciId)) {
+            // Do nothing if the current spell checker is same as new spell checker.
             return;
         }
         final long ident = Binder.clearCallingIdentity();
         try {
             Settings.Secure.putString(mContext.getContentResolver(),
-                    Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(hashCode));
+                    Settings.Secure.SELECTED_SPELL_CHECKER, sciId);
+            setCurrentSpellCheckerSubtypeLocked(0);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void setCurrentSpellCheckerSubtypeLocked(int hashCode) {
+        if (DBG) {
+            Slog.w(TAG, "setCurrentSpellCheckerSubtype: " + hashCode);
+        }
+        final SpellCheckerInfo sci = getCurrentSpellChecker(null);
+        int tempHashCode = 0;
+        for (int i = 0; sci != null && i < sci.getSubtypeCount(); ++i) {
+            if(sci.getSubtypeAt(i).hashCode() == hashCode) {
+                tempHashCode = hashCode;
+                break;
+            }
+        }
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            Settings.Secure.putString(mContext.getContentResolver(),
+                    Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(tempHashCode));
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void setSpellCheckerEnabledLocked(boolean enabled) {
+        if (DBG) {
+            Slog.w(TAG, "setSpellCheckerEnabled: " + enabled);
+        }
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            Settings.Secure.putInt(mContext.getContentResolver(),
+                    Settings.Secure.SPELL_CHECKER_ENABLED, enabled ? 1 : 0);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private boolean isSpellCheckerEnabledLocked() {
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            final boolean retval = Settings.Secure.getInt(mContext.getContentResolver(),
+                    Settings.Secure.SPELL_CHECKER_ENABLED, 1) == 1;
+            if (DBG) {
+                Slog.w(TAG, "getSpellCheckerEnabled: " + retval);
+            }
+            return retval;
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index 24b6ac3..2155147 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -532,9 +532,12 @@
                     mLastRead = 0;
                     mLastWrite = 0;
                 }
+            } catch (IllegalStateException e) {
+                Slog.e(TAG, "problem during onPollAlarm: " + e);
             } catch (RemoteException e) {
-                Slog.e(TAG, "got remoteException in onPollAlarm:" + e);
+                Slog.e(TAG, "problem during onPollAlarm: " + e);
             }
+
             // don't count this data if we're roaming.
             boolean roaming = "true".equals(
                     SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING));
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 9765f2a..6ceccaf 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -75,7 +75,7 @@
     static final String TAG = "WallpaperService";
     static final boolean DEBUG = false;
 
-    Object mLock = new Object();
+    final Object mLock = new Object[0];
 
     /**
      * Minimum time between crashes of a wallpaper service for us to consider
@@ -118,9 +118,10 @@
                         File changedFile = new File(WALLPAPER_DIR, path);
                         if (WALLPAPER_FILE.equals(changedFile)) {
                             notifyCallbacksLocked();
-                            if (mWallpaperComponent == null ||
-                                    mWallpaperComponent.equals(mImageWallpaperComponent)) {
-                                bindWallpaperComponentLocked(mWallpaperComponent, true);
+                            if (mWallpaperComponent == null || mImageWallpaperPending) {
+                                mImageWallpaperPending = false;
+                                bindWallpaperComponentLocked(mImageWallpaperComponent, true);
+                                saveSettingsLocked();
                             }
                         }
                     }
@@ -133,7 +134,12 @@
 
     int mWidth = -1;
     int mHeight = -1;
-    
+
+    /**
+     * Client is currently writing a new image wallpaper.
+     */
+    boolean mImageWallpaperPending;
+
     /**
      * Resource name if using a picture from the wallpaper gallery
      */
@@ -343,6 +349,7 @@
         }
         final long ident = Binder.clearCallingIdentity();
         try {
+            mImageWallpaperPending = false;
             bindWallpaperComponentLocked(null, false);
         } catch (IllegalArgumentException e) {
             // This can happen if the default wallpaper component doesn't
@@ -433,9 +440,7 @@
             try {
                 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name);
                 if (pfd != null) {
-                    // Bind the wallpaper to an ImageWallpaper
-                    bindWallpaperComponentLocked(mImageWallpaperComponent, false);
-                    saveSettingsLocked();
+                    mImageWallpaperPending = true;
                 }
                 return pfd;
             } finally {
@@ -463,6 +468,7 @@
         synchronized (mLock) {
             final long ident = Binder.clearCallingIdentity();
             try {
+                mImageWallpaperPending = false;
                 bindWallpaperComponentLocked(name, false);
             } finally {
                 Binder.restoreCallingIdentity(ident);
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index af01c5b..09ddc2f 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -40,7 +40,6 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemClock;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.text.TextUtils.SimpleStringSplitter;
@@ -72,7 +71,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * This class is instantiated by the system as a system level service and can be
@@ -871,10 +869,6 @@
 
         boolean mIsAutomation;
 
-        final Callback mCallback = new Callback();
-
-        final AtomicInteger mInteractionIdCounter = new AtomicInteger();
-
         final Rect mTempBounds = new Rect();
 
         // the events pending events to be dispatched to this service
@@ -974,14 +968,16 @@
             }
         }
 
-        public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int viewId)
+        public float findAccessibilityNodeInfoByViewIdInActiveWindow(int viewId,
+                int interactionId, IAccessibilityInteractionConnectionCallback callback,
+                long interrogatingTid)
                 throws RemoteException {
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
                 final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this);
                 if (!permissionGranted) {
-                    return null;
+                    return 0;
                 } else {
                     connection = getConnectionToRetrievalAllowingWindowLocked();
                     if (connection == null) {
@@ -989,22 +985,15 @@
                             Slog.e(LOG_TAG, "No interaction connection to a retrieve "
                                     + "allowing window.");
                         }
-                        return null;
+                        return 0;
                     }
                 }
             }
+            final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
-                final int interactionId = mInteractionIdCounter.getAndIncrement();
-                connection.findAccessibilityNodeInfoByViewId(viewId, interactionId, mCallback);
-                AccessibilityNodeInfo info = mCallback.getFindAccessibilityNodeInfoResultAndClear(
-                        interactionId);
-                if (info != null) {
-                    applyCompatibilityScaleIfNeeded(info);
-                    info.setConnection(this);
-                    info.setSealed(true);
-                }
-                return info;
+                connection.findAccessibilityNodeInfoByViewId(viewId, interactionId, callback,
+                        interrogatingPid, interrogatingTid);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error finding node.");
@@ -1012,51 +1001,44 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return null;
+            return getCompatibilityScale(mSecurityPolicy.getRetrievalAllowingWindowLocked());
         }
 
-        public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewTextInActiveWindow(
-                String text) throws RemoteException {
+        public float findAccessibilityNodeInfosByViewTextInActiveWindow(
+                String text, int interactionId,
+                IAccessibilityInteractionConnectionCallback callback, long threadId)
+                throws RemoteException {
             return findAccessibilityNodeInfosByViewText(text,
-                    mSecurityPolicy.mRetrievalAlowingWindowId, View.NO_ID);
+                    mSecurityPolicy.mRetrievalAlowingWindowId, View.NO_ID, interactionId, callback,
+                    threadId);
         }
 
-        public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(String text,
-                int accessibilityWindowId, int accessibilityViewId) throws RemoteException {
+        public float findAccessibilityNodeInfosByViewText(String text,
+                int accessibilityWindowId, int accessibilityViewId, int interactionId,
+                IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
+                throws RemoteException {
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
                 final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, accessibilityWindowId);
                 if (!permissionGranted) {
-                    return null;
+                    return 0;
                 } else {
                     connection = getConnectionToRetrievalAllowingWindowLocked();
                     if (connection == null) {
                         if (DEBUG) {
                             Slog.e(LOG_TAG, "No interaction connection to focused window.");
                         }
-                        return null;
+                        return 0;
                     }
                 }
             }
+            final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
-                final int interactionId = mInteractionIdCounter.getAndIncrement();
                 connection.findAccessibilityNodeInfosByViewText(text, accessibilityViewId,
-                        interactionId, mCallback);
-                List<AccessibilityNodeInfo> infos =
-                    mCallback.getFindAccessibilityNodeInfosResultAndClear(interactionId);
-                if (infos != null) {
-                    final int infoCount = infos.size();
-                    for (int i = 0; i < infoCount; i++) {
-                        AccessibilityNodeInfo info = infos.get(i);
-                        applyCompatibilityScaleIfNeeded(info);
-                        info.setConnection(this);
-                        info.setSealed(true);
-                    }
-                }
-                return infos;
+                        interactionId, callback, interrogatingPid, interrogatingTid);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error finding node.");
@@ -1064,18 +1046,20 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return null;
+            return getCompatibilityScale(accessibilityWindowId);
         }
 
-        public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(
-                int accessibilityWindowId, int accessibilityViewId) throws RemoteException {
+        public float findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
+                int accessibilityViewId, int interactionId,
+                IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
+                throws RemoteException {
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
                 final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, accessibilityWindowId);
                 if (!permissionGranted) {
-                    return null;
+                    return 0;
                 } else {
                     connection = mWindowIdToInteractionConnectionMap.get(accessibilityWindowId);
                     if (connection == null) {
@@ -1083,23 +1067,15 @@
                             Slog.e(LOG_TAG, "No interaction connection to window: "
                                     + accessibilityWindowId);
                         }
-                        return null;
+                        return 0;
                     }
                 }
             }
+            final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
-                final int interactionId = mInteractionIdCounter.getAndIncrement();
                 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityViewId,
-                        interactionId, mCallback);
-                AccessibilityNodeInfo info =
-                     mCallback.getFindAccessibilityNodeInfoResultAndClear(interactionId);
-                if (info != null) {
-                    applyCompatibilityScaleIfNeeded(info);
-                    info.setConnection(this);
-                    info.setSealed(true);
-                }
-                return info;
+                        interactionId, callback, interrogatingPid, interrogatingTid);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error requesting node with accessibilityViewId: "
@@ -1108,11 +1084,12 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return null;
+            return getCompatibilityScale(accessibilityWindowId);
         }
 
         public boolean performAccessibilityAction(int accessibilityWindowId,
-                int accessibilityViewId, int action) {
+                int accessibilityViewId, int action, int interactionId,
+                IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) {
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 final boolean permissionGranted = mSecurityPolicy.canPerformActionLocked(this,
@@ -1130,12 +1107,11 @@
                     }
                 }
             }
+            final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
-                final int interactionId = mInteractionIdCounter.getAndIncrement();
                 connection.performAccessibilityAction(accessibilityViewId, action, interactionId,
-                        mCallback);
-                return mCallback.getPerformAccessibilityActionResult(interactionId);
+                        callback, interrogatingPid, interrogatingTid);
             } catch (RemoteException re) {
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Error requesting node with accessibilityViewId: "
@@ -1144,7 +1120,7 @@
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
             }
-            return false;
+            return true;
         }
 
         public void onServiceDisconnected(ComponentName componentName) {
@@ -1173,22 +1149,9 @@
             return mWindowIdToInteractionConnectionMap.get(windowId);
         }
 
-        private void applyCompatibilityScaleIfNeeded(AccessibilityNodeInfo info) {
-            IBinder windowToken = mWindowIdToWindowTokenMap.get(info.getWindowId());
-            final float scale = mWindowManagerService.getWindowCompatibilityScale(windowToken);
-
-            if (scale == 1.0f) {
-                return;
-            }
-
-            Rect bounds = mTempBounds;
-            info.getBoundsInParent(bounds);
-            bounds.scale(scale);
-            info.setBoundsInParent(bounds);
-
-            info.getBoundsInScreen(bounds);
-            bounds.scale(scale);
-            info.setBoundsInScreen(bounds);
+        private float getCompatibilityScale(int windowId) {
+            IBinder windowToken = mWindowIdToWindowTokenMap.get(windowId);
+            return mWindowManagerService.getWindowCompatibilityScale(windowToken);
         }
     }
 
@@ -1275,99 +1238,4 @@
             }
         }
     }
-
-    final class Callback extends IAccessibilityInteractionConnectionCallback.Stub {
-        private static final long TIMEOUT_INTERACTION_MILLIS = 5000;
-
-        private int mInteractionId = -1;
-        private AccessibilityNodeInfo mFindAccessibilityNodeInfoResult;
-        private List<AccessibilityNodeInfo> mFindAccessibilityNodeInfosResult;
-        private boolean mPerformAccessibilityActionResult;
-
-        public void setFindAccessibilityNodeInfoResult(AccessibilityNodeInfo info,
-                int interactionId) {
-            synchronized (mLock) {
-                if (interactionId > mInteractionId) {
-                    mFindAccessibilityNodeInfoResult = info;
-                    mInteractionId = interactionId;
-                }
-                mLock.notifyAll();
-            }
-        }
-
-        public AccessibilityNodeInfo getFindAccessibilityNodeInfoResultAndClear(int interactionId) {
-            synchronized (mLock) {
-                waitForResultTimedLocked(TIMEOUT_INTERACTION_MILLIS, interactionId);
-                AccessibilityNodeInfo result = mFindAccessibilityNodeInfoResult;
-                clearLocked();
-                return result;
-            }
-        }
-
-        public void setFindAccessibilityNodeInfosResult(List<AccessibilityNodeInfo> infos,
-                int interactionId) {
-            synchronized (mLock) {
-                if (interactionId > mInteractionId) {
-                    mFindAccessibilityNodeInfosResult = infos;
-                    mInteractionId = interactionId;
-                }
-                mLock.notifyAll();
-            }
-        }
-
-        public List<AccessibilityNodeInfo> getFindAccessibilityNodeInfosResultAndClear(
-                int interactionId) {
-            synchronized (mLock) {
-                waitForResultTimedLocked(TIMEOUT_INTERACTION_MILLIS, interactionId);
-                List<AccessibilityNodeInfo> result = mFindAccessibilityNodeInfosResult;
-                clearLocked();
-                return result;
-            }
-        }
-
-        public void setPerformAccessibilityActionResult(boolean succeeded, int interactionId) {
-            synchronized (mLock) {
-                if (interactionId > mInteractionId) {
-                    mPerformAccessibilityActionResult = succeeded;
-                    mInteractionId = interactionId;
-                }
-                mLock.notifyAll();
-            }
-        }
-
-        public boolean getPerformAccessibilityActionResult(int interactionId) {
-            synchronized (mLock) {
-                waitForResultTimedLocked(TIMEOUT_INTERACTION_MILLIS, interactionId);
-                final boolean result = mPerformAccessibilityActionResult;
-                clearLocked();
-                return result;
-            }
-        }
-
-        public void clearLocked() {
-            mInteractionId = -1;
-            mFindAccessibilityNodeInfoResult = null;
-            mFindAccessibilityNodeInfosResult = null;
-            mPerformAccessibilityActionResult = false;
-        }
-
-        private void waitForResultTimedLocked(long waitTimeMillis, int interactionId) {
-            final long startTimeMillis = SystemClock.uptimeMillis();
-            while (true) {
-                try {
-                    if (mInteractionId == interactionId) {
-                        return;
-                    }
-                    final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
-                    waitTimeMillis = TIMEOUT_INTERACTION_MILLIS - elapsedTimeMillis;
-                    if (waitTimeMillis <= 0) {
-                        return;
-                    }
-                    mLock.wait(waitTimeMillis);
-                } catch (InterruptedException ie) {
-                    /* ignore */
-                }
-            }
-        }
-    }
 }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index c935733..bb5e989 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -91,7 +91,6 @@
 import android.os.FileObserver;
 import android.os.FileUtils;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.IPermissionController;
 import android.os.Looper;
@@ -5518,6 +5517,48 @@
         return msg;
     }
 
+    boolean incProviderCount(ProcessRecord r, ContentProviderRecord cpr) {
+        if (r != null) {
+            Integer cnt = r.conProviders.get(cpr);
+            if (DEBUG_PROVIDER) Slog.v(TAG,
+                    "Adding provider requested by "
+                    + r.processName + " from process "
+                    + cpr.info.processName + ": " + cpr.name.flattenToShortString()
+                    + " cnt=" + (cnt == null ? 1 : cnt));
+            if (cnt == null) {
+                cpr.clients.add(r);
+                r.conProviders.put(cpr, new Integer(1));
+                return true;
+            } else {
+                r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
+            }
+        } else {
+            cpr.externals++;
+        }
+        return false;
+    }
+
+    boolean decProviderCount(ProcessRecord r, ContentProviderRecord cpr) {
+        if (r != null) {
+            Integer cnt = r.conProviders.get(cpr);
+            if (DEBUG_PROVIDER) Slog.v(TAG,
+                    "Removing provider requested by "
+                    + r.processName + " from process "
+                    + cpr.info.processName + ": " + cpr.name.flattenToShortString()
+                    + " cnt=" + cnt);
+            if (cnt == null || cnt.intValue() <= 1) {
+                cpr.clients.remove(r);
+                r.conProviders.remove(cpr);
+                return true;
+            } else {
+                r.conProviders.put(cpr, new Integer(cnt.intValue()-1));
+            }
+        } else {
+            cpr.externals++;
+        }
+        return false;
+    }
+
     private final ContentProviderHolder getContentProviderImpl(
         IApplicationThread caller, String name) {
         ContentProviderRecord cpr;
@@ -5537,7 +5578,8 @@
 
             // First check if this content provider has been published...
             cpr = mProvidersByName.get(name);
-            if (cpr != null) {
+            boolean providerRunning = cpr != null;
+            if (providerRunning) {
                 cpi = cpr.info;
                 String msg;
                 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
@@ -5561,18 +5603,8 @@
 
                 // In this case the provider instance already exists, so we can
                 // return it right away.
-                if (r != null) {
-                    if (DEBUG_PROVIDER) Slog.v(TAG,
-                            "Adding provider requested by "
-                            + r.processName + " from process "
-                            + cpr.info.processName);
-                    Integer cnt = r.conProviders.get(cpr);
-                    if (cnt == null) {
-                        r.conProviders.put(cpr, new Integer(1));
-                    } else {
-                        r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
-                    }
-                    cpr.clients.add(r);
+                final boolean countChanged = incProviderCount(r, cpr);
+                if (countChanged) {
                     if (cpr.app != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
                         // If this is a perceptible app accessing the provider,
                         // make sure to count it as being accessed and thus
@@ -5580,17 +5612,46 @@
                         // content providers are often expensive to start.
                         updateLruProcessLocked(cpr.app, false, true);
                     }
-                } else {
-                    cpr.externals++;
                 }
 
                 if (cpr.app != null) {
-                    updateOomAdjLocked(cpr.app);
+                    if (false) {
+                        if (cpr.name.flattenToShortString().equals(
+                                "com.android.providers.calendar/.CalendarProvider2")) {
+                            Slog.v(TAG, "****************** KILLING "
+                                + cpr.name.flattenToShortString());
+                            Process.killProcess(cpr.app.pid);
+                        }
+                    }
+                    boolean success = updateOomAdjLocked(cpr.app);
+                    if (DEBUG_PROVIDER) Slog.i(TAG, "Adjust success: " + success);
+                    // NOTE: there is still a race here where a signal could be
+                    // pending on the process even though we managed to update its
+                    // adj level.  Not sure what to do about this, but at least
+                    // the race is now smaller.
+                    if (!success) {
+                        // Uh oh...  it looks like the provider's process
+                        // has been killed on us.  We need to wait for a new
+                        // process to be started, and make sure its death
+                        // doesn't kill our process.
+                        Slog.i(TAG,
+                                "Existing provider " + cpr.name.flattenToShortString()
+                                + " is crashing; detaching " + r);
+                        boolean lastRef = decProviderCount(r, cpr);
+                        appDiedLocked(cpr.app, cpr.app.pid, cpr.app.thread);
+                        if (!lastRef) {
+                            // This wasn't the last ref our process had on
+                            // the provider...  we have now been killed, bail.
+                            return null;
+                        }
+                        providerRunning = false;
+                    }
                 }
 
                 Binder.restoreCallingIdentity(origId);
+            }
 
-            } else {
+            if (!providerRunning) {
                 try {
                     cpi = AppGlobals.getPackageManager().
                         resolveContentProvider(name,
@@ -5701,22 +5762,7 @@
                     mProvidersByClass.put(comp, cpr);
                 }
                 mProvidersByName.put(name, cpr);
-
-                if (r != null) {
-                    if (DEBUG_PROVIDER) Slog.v(TAG,
-                            "Adding provider requested by "
-                            + r.processName + " from process "
-                            + cpr.info.processName);
-                    Integer cnt = r.conProviders.get(cpr);
-                    if (cnt == null) {
-                        r.conProviders.put(cpr, new Integer(1));
-                    } else {
-                        r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
-                    }
-                    cpr.clients.add(r);
-                } else {
-                    cpr.externals++;
-                }
+                incProviderCount(r, cpr);
             }
         }
 
@@ -5780,24 +5826,16 @@
             //update content provider record entry info
             ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
             ContentProviderRecord localCpr = mProvidersByClass.get(comp);
-            if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
-                    + r.info.processName + " from process "
-                    + localCpr.appInfo.processName);
             if (localCpr.app == r) {
                 //should not happen. taken care of as a local provider
                 Slog.w(TAG, "removeContentProvider called on local provider: "
                         + cpr.info.name + " in process " + r.processName);
                 return;
             } else {
-                Integer cnt = r.conProviders.get(localCpr);
-                if (cnt == null || cnt.intValue() <= 1) {
-                    localCpr.clients.remove(r);
-                    r.conProviders.remove(localCpr);
-                } else {
-                    r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
+                if (decProviderCount(r, localCpr)) {
+                    updateOomAdjLocked();
                 }
             }
-            updateOomAdjLocked();
         }
     }
 
@@ -9026,6 +9064,7 @@
     final static class MemItem {
         final String label;
         final long pss;
+        ArrayList<MemItem> subitems;
 
         public MemItem(String _label, long _pss) {
             label = _label;
@@ -9051,7 +9090,10 @@
 
         for (int i=0; i<items.size(); i++) {
             MemItem mi = items.get(i);
-            pw.print(prefix); pw.printf("%8d Kb: ", mi.pss); pw.println(mi.label);
+            pw.print(prefix); pw.printf("%7d Kb: ", mi.pss); pw.println(mi.label);
+            if (mi.subitems != null) {
+                dumpMemItems(pw, prefix + "           ", mi.subitems, true);
+            }
         }
     }
 
@@ -9119,6 +9161,7 @@
                 "Backup", "Services", "Home", "Background"
         };
         long oomPss[] = new long[oomLabel.length];
+        ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])new ArrayList[oomLabel.length];
 
         long totalPss = 0;
 
@@ -9147,7 +9190,9 @@
                 if (!isCheckinRequest && mi != null) {
                     long myTotalPss = mi.getTotalPss();
                     totalPss += myTotalPss;
-                    procMems.add(new MemItem(r.processName + " (pid " + r.pid + ")", myTotalPss));
+                    MemItem pssItem = new MemItem(r.processName + " (pid " + r.pid + ")",
+                            myTotalPss);
+                    procMems.add(pssItem);
 
                     nativePss += mi.nativePss;
                     dalvikPss += mi.dalvikPss;
@@ -9161,6 +9206,10 @@
                     for (int oomIndex=0; oomIndex<oomPss.length; oomIndex++) {
                         if (r.setAdj <= oomAdj[oomIndex] || oomIndex == (oomPss.length-1)) {
                             oomPss[oomIndex] += myTotalPss;
+                            if (oomProcs[oomIndex] == null) {
+                                oomProcs[oomIndex] = new ArrayList<MemItem>();
+                            }
+                            oomProcs[oomIndex].add(pssItem);
                             break;
                         }
                     }
@@ -9181,7 +9230,9 @@
             ArrayList<MemItem> oomMems = new ArrayList<MemItem>();
             for (int j=0; j<oomPss.length; j++) {
                 if (oomPss[j] != 0) {
-                    oomMems.add(new MemItem(oomLabel[j], oomPss[j]));
+                    MemItem item = new MemItem(oomLabel[j], oomPss[j]);
+                    item.subitems = oomProcs[j];
+                    oomMems.add(item);
                 }
             }
 
@@ -13445,16 +13496,18 @@
         }
     }
 
-    private final void updateOomAdjLocked(
+    private final boolean updateOomAdjLocked(
             ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
         app.hiddenAdj = hiddenAdj;
 
         if (app.thread == null) {
-            return;
+            return false;
         }
 
         final boolean wasKeeping = app.keeping;
 
+        boolean success = true;
+
         computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
 
         if (app.curRawAdj != app.setRawAdj) {
@@ -13491,6 +13544,7 @@
                     " oom adj to " + app.curAdj + " because " + app.adjType);
                 app.setAdj = app.curAdj;
             } else {
+                success = false;
                 Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj);
             }
         }
@@ -13505,6 +13559,7 @@
                 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
                         app.processName, app.setAdj, app.waitingToKill);
                 Process.killProcessQuiet(app.pid);
+                success = false;
             } else {
                 if (true) {
                     long oldId = Binder.clearCallingIdentity();
@@ -13527,6 +13582,7 @@
                 }
             }
         }
+        return success;
     }
 
     private final ActivityRecord resumedAppLocked() {
@@ -13540,7 +13596,7 @@
         return resumedActivity;
     }
 
-    private final void updateOomAdjLocked(ProcessRecord app) {
+    private final boolean updateOomAdjLocked(ProcessRecord app) {
         final ActivityRecord TOP_ACT = resumedAppLocked();
         final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
         int curAdj = app.curAdj;
@@ -13549,7 +13605,7 @@
 
         mAdjSeq++;
 
-        updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
+        boolean success = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
         final boolean nowHidden = app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
             && app.curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
         if (nowHidden != wasHidden) {
@@ -13557,6 +13613,7 @@
             // list may also be changed.
             updateOomAdjLocked();
         }
+        return success;
     }
 
     final void updateOomAdjLocked() {
diff --git a/services/java/com/android/server/am/ProcessList.java b/services/java/com/android/server/am/ProcessList.java
index dfcc0bfa..131255f 100644
--- a/services/java/com/android/server/am/ProcessList.java
+++ b/services/java/com/android/server/am/ProcessList.java
@@ -163,7 +163,7 @@
         int minSize = 320*480;  //  153600
         int maxSize = 1280*800; // 1024000  230400 870400  .264
         float scaleDisp = ((float)(displayWidth*displayHeight)-minSize)/(maxSize-minSize);
-        Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth + " dh=" + displayHeight);
+        //Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth + " dh=" + displayHeight);
 
         StringBuilder adjString = new StringBuilder();
         StringBuilder memString = new StringBuilder();
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
index e61a7f4..87129ea 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -116,6 +116,8 @@
         if (!askedCompatMode) {
             pw.print(prefix); pw.print("askedCompatMode="); pw.println(askedCompatMode);
         }
+        pw.print(prefix); pw.print("lastThumbnail="); pw.print(lastThumbnail);
+                pw.print(" lastDescription="); pw.println(lastDescription);
         pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime);
                 pw.print(" (inactive for ");
                 pw.print((getInactiveDuration()/1000)); pw.println("s)");
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 6b65e07..55e0678 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -388,6 +388,7 @@
         private final VpnConfig mConfig;
         private final String[] mDaemons;
         private final String[][] mArguments;
+        private final LocalSocket[] mSockets;
         private final String mOuterInterface;
         private final LegacyVpnInfo mInfo;
 
@@ -398,6 +399,7 @@
             mConfig = config;
             mDaemons = new String[] {"racoon", "mtpd"};
             mArguments = new String[][] {racoon, mtpd};
+            mSockets = new LocalSocket[mDaemons.length];
             mInfo = new LegacyVpnInfo();
 
             // This is the interface which VPN is running on.
@@ -416,10 +418,14 @@
         }
 
         public void exit() {
-            // We assume that everything is reset after the daemons die.
+            // We assume that everything is reset after stopping the daemons.
             interrupt();
-            for (String daemon : mDaemons) {
-                SystemProperties.set("ctl.stop", daemon);
+            for (LocalSocket socket : mSockets) {
+                try {
+                    socket.close();
+                } catch (Exception e) {
+                    // ignore
+                }
             }
         }
 
@@ -462,15 +468,10 @@
                 checkpoint(false);
                 mInfo.state = LegacyVpnInfo.STATE_INITIALIZING;
 
-                // First stop the daemons.
-                for (String daemon : mDaemons) {
-                    SystemProperties.set("ctl.stop", daemon);
-                }
-
                 // Wait for the daemons to stop.
                 for (String daemon : mDaemons) {
                     String key = "init.svc." + daemon;
-                    while (!"stopped".equals(SystemProperties.get(key))) {
+                    while (!"stopped".equals(SystemProperties.get(key, "stopped"))) {
                         checkpoint(true);
                     }
                 }
@@ -511,27 +512,27 @@
                     }
 
                     // Create the control socket.
-                    LocalSocket socket = new LocalSocket();
+                    mSockets[i] = new LocalSocket();
                     LocalSocketAddress address = new LocalSocketAddress(
                             daemon, LocalSocketAddress.Namespace.RESERVED);
 
                     // Wait for the socket to connect.
                     while (true) {
                         try {
-                            socket.connect(address);
+                            mSockets[i].connect(address);
                             break;
                         } catch (Exception e) {
                             // ignore
                         }
                         checkpoint(true);
                     }
-                    socket.setSoTimeout(500);
+                    mSockets[i].setSoTimeout(500);
 
                     // Send over the arguments.
-                    OutputStream out = socket.getOutputStream();
+                    OutputStream out = mSockets[i].getOutputStream();
                     for (String argument : arguments) {
                         byte[] bytes = argument.getBytes(Charsets.UTF_8);
-                        if (bytes.length > 0xFFFF) {
+                        if (bytes.length >= 0xFFFF) {
                             throw new IllegalArgumentException("Argument is too large");
                         }
                         out.write(bytes.length >> 8);
@@ -539,11 +540,12 @@
                         out.write(bytes);
                         checkpoint(false);
                     }
+                    out.write(0xFF);
+                    out.write(0xFF);
                     out.flush();
-                    socket.shutdownOutput();
 
                     // Wait for End-of-File.
-                    InputStream in = socket.getInputStream();
+                    InputStream in = mSockets[i].getInputStream();
                     while (true) {
                         try {
                             if (in.read() == -1) {
@@ -554,7 +556,6 @@
                         }
                         checkpoint(true);
                     }
-                    socket.close();
                 }
 
                 // Wait for the daemons to create the new state.
@@ -631,6 +632,13 @@
                 Log.i(TAG, "Aborting", e);
                 exit();
             } finally {
+                // Kill the daemons if they fail to stop.
+                if (mInfo.state == LegacyVpnInfo.STATE_INITIALIZING) {
+                    for (String daemon : mDaemons) {
+                        SystemProperties.set("ctl.stop", daemon);
+                    }
+                }
+
                 // Do not leave an unstable state.
                 if (mInfo.state == LegacyVpnInfo.STATE_INITIALIZING ||
                         mInfo.state == LegacyVpnInfo.STATE_CONNECTING) {
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 84880f9..84e5eae 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -60,6 +60,7 @@
 import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
+import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
 
 import android.app.IActivityManager;
 import android.app.INotificationManager;
@@ -454,7 +455,7 @@
             mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
             synchronized (mRulesLock) {
-                if (mMeteredIfaces.contains(iface)) {
+                if (mMeteredIfaces.contains(iface) && !LIMIT_GLOBAL_ALERT.equals(limitName)) {
                     try {
                         // force stats update to make sure we have numbers that
                         // caused alert to trigger.
@@ -763,7 +764,12 @@
             // disable data connection when over limit and not snoozed
             final boolean overLimit = policy.limitBytes != LIMIT_DISABLED
                     && totalBytes > policy.limitBytes && policy.lastSnooze < start;
-            setNetworkTemplateEnabled(policy.template, !overLimit);
+            final boolean enabled = !overLimit;
+
+            if (LOGD) {
+                Slog.d(TAG, "setting template=" + policy.template + " enabled=" + enabled);
+            }
+            setNetworkTemplateEnabled(policy.template, enabled);
         }
     }
 
@@ -772,7 +778,6 @@
      * for the given {@link NetworkTemplate}.
      */
     private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
-        if (LOGD) Slog.d(TAG, "setting template=" + template + " enabled=" + enabled);
         switch (template.getMatchRule()) {
             case MATCH_MOBILE_3G_LOWER:
             case MATCH_MOBILE_4G:
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index c911687..80ae9bc 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -43,6 +43,7 @@
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
 import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
 import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
 
@@ -56,6 +57,7 @@
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.net.IConnectivityManager;
+import android.net.INetworkManagementEventObserver;
 import android.net.INetworkStatsService;
 import android.net.NetworkIdentity;
 import android.net.NetworkInfo;
@@ -121,7 +123,8 @@
     private static final int VERSION_UID_WITH_TAG = 3;
     private static final int VERSION_UID_WITH_SET = 4;
 
-    private static final int MSG_FORCE_UPDATE = 0x1;
+    private static final int MSG_PERFORM_POLL = 0x1;
+    private static final int MSG_PERFORM_POLL_DETAILED = 0x2;
 
     private final Context mContext;
     private final INetworkManagementService mNetworkManager;
@@ -141,7 +144,6 @@
 
     private PendingIntent mPollIntent;
 
-    // TODO: listen for kernel push events through netd instead of polling
     // TODO: trim empty history objects entirely
 
     private static final long KB_IN_BYTES = 1024;
@@ -174,17 +176,18 @@
     /** Flag if {@link #mUidStats} have been loaded from disk. */
     private boolean mUidStatsLoaded = false;
 
-    private NetworkStats mLastNetworkSnapshot;
-    private NetworkStats mLastPersistNetworkSnapshot;
+    private NetworkStats mLastPollNetworkSnapshot;
+    private NetworkStats mLastPollUidSnapshot;
+    private NetworkStats mLastPollOperationsSnapshot;
 
-    private NetworkStats mLastUidSnapshot;
+    private NetworkStats mLastPersistNetworkSnapshot;
+    private NetworkStats mLastPersistUidSnapshot;
 
     /** Current counter sets for each UID. */
     private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
 
     /** Data layer operation counters for splicing into other structures. */
     private NetworkStats mOperations = new NetworkStats(0L, 10);
-    private NetworkStats mLastOperationsSnapshot;
 
     private final HandlerThread mHandlerThread;
     private final Handler mHandler;
@@ -252,13 +255,18 @@
         mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
 
         try {
-            registerPollAlarmLocked();
+            mNetworkManager.registerObserver(mAlertObserver);
         } catch (RemoteException e) {
-            Slog.w(TAG, "unable to register poll alarm");
+            // ouch, no push updates means we fall back to
+            // ACTION_NETWORK_STATS_POLL intervals.
+            Slog.e(TAG, "unable to register INetworkManagementEventObserver", e);
         }
 
-        // kick off background poll to bootstrap deltas
-        mHandler.obtainMessage(MSG_FORCE_UPDATE).sendToTarget();
+        registerPollAlarmLocked();
+        registerGlobalAlert();
+
+        // bootstrap initial stats to prevent double-counting later
+        bootstrapStats();
     }
 
     private void shutdownLocked() {
@@ -280,17 +288,37 @@
      * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and
      * reschedule based on current {@link NetworkStatsSettings#getPollInterval()}.
      */
-    private void registerPollAlarmLocked() throws RemoteException {
-        if (mPollIntent != null) {
-            mAlarmManager.remove(mPollIntent);
+    private void registerPollAlarmLocked() {
+        try {
+            if (mPollIntent != null) {
+                mAlarmManager.remove(mPollIntent);
+            }
+
+            mPollIntent = PendingIntent.getBroadcast(
+                    mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
+
+            final long currentRealtime = SystemClock.elapsedRealtime();
+            mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
+                    mSettings.getPollInterval(), mPollIntent);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "problem registering for poll alarm: " + e);
         }
+    }
 
-        mPollIntent = PendingIntent.getBroadcast(
-                mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
-
-        final long currentRealtime = SystemClock.elapsedRealtime();
-        mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
-                mSettings.getPollInterval(), mPollIntent);
+    /**
+     * Register for a global alert that is delivered through
+     * {@link INetworkManagementEventObserver} once a threshold amount of data
+     * has been transferred.
+     */
+    private void registerGlobalAlert() {
+        try {
+            final long alertBytes = mSettings.getPersistThreshold();
+            mNetworkManager.setGlobalAlert(alertBytes);
+        } catch (IllegalStateException e) {
+            Slog.w(TAG, "problem registering for global alert: " + e);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "problem registering for global alert: " + e);
+        }
     }
 
     @Override
@@ -475,10 +503,7 @@
     @Override
     public void forceUpdate() {
         mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
-
-        synchronized (mStatsLock) {
-            performPollLocked(true, false);
-        }
+        performPoll(true, false);
     }
 
     /**
@@ -507,14 +532,10 @@
         public void onReceive(Context context, Intent intent) {
             // on background handler thread, and verified UPDATE_DEVICE_STATS
             // permission above.
-            synchronized (mStatsLock) {
-                mWakeLock.acquire();
-                try {
-                    performPollLocked(true, false);
-                } finally {
-                    mWakeLock.release();
-                }
-            }
+            performPoll(true, false);
+
+            // verify that we're watching global alert
+            registerGlobalAlert();
         }
     };
 
@@ -547,6 +568,26 @@
     };
 
     /**
+     * Observer that watches for {@link INetworkManagementService} alerts.
+     */
+    private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
+        @Override
+        public void limitReached(String limitName, String iface) {
+            // only someone like NMS should be calling us
+            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+
+            if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
+                // kick off background poll to collect network stats; UID stats
+                // are handled during normal polling interval.
+                mHandler.obtainMessage(MSG_PERFORM_POLL).sendToTarget();
+
+                // re-arm global alert for next update
+                registerGlobalAlert();
+            }
+        }
+    };
+
+    /**
      * Inspect all current {@link NetworkState} to derive mapping from {@code
      * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
      * are active on a single {@code iface}, they are combined under a single
@@ -588,6 +629,33 @@
     }
 
     /**
+     * Bootstrap initial stats snapshot, usually during {@link #systemReady()}
+     * so we have baseline values without double-counting.
+     */
+    private void bootstrapStats() {
+        try {
+            mLastPollNetworkSnapshot = mNetworkManager.getNetworkStatsSummary();
+            mLastPollUidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
+            mLastPollOperationsSnapshot = new NetworkStats(0L, 0);
+        } catch (IllegalStateException e) {
+            Slog.w(TAG, "problem reading network stats: " + e);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "problem reading network stats: " + e);
+        }
+    }
+
+    private void performPoll(boolean detailedPoll, boolean forcePersist) {
+        synchronized (mStatsLock) {
+            mWakeLock.acquire();
+            try {
+                performPollLocked(detailedPoll, forcePersist);
+            } finally {
+                mWakeLock.release();
+            }
+        }
+    }
+
+    /**
      * Periodic poll operation, reading current statistics and recording into
      * {@link NetworkStatsHistory}.
      *
@@ -596,6 +664,7 @@
      */
     private void performPollLocked(boolean detailedPoll, boolean forcePersist) {
         if (LOGV) Slog.v(TAG, "performPollLocked()");
+        final long startRealtime = SystemClock.elapsedRealtime();
 
         // try refreshing time source when stale
         if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
@@ -605,6 +674,7 @@
         // TODO: consider marking "untrusted" times in historical stats
         final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
                 : System.currentTimeMillis();
+        final long persistThreshold = mSettings.getPersistThreshold();
 
         final NetworkStats networkSnapshot;
         final NetworkStats uidSnapshot;
@@ -620,30 +690,32 @@
         }
 
         performNetworkPollLocked(networkSnapshot, currentTime);
-        if (detailedPoll) {
-            performUidPollLocked(uidSnapshot, currentTime);
+
+        // persist when enough network data has occurred
+        final NetworkStats persistNetworkDelta = computeStatsDelta(
+                mLastPersistNetworkSnapshot, networkSnapshot, true);
+        if (forcePersist || persistNetworkDelta.getTotalBytes() > persistThreshold) {
+            writeNetworkStatsLocked();
+            mLastPersistNetworkSnapshot = networkSnapshot;
         }
 
-        // decide if enough has changed to trigger persist
-        final NetworkStats persistDelta = computeStatsDelta(
-                mLastPersistNetworkSnapshot, networkSnapshot, true);
-        final long persistThreshold = mSettings.getPersistThreshold();
+        if (detailedPoll) {
+            performUidPollLocked(uidSnapshot, currentTime);
 
-        NetworkStats.Entry entry = null;
-        for (String iface : persistDelta.getUniqueIfaces()) {
-            final int index = persistDelta.findIndex(iface, UID_ALL, SET_DEFAULT, TAG_NONE);
-            entry = persistDelta.getValues(index, entry);
-            if (forcePersist || entry.rxBytes > persistThreshold
-                    || entry.txBytes > persistThreshold) {
-                writeNetworkStatsLocked();
-                if (mUidStatsLoaded) {
-                    writeUidStatsLocked();
-                }
+            // persist when enough network data has occurred
+            final NetworkStats persistUidDelta = computeStatsDelta(
+                    mLastPersistUidSnapshot, uidSnapshot, true);
+            if (forcePersist || persistUidDelta.getTotalBytes() > persistThreshold) {
+                writeUidStatsLocked();
                 mLastPersistNetworkSnapshot = networkSnapshot;
-                break;
             }
         }
 
+        if (LOGV) {
+            final long duration = SystemClock.elapsedRealtime() - startRealtime;
+            Slog.v(TAG, "performPollLocked() took " + duration + "ms");
+        }
+
         // finally, dispatch updated event to any listeners
         final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
         updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -656,7 +728,7 @@
     private void performNetworkPollLocked(NetworkStats networkSnapshot, long currentTime) {
         final HashSet<String> unknownIface = Sets.newHashSet();
 
-        final NetworkStats delta = computeStatsDelta(mLastNetworkSnapshot, networkSnapshot, false);
+        final NetworkStats delta = computeStatsDelta(mLastPollNetworkSnapshot, networkSnapshot, false);
         final long timeStart = currentTime - delta.getElapsedRealtime();
 
         NetworkStats.Entry entry = null;
@@ -678,7 +750,7 @@
             history.removeBucketsBefore(currentTime - maxHistory);
         }
 
-        mLastNetworkSnapshot = networkSnapshot;
+        mLastPollNetworkSnapshot = networkSnapshot;
 
         if (LOGD && unknownIface.size() > 0) {
             Slog.w(TAG, "unknown interfaces " + unknownIface.toString() + ", ignoring those stats");
@@ -691,9 +763,9 @@
     private void performUidPollLocked(NetworkStats uidSnapshot, long currentTime) {
         ensureUidStatsLoadedLocked();
 
-        final NetworkStats delta = computeStatsDelta(mLastUidSnapshot, uidSnapshot, false);
+        final NetworkStats delta = computeStatsDelta(mLastPollUidSnapshot, uidSnapshot, false);
         final NetworkStats operationsDelta = computeStatsDelta(
-                mLastOperationsSnapshot, mOperations, false);
+                mLastPollOperationsSnapshot, mOperations, false);
         final long timeStart = currentTime - delta.getElapsedRealtime();
 
         NetworkStats.Entry entry = null;
@@ -731,8 +803,8 @@
             }
         }
 
-        mLastUidSnapshot = uidSnapshot;
-        mLastOperationsSnapshot = mOperations;
+        mLastPollUidSnapshot = uidSnapshot;
+        mLastPollOperationsSnapshot = mOperations;
         mOperations = new NetworkStats(0L, 10);
     }
 
@@ -1162,8 +1234,12 @@
         /** {@inheritDoc} */
         public boolean handleMessage(Message msg) {
             switch (msg.what) {
-                case MSG_FORCE_UPDATE: {
-                    forceUpdate();
+                case MSG_PERFORM_POLL: {
+                    performPoll(false, false);
+                    return true;
+                }
+                case MSG_PERFORM_POLL_DETAILED: {
+                    performPoll(true, false);
                     return true;
                 }
                 default: {
@@ -1226,10 +1302,10 @@
         }
 
         public long getPollInterval() {
-            return getSecureLong(NETSTATS_POLL_INTERVAL, 15 * MINUTE_IN_MILLIS);
+            return getSecureLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
         }
         public long getPersistThreshold() {
-            return getSecureLong(NETSTATS_PERSIST_THRESHOLD, 16 * KB_IN_BYTES);
+            return getSecureLong(NETSTATS_PERSIST_THRESHOLD, 512 * KB_IN_BYTES);
         }
         public long getNetworkBucketDuration() {
             return getSecureLong(NETSTATS_NETWORK_BUCKET_DURATION, HOUR_IN_MILLIS);
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 2f19a46..b8797d18 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -194,7 +194,8 @@
     /**
      * Whether verification is enabled by default.
      */
-    private static final boolean DEFAULT_VERIFY_ENABLE = true;
+    // STOPSHIP: change this to true
+    private static final boolean DEFAULT_VERIFY_ENABLE = false;
 
     /**
      * The default maximum time to wait for the verification agent to return in
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index a01c975..8f51466 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -568,12 +568,9 @@
                     notification.sound = null;
                     notification.vibrate = null;
 
-                    Intent intent = new Intent(
-                            Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
-                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-                    intent.setComponent(new ComponentName("com.android.settings",
-                            "com.android.settings.UsbSettings"));
+                    Intent intent = Intent.makeRestartActivityTask(
+                            new ComponentName("com.android.settings",
+                                    "com.android.settings.UsbSettings"));
                     PendingIntent pi = PendingIntent.getActivity(mContext, 0,
                             intent, 0);
                     notification.setLatestEventInfo(mContext, title, message, pi);
@@ -604,12 +601,9 @@
                     notification.sound = null;
                     notification.vibrate = null;
 
-                    Intent intent = new Intent(
-                            Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
-                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-                    intent.setComponent(new ComponentName("com.android.settings",
-                            "com.android.settings.DevelopmentSettings"));
+                    Intent intent = Intent.makeRestartActivityTask(
+                            new ComponentName("com.android.settings",
+                                    "com.android.settings.DevelopmentSettings"));
                     PendingIntent pi = PendingIntent.getActivity(mContext, 0,
                             intent, 0);
                     notification.setLatestEventInfo(mContext, title, message, pi);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 3df94a6..e258b1a 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -163,6 +163,7 @@
     static final boolean DEBUG_WALLPAPER = false;
     static final boolean DEBUG_DRAG = false;
     static final boolean DEBUG_SCREEN_ON = false;
+    static final boolean DEBUG_SCREENSHOT = false;
     static final boolean SHOW_SURFACE_ALLOC = false;
     static final boolean SHOW_TRANSACTIONS = false;
     static final boolean HIDE_STACK_CRAWLS = true;
@@ -4996,6 +4997,14 @@
                 dh = tmp;
                 rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
             }
+            if (DEBUG_SCREENSHOT) {
+                Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from 0 to " + maxLayer);
+                for (int i=0; i<mWindows.size(); i++) {
+                    Slog.i(TAG, mWindows.get(i) + ": " + mWindows.get(i).mLayer
+                            + " animLayer=" + mWindows.get(i).mAnimLayer
+                            + " surfaceLayer=" + mWindows.get(i).mSurfaceLayer);
+                }
+            }
             rawss = Surface.screenshot(dw, dh, 0, maxLayer);
         }
 
diff --git a/services/sensorservice/Fusion.cpp b/services/sensorservice/Fusion.cpp
index ff4786b..0ab86c3 100644
--- a/services/sensorservice/Fusion.cpp
+++ b/services/sensorservice/Fusion.cpp
@@ -47,9 +47,46 @@
 static const float accSTDEV  = 0.05f;   // m/s^2 (measured 0.08 / CDD 0.05)
 static const float magSTDEV  = 0.5f;    // uT    (measured 0.7  / CDD 0.5)
 
-static const float FREE_FALL_THRESHOLD = 0.981f;
 static const float SYMMETRY_TOLERANCE = 1e-10f;
 
+/*
+ * Accelerometer updates will not be performed near free fall to avoid
+ * ill-conditioning and div by zeros.
+ * Threshhold: 10% of g, in m/s^2
+ */
+static const float FREE_FALL_THRESHOLD = 0.981f;
+static const float FREE_FALL_THRESHOLD_SQ =
+        FREE_FALL_THRESHOLD*FREE_FALL_THRESHOLD;
+
+/*
+ * The geomagnetic-field should be between 30uT and 60uT.
+ * Fields strengths greater than this likely indicate a local magnetic
+ * disturbance which we do not want to update into the fused frame.
+ */
+static const float MAX_VALID_MAGNETIC_FIELD = 100; // uT
+static const float MAX_VALID_MAGNETIC_FIELD_SQ =
+        MAX_VALID_MAGNETIC_FIELD*MAX_VALID_MAGNETIC_FIELD;
+
+/*
+ * Values of the field smaller than this should be ignored in fusion to avoid
+ * ill-conditioning. This state can happen with anomalous local magnetic
+ * disturbances canceling the Earth field.
+ */
+static const float MIN_VALID_MAGNETIC_FIELD = 10; // uT
+static const float MIN_VALID_MAGNETIC_FIELD_SQ =
+        MIN_VALID_MAGNETIC_FIELD*MIN_VALID_MAGNETIC_FIELD;
+
+/*
+ * If the cross product of two vectors has magnitude squared less than this,
+ * we reject it as invalid due to alignment of the vectors.
+ * This threshold is used to check for the case where the magnetic field sample
+ * is parallel to the gravity field, which can happen in certain places due
+ * to magnetic field disturbances.
+ */
+static const float MIN_VALID_CROSS_PRODUCT_MAG = 1.0e-3;
+static const float MIN_VALID_CROSS_PRODUCT_MAG_SQ =
+    MIN_VALID_CROSS_PRODUCT_MAG*MIN_VALID_CROSS_PRODUCT_MAG;
+
 // -----------------------------------------------------------------------
 
 template <typename TYPE, size_t C, size_t R>
@@ -240,8 +277,9 @@
 
 status_t Fusion::handleAcc(const vec3_t& a) {
     // ignore acceleration data if we're close to free-fall
-    if (length(a) < FREE_FALL_THRESHOLD)
+    if (length_squared(a) < FREE_FALL_THRESHOLD_SQ) {
         return BAD_VALUE;
+    }
 
     if (!checkInitComplete(ACC, a))
         return BAD_VALUE;
@@ -253,15 +291,34 @@
 
 status_t Fusion::handleMag(const vec3_t& m) {
     // the geomagnetic-field should be between 30uT and 60uT
-    // reject obviously wrong magnetic-fields
-    if (length(m) > 100)
+    // reject if too large to avoid spurious magnetic sources
+    const float magFieldSq = length_squared(m);
+    if (magFieldSq > MAX_VALID_MAGNETIC_FIELD_SQ) {
         return BAD_VALUE;
+    } else if (magFieldSq < MIN_VALID_MAGNETIC_FIELD_SQ) {
+        // Also reject if too small since we will get ill-defined (zero mag)
+        // cross-products below
+        return BAD_VALUE;
+    }
 
     if (!checkInitComplete(MAG, m))
         return BAD_VALUE;
 
+    // Orthogonalize the magnetic field to the gravity field, mapping it into
+    // tangent to Earth.
     const vec3_t up( getRotationMatrix() * Ba );
     const vec3_t east( cross_product(m, up) );
+
+    // If the m and up vectors align, the cross product magnitude will
+    // approach 0.
+    // Reject this case as well to avoid div by zero problems and
+    // ill-conditioning below.
+    if (length_squared(east) < MIN_VALID_CROSS_PRODUCT_MAG_SQ) {
+        return BAD_VALUE;
+    }
+
+    // If we have created an orthogonal magnetic field successfully,
+    // then pass it in as the update.
     vec3_t north( cross_product(up, east) );
 
     const float l = 1 / length(north);
diff --git a/services/sensorservice/vec.h b/services/sensorservice/vec.h
index f74ccc5..24f30ff 100644
--- a/services/sensorservice/vec.h
+++ b/services/sensorservice/vec.h
@@ -212,6 +212,15 @@
     typename TYPE,
     size_t SIZE
 >
+TYPE PURE length_squared(const V<TYPE, SIZE>& v) {
+    return dot_product(v, v);
+}
+
+template <
+    template<typename T, size_t S> class V,
+    typename TYPE,
+    size_t SIZE
+>
 V<TYPE, SIZE> PURE normalize(const V<TYPE, SIZE>& v) {
     return v * (1/length(v));
 }
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8b2485a..f8925b8 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -556,6 +556,7 @@
         // need a hardware-protected path to external video sink
         usage |= GraphicBuffer::USAGE_PROTECTED;
     }
+    usage |= GraphicBuffer::USAGE_HW_COMPOSER;
     return usage;
 }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0080202..598220f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2207,14 +2207,17 @@
         return BAD_VALUE;
 
     // make sure none of the layers are protected
-    const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+    const LayerVector& layers(mDrawingState.layersSortedByZ);
     const size_t count = layers.size();
     for (size_t i=0 ; i<count ; ++i) {
         const sp<LayerBase>& layer(layers[i]);
-        const uint32_t z = layer->drawingState().z;
-        if (z >= minLayerZ && z <= maxLayerZ) {
-            if (layer->isProtected()) {
-                return INVALID_OPERATION;
+        const uint32_t flags = layer->drawingState().flags;
+        if (!(flags & ISurfaceComposer::eLayerHidden)) {
+            const uint32_t z = layer->drawingState().z;
+            if (z >= minLayerZ && z <= maxLayerZ) {
+                if (layer->isProtected()) {
+                    return INVALID_OPERATION;
+                }
             }
         }
     }
@@ -2270,9 +2273,12 @@
 
         for (size_t i=0 ; i<count ; ++i) {
             const sp<LayerBase>& layer(layers[i]);
-            const uint32_t z = layer->drawingState().z;
-            if (z >= minLayerZ && z <= maxLayerZ) {
-                layer->drawForSreenShot();
+            const uint32_t flags = layer->drawingState().flags;
+            if (!(flags & ISurfaceComposer::eLayerHidden)) {
+                const uint32_t z = layer->drawingState().z;
+                if (z >= minLayerZ && z <= maxLayerZ) {
+                    layer->drawForSreenShot();
+                }
             }
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index 6138490..6dd8cd6 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -38,6 +38,7 @@
 import static android.text.format.DateUtils.WEEK_IN_MILLIS;
 import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL;
 import static org.easymock.EasyMock.anyLong;
+import static org.easymock.EasyMock.capture;
 import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.eq;
 import static org.easymock.EasyMock.expect;
@@ -49,6 +50,7 @@
 import android.app.PendingIntent;
 import android.content.Intent;
 import android.net.IConnectivityManager;
+import android.net.INetworkManagementEventObserver;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
@@ -65,10 +67,10 @@
 import com.android.server.net.NetworkStatsService;
 import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
 
+import org.easymock.Capture;
 import org.easymock.EasyMock;
 
 import java.io.File;
-import java.util.concurrent.Future;
 
 import libcore.io.IoUtils;
 
@@ -105,6 +107,7 @@
     private IConnectivityManager mConnManager;
 
     private NetworkStatsService mService;
+    private INetworkManagementEventObserver mNetworkObserver;
 
     @Override
     public void setUp() throws Exception {
@@ -132,13 +135,20 @@
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
-        final Future<?> firstPoll = expectSystemReady();
+        expectSystemReady();
+
+        // catch INetworkManagementEventObserver during systemReady()
+        final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
+                INetworkManagementEventObserver>();
+        mNetManager.registerObserver(capture(networkObserver));
+        expectLastCall().atLeastOnce();
 
         replay();
         mService.systemReady();
-        firstPoll.get();
         verifyAndReset();
 
+        mNetworkObserver = networkObserver.getValue();
+
     }
 
     @Override
@@ -183,6 +193,7 @@
         expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L));
         expectNetworkStatsUidDetail(buildEmptyStats());
+        expectNetworkStatsPoll();
 
         replay();
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -199,6 +210,7 @@
         expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 4096L, 4L, 8192L, 8L));
         expectNetworkStatsUidDetail(buildEmptyStats());
+        expectNetworkStatsPoll();
 
         replay();
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -238,6 +250,7 @@
                 .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
                 .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
                 .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L));
+        expectNetworkStatsPoll();
 
         mService.setUidForeground(UID_RED, false);
         mService.incrementOperationCount(UID_RED, 0xFAAD, 4);
@@ -273,11 +286,18 @@
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
-        final Future<?> firstPoll = expectSystemReady();
+        expectSystemReady();
+
+        // catch INetworkManagementEventObserver during systemReady()
+        final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
+                INetworkManagementEventObserver>();
+        mNetManager.registerObserver(capture(networkObserver));
+        expectLastCall().atLeastOnce();
 
         replay();
         mService.systemReady();
-        firstPoll.get();
+
+        mNetworkObserver = networkObserver.getValue();
 
         // after systemReady(), we should have historical stats loaded again
         assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0);
@@ -312,6 +332,7 @@
         expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 512L, 4L, 512L, 4L));
         expectNetworkStatsUidDetail(buildEmptyStats());
+        expectNetworkStatsPoll();
 
         replay();
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -329,6 +350,7 @@
         expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS);
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
+        expectNetworkStatsPoll();
 
         replay();
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -363,6 +385,7 @@
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
                 .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
+        expectNetworkStatsPoll();
 
         mService.incrementOperationCount(UID_RED, 0xF00D, 10);
 
@@ -384,6 +407,7 @@
         expectNetworkState(buildMobile3gState(IMSI_2));
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
+        expectNetworkStatsPoll();
 
         replay();
         mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
@@ -399,6 +423,7 @@
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
                 .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 1024L, 8L, 0L)
                 .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L));
+        expectNetworkStatsPoll();
 
         mService.incrementOperationCount(UID_BLUE, 0xFAAD, 10);
 
@@ -441,6 +466,7 @@
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
                 .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L)
                 .addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
+        expectNetworkStatsPoll();
 
         mService.incrementOperationCount(UID_RED, 0xFAAD, 10);
 
@@ -494,6 +520,7 @@
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
+        expectNetworkStatsPoll();
 
         mService.incrementOperationCount(UID_RED, 0xF00D, 5);
 
@@ -511,6 +538,7 @@
         expectNetworkState(buildMobile4gState());
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
+        expectNetworkStatsPoll();
 
         replay();
         mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
@@ -525,6 +553,7 @@
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L));
+        expectNetworkStatsPoll();
 
         mService.incrementOperationCount(UID_RED, 0xFAAD, 5);
 
@@ -558,6 +587,7 @@
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
                 .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L));
+        expectNetworkStatsPoll();
 
         mService.incrementOperationCount(UID_RED, 0xF00D, 1);
 
@@ -576,6 +606,7 @@
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
                 .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 2048L, 16L, 1024L, 8L, 0L));
+        expectNetworkStatsPoll();
 
         replay();
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -617,6 +648,7 @@
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L));
+        expectNetworkStatsPoll();
 
         mService.incrementOperationCount(UID_RED, 0xF00D, 1);
 
@@ -637,6 +669,7 @@
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)
                 .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L)
                 .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L));
+        expectNetworkStatsPoll();
 
         mService.setUidForeground(UID_RED, true);
         mService.incrementOperationCount(UID_RED, 0xFAAD, 1);
@@ -679,7 +712,7 @@
                 txPackets, operations);
     }
 
-    private Future<?> expectSystemReady() throws Exception {
+    private void expectSystemReady() throws Exception {
         mAlarmManager.remove(isA(PendingIntent.class));
         expectLastCall().anyTimes();
 
@@ -687,8 +720,8 @@
                 eq(AlarmManager.ELAPSED_REALTIME), anyLong(), anyLong(), isA(PendingIntent.class));
         expectLastCall().atLeastOnce();
 
-        return mServiceContext.nextBroadcastIntent(
-                NetworkStatsService.ACTION_NETWORK_STATS_UPDATED);
+        mNetManager.setGlobalAlert(anyLong());
+        expectLastCall().atLeastOnce();
     }
 
     private void expectNetworkState(NetworkState... state) throws Exception {
@@ -727,6 +760,11 @@
         expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
     }
 
+    private void expectNetworkStatsPoll() throws Exception {
+        mNetManager.setGlobalAlert(anyLong());
+        expectLastCall().anyTimes();
+    }
+
     private void assertStatsFilesExist(boolean exist) {
         final File networkFile = new File(mStatsDir, "netstats.bin");
         final File uidFile = new File(mStatsDir, "netstats_uid.bin");
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 2cf4b88..0aed77e 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -545,7 +545,7 @@
             int defaultRoamingIndicator = 0;  //[12] Is default roaming indicator from PRL
             int reasonForDenial = 0;       //[13] Denial reason if registrationState = 3
 
-            if (states.length == 14) {
+            if (states.length >= 14) {
                 try {
                     if (states[0] != null) {
                         registrationState = Integer.parseInt(states[0]);
@@ -593,8 +593,8 @@
                 }
             } else {
                 throw new RuntimeException("Warning! Wrong number of parameters returned from "
-                                     + "RIL_REQUEST_REGISTRATION_STATE: expected 14 got "
-                                     + states.length);
+                                     + "RIL_REQUEST_REGISTRATION_STATE: expected 14 or more "
+                                     + "strings and got " + states.length + " strings");
             }
 
             mRegistrationState = registrationState;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index c8671c1..00fb0e0 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -576,7 +576,8 @@
         boolean allowed =
                     (gprsState == ServiceState.STATE_IN_SERVICE || mAutoAttachOnCreation) &&
                     mPhone.mIccRecords.getRecordsLoaded() &&
-                    mPhone.getState() == Phone.State.IDLE &&
+                    (mPhone.getState() == Phone.State.IDLE ||
+                     mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) &&
                     internalDataEnabled &&
                     (!mPhone.getServiceState().getRoaming() || getDataOnRoamingEnabled()) &&
                     !mIsPsRestricted &&
@@ -587,8 +588,10 @@
                 reason += " - gprs= " + gprsState;
             }
             if (!mPhone.mIccRecords.getRecordsLoaded()) reason += " - SIM not loaded";
-            if (mPhone.getState() != Phone.State.IDLE) {
+            if (mPhone.getState() != Phone.State.IDLE &&
+                    !mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
                 reason += " - PhoneState= " + mPhone.getState();
+                reason += " - Concurrent voice and data not allowed";
             }
             if (!internalDataEnabled) reason += " - mInternalDataEnabled= false";
             if (mPhone.getServiceState().getRoaming() && !getDataOnRoamingEnabled()) {
diff --git a/tests/BiDiTests/res/layout/basic.xml b/tests/BiDiTests/res/layout/basic.xml
index 8a27213..f503658 100644
--- a/tests/BiDiTests/res/layout/basic.xml
+++ b/tests/BiDiTests/res/layout/basic.xml
@@ -27,11 +27,18 @@
                       android:layout_width="match_parent"
                       android:layout_height="wrap_content">
 
-            <Button android:id="@+id/button"
+            <TextView android:id="@+id/textview_password_default"
                     android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button_text"
                     android:textSize="32dip"
+                    android:text="@string/textview_password_default_text"
+            />
+
+            <EditText android:id="@+id/edittext_password_default"
+                      android:layout_height="wrap_content"
+                      android:layout_width="match_parent"
+                      android:textSize="32dip"
+                      android:password="true"
                     />
 
             <TextView android:id="@+id/textview_default"
diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml
index b0809da..b1f5e50e 100644
--- a/tests/BiDiTests/res/values/strings.xml
+++ b/tests/BiDiTests/res/values/strings.xml
@@ -28,6 +28,7 @@
     <string name="textview_ltr_text">This is a text for a LTR TextView</string>
     <string name="textview_rtl_text">This is a text for a RTL TextView</string>
     <string name="textview_default_text">This is a text for a default TextView</string>
+    <string name="textview_password_default_text">This is a text for a password TextView</string>
     <string name="edittext_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
     <string name="normal_text">Normal String</string>
     <string name="normal_long_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
index e77178d..3232eedc 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
@@ -33,7 +33,6 @@
 import android.widget.FrameLayout;
 
 import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGL11;
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.egl.EGLContext;
 import javax.microedition.khronos.egl.EGLDisplay;
@@ -207,7 +206,7 @@
             glEnableVertexAttribArray(attribTexCoords);
             checkGlError();
 
-            glUniform1i(texture, 0);
+            glUniform1i(uniformTexture, texture);
             checkGlError();
             
             while (!mFinished) {
@@ -350,7 +349,7 @@
                     !mEglSurface.equals(mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
                 if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
                     throw new RuntimeException("eglMakeCurrent failed "
-                            + getEGLErrorString(mEgl.eglGetError()));
+                            + GLUtils.getEGLErrorString(mEgl.eglGetError()));
                 }
             }
         }
@@ -361,13 +360,13 @@
             mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
             if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
                 throw new RuntimeException("eglGetDisplay failed "
-                        + getEGLErrorString(mEgl.eglGetError()));
+                        + GLUtils.getEGLErrorString(mEgl.eglGetError()));
             }
             
             int[] version = new int[2];
             if (!mEgl.eglInitialize(mEglDisplay, version)) {
                 throw new RuntimeException("eglInitialize failed " +
-                        getEGLErrorString(mEgl.eglGetError()));
+                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
             }
 
             mEglConfig = chooseEglConfig();
@@ -386,12 +385,12 @@
                     return;
                 }
                 throw new RuntimeException("createWindowSurface failed "
-                        + getEGLErrorString(error));
+                        + GLUtils.getEGLErrorString(error));
             }
 
             if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
                 throw new RuntimeException("eglMakeCurrent failed "
-                        + getEGLErrorString(mEgl.eglGetError()));
+                        + GLUtils.getEGLErrorString(mEgl.eglGetError()));
             }
 
             mGL = mEglContext.getGL();
@@ -409,7 +408,7 @@
             int[] configSpec = getConfig();
             if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) {
                 throw new IllegalArgumentException("eglChooseConfig failed " +
-                        getEGLErrorString(mEgl.eglGetError()));
+                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
             } else if (configsCount[0] > 0) {
                 return configs[0];
             }
@@ -429,43 +428,6 @@
             };
         }
 
-        static String getEGLErrorString(int error) {
-            switch (error) {
-                case EGL10.EGL_SUCCESS:
-                    return "EGL_SUCCESS";
-                case EGL10.EGL_NOT_INITIALIZED:
-                    return "EGL_NOT_INITIALIZED";
-                case EGL10.EGL_BAD_ACCESS:
-                    return "EGL_BAD_ACCESS";
-                case EGL10.EGL_BAD_ALLOC:
-                    return "EGL_BAD_ALLOC";
-                case EGL10.EGL_BAD_ATTRIBUTE:
-                    return "EGL_BAD_ATTRIBUTE";
-                case EGL10.EGL_BAD_CONFIG:
-                    return "EGL_BAD_CONFIG";
-                case EGL10.EGL_BAD_CONTEXT:
-                    return "EGL_BAD_CONTEXT";
-                case EGL10.EGL_BAD_CURRENT_SURFACE:
-                    return "EGL_BAD_CURRENT_SURFACE";
-                case EGL10.EGL_BAD_DISPLAY:
-                    return "EGL_BAD_DISPLAY";
-                case EGL10.EGL_BAD_MATCH:
-                    return "EGL_BAD_MATCH";
-                case EGL10.EGL_BAD_NATIVE_PIXMAP:
-                    return "EGL_BAD_NATIVE_PIXMAP";
-                case EGL10.EGL_BAD_NATIVE_WINDOW:
-                    return "EGL_BAD_NATIVE_WINDOW";
-                case EGL10.EGL_BAD_PARAMETER:
-                    return "EGL_BAD_PARAMETER";
-                case EGL10.EGL_BAD_SURFACE:
-                    return "EGL_BAD_SURFACE";
-                case EGL11.EGL_CONTEXT_LOST:
-                    return "EGL_CONTEXT_LOST";
-                default:
-                    return "0x" + Integer.toHexString(error);
-            }
-        }
-
         void finish() {
             mFinished = true;
         }
diff --git a/tests/RenderScriptTests/FBOTest/res/drawable/robot.png b/tests/RenderScriptTests/FBOTest/res/drawable-nodpi/robot.png
similarity index 100%
rename from tests/RenderScriptTests/FBOTest/res/drawable/robot.png
rename to tests/RenderScriptTests/FBOTest/res/drawable-nodpi/robot.png
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing/res/drawable/city.png b/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/city.png
similarity index 100%
rename from tests/RenderScriptTests/ImageProcessing/res/drawable/city.png
rename to tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/city.png
Binary files differ
diff --git a/tests/RenderScriptTests/ModelViewer/res/drawable/robot.png b/tests/RenderScriptTests/ModelViewer/res/drawable-nodpi/robot.png
similarity index 100%
rename from tests/RenderScriptTests/ModelViewer/res/drawable/robot.png
rename to tests/RenderScriptTests/ModelViewer/res/drawable-nodpi/robot.png
Binary files differ
diff --git a/tests/RenderScriptTests/PerfTest/res/drawable/checker.png b/tests/RenderScriptTests/PerfTest/res/drawable-nodpi/checker.png
similarity index 100%
rename from tests/RenderScriptTests/PerfTest/res/drawable/checker.png
rename to tests/RenderScriptTests/PerfTest/res/drawable-nodpi/checker.png
Binary files differ
diff --git a/tests/RenderScriptTests/PerfTest/res/drawable/data.png b/tests/RenderScriptTests/PerfTest/res/drawable-nodpi/data.png
similarity index 100%
rename from tests/RenderScriptTests/PerfTest/res/drawable/data.png
rename to tests/RenderScriptTests/PerfTest/res/drawable-nodpi/data.png
Binary files differ
diff --git a/tests/RenderScriptTests/PerfTest/res/drawable/flares.png b/tests/RenderScriptTests/PerfTest/res/drawable-nodpi/flares.png
similarity index 100%
rename from tests/RenderScriptTests/PerfTest/res/drawable/flares.png
rename to tests/RenderScriptTests/PerfTest/res/drawable-nodpi/flares.png
Binary files differ
diff --git a/tests/RenderScriptTests/PerfTest/res/drawable/globe.png b/tests/RenderScriptTests/PerfTest/res/drawable-nodpi/globe.png
similarity index 100%
rename from tests/RenderScriptTests/PerfTest/res/drawable/globe.png
rename to tests/RenderScriptTests/PerfTest/res/drawable-nodpi/globe.png
Binary files differ
diff --git a/tests/RenderScriptTests/PerfTest/res/drawable/leaf.png b/tests/RenderScriptTests/PerfTest/res/drawable-nodpi/leaf.png
similarity index 100%
rename from tests/RenderScriptTests/PerfTest/res/drawable/leaf.png
rename to tests/RenderScriptTests/PerfTest/res/drawable-nodpi/leaf.png
Binary files differ
diff --git a/tests/RenderScriptTests/PerfTest/res/drawable/light1.jpg b/tests/RenderScriptTests/PerfTest/res/drawable-nodpi/light1.jpg
similarity index 100%
rename from tests/RenderScriptTests/PerfTest/res/drawable/light1.jpg
rename to tests/RenderScriptTests/PerfTest/res/drawable-nodpi/light1.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/PerfTest/res/drawable/space.jpg b/tests/RenderScriptTests/PerfTest/res/drawable-nodpi/space.jpg
similarity index 100%
rename from tests/RenderScriptTests/PerfTest/res/drawable/space.jpg
rename to tests/RenderScriptTests/PerfTest/res/drawable-nodpi/space.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/PerfTest/res/drawable/test_pattern.png b/tests/RenderScriptTests/PerfTest/res/drawable-nodpi/test_pattern.png
similarity index 100%
rename from tests/RenderScriptTests/PerfTest/res/drawable/test_pattern.png
rename to tests/RenderScriptTests/PerfTest/res/drawable-nodpi/test_pattern.png
Binary files differ
diff --git a/tests/RenderScriptTests/PerfTest/res/drawable/torusmap.png b/tests/RenderScriptTests/PerfTest/res/drawable-nodpi/torusmap.png
similarity index 100%
rename from tests/RenderScriptTests/PerfTest/res/drawable/torusmap.png
rename to tests/RenderScriptTests/PerfTest/res/drawable-nodpi/torusmap.png
Binary files differ
diff --git a/tests/RenderScriptTests/tests/res/drawable/test_pattern.png b/tests/RenderScriptTests/tests/res/drawable-nodpi/test_pattern.png
similarity index 100%
rename from tests/RenderScriptTests/tests/res/drawable/test_pattern.png
rename to tests/RenderScriptTests/tests/res/drawable-nodpi/test_pattern.png
Binary files differ
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 5b4bce2..83dda5c 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -281,7 +281,11 @@
         if (WifiNative.removeNetworkCommand(netId)) {
             WifiNative.saveConfigCommand();
             synchronized (sConfiguredNetworks) {
-                sConfiguredNetworks.remove(netId);
+                WifiConfiguration config = sConfiguredNetworks.get(netId);
+                if (config != null) {
+                    sConfiguredNetworks.remove(netId);
+                    sNetworkIds.remove(configKey(config));
+                }
             }
             writeIpAndProxyConfigurations();
             sendConfiguredNetworksChangedBroadcast();
@@ -315,7 +319,13 @@
     static boolean removeNetwork(int netId) {
         boolean ret = WifiNative.removeNetworkCommand(netId);
         synchronized (sConfiguredNetworks) {
-            if (ret) sConfiguredNetworks.remove(netId);
+            if (ret) {
+                WifiConfiguration config = sConfiguredNetworks.get(netId);
+                if (config != null) {
+                    sConfiguredNetworks.remove(netId);
+                    sNetworkIds.remove(configKey(config));
+                }
+            }
         }
         sendConfiguredNetworksChangedBroadcast();
         return ret;
@@ -366,7 +376,8 @@
         boolean ret = WifiNative.disableNetworkCommand(netId);
         synchronized (sConfiguredNetworks) {
             WifiConfiguration config = sConfiguredNetworks.get(netId);
-            if (config != null) {
+            /* Only change the reason if the network was not previously disabled */
+            if (config != null && config.status != Status.DISABLED) {
                 config.status = Status.DISABLED;
                 config.disableReason = reason;
             }
@@ -600,7 +611,10 @@
         synchronized (sConfiguredNetworks) {
             for(WifiConfiguration config : sConfiguredNetworks.values()) {
                 if(config != null && config.networkId != netId) {
-                    config.status = Status.DISABLED;
+                    if (config.status != Status.DISABLED) {
+                        config.status = Status.DISABLED;
+                        config.disableReason = WifiConfiguration.DISABLED_UNKNOWN_REASON;
+                    }
                 }
             }
         }
@@ -854,18 +868,24 @@
          * refer to an existing configuration.
          */
         int netId = config.networkId;
-        boolean updateFailed = true;
+        boolean newNetwork = false;
         // networkId of INVALID_NETWORK_ID means we want to create a new network
-        boolean newNetwork = (netId == INVALID_NETWORK_ID);
-
-        if (newNetwork) {
-            netId = WifiNative.addNetworkCommand();
-            if (netId < 0) {
-                Log.e(TAG, "Failed to add a network!");
-                return new NetworkUpdateResult(INVALID_NETWORK_ID);
-          }
+        if (netId == INVALID_NETWORK_ID) {
+            Integer savedNetId = sNetworkIds.get(configKey(config));
+            if (savedNetId != null) {
+                netId = savedNetId;
+            } else {
+                newNetwork = true;
+                netId = WifiNative.addNetworkCommand();
+                if (netId < 0) {
+                    Log.e(TAG, "Failed to add a network!");
+                    return new NetworkUpdateResult(INVALID_NETWORK_ID);
+                }
+            }
         }
 
+        boolean updateFailed = true;
+
         setVariables: {
 
             if (config.SSID != null &&
@@ -1053,12 +1073,15 @@
         if (sConfig == null) {
             sConfig = new WifiConfiguration();
             sConfig.networkId = netId;
-            synchronized (sConfiguredNetworks) {
-                sConfiguredNetworks.put(netId, sConfig);
-            }
         }
+
         readNetworkVariables(sConfig);
 
+        synchronized (sConfiguredNetworks) {
+            sConfiguredNetworks.put(netId, sConfig);
+            sNetworkIds.put(configKey(sConfig), netId);
+        }
+
         NetworkUpdateResult result = writeIpAndProxyConfigurationsOnChange(sConfig, config);
         result.setNetworkId(netId);
         return result;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index d2a0b30..85a6f27 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -530,6 +530,7 @@
         if (source != null) {
             networkId = source.networkId;
             status = source.status;
+            disableReason = source.disableReason;
             SSID = source.SSID;
             BSSID = source.BSSID;
             preSharedKey = source.preSharedKey;
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 6c6f149..c1f6785 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -243,7 +243,7 @@
 
     /* p2p_connect <peer device address> <pbc|pin|PIN#> [label|display|keypad]
         [persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>] */
-    public static String p2pConnect(WifiP2pConfig config) {
+    public static String p2pConnect(WifiP2pConfig config, boolean joinExistingGroup) {
         if (config == null) return null;
         List<String> args = new ArrayList<String>();
         WpsConfiguration wpsConfig = config.wpsConfig;
@@ -269,15 +269,15 @@
                 break;
         }
 
-        if (config.isPersistent) args.add("persistent");
-        if (config.joinExistingGroup) args.add("join");
+        /* Persist unless there is an explicit request to not do so*/
+        if (config.persist != WifiP2pConfig.Persist.NO) args.add("persistent");
+        if (joinExistingGroup) args.add("join");
 
         int groupOwnerIntent = config.groupOwnerIntent;
         if (groupOwnerIntent < 0 || groupOwnerIntent > 15) {
             groupOwnerIntent = 3; //default value
         }
         args.add("go_intent=" + groupOwnerIntent);
-        if (config.channel > 0) args.add("freq=" + config.channel);
 
         String command = "P2P_CONNECT ";
         for (String s : args) command += s + " ";
@@ -300,11 +300,24 @@
 
     /* Invite a peer to a group */
     public static boolean p2pInvite(WifiP2pGroup group, String deviceAddress) {
-        if (group == null || deviceAddress == null) return false;
-        return doBooleanCommand("P2P_INVITE group=" + group.getInterface()
-                + " peer=" + deviceAddress + " go_dev_addr=" + group.getOwner().deviceAddress);
+        if (deviceAddress == null) return false;
+
+        if (group == null) {
+            return doBooleanCommand("P2P_INVITE peer=" + deviceAddress);
+        } else {
+            return doBooleanCommand("P2P_INVITE group=" + group.getInterface()
+                    + " peer=" + deviceAddress + " go_dev_addr=" + group.getOwner().deviceAddress);
+        }
     }
 
+    /* Reinvoke a persistent connection */
+    public static boolean p2pReinvoke(int netId, String deviceAddress) {
+        if (deviceAddress == null || netId < 0) return false;
+
+        return doBooleanCommand("P2P_INVITE persistent=" + netId + " peer=" + deviceAddress);
+    }
+
+
     public static String p2pGetInterfaceAddress(String deviceAddress) {
         if (deviceAddress == null) return null;
 
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
index 4dd856f..274edae 100644
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -46,9 +46,9 @@
 import java.net.HttpURLConnection;
 import java.net.InetAddress;
 import java.net.URL;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 
 /**
  * {@link WifiWatchdogStateMachine} monitors the initial connection to a Wi-Fi
@@ -79,7 +79,7 @@
     private static final int LOW_SIGNAL_CUTOFF = 1;
 
     private static final long DEFAULT_DNS_CHECK_SHORT_INTERVAL_MS = 2 * 60 * 1000;
-    private static final long DEFAULT_DNS_CHECK_LONG_INTERVAL_MS = 10 * 60 * 1000;
+    private static final long DEFAULT_DNS_CHECK_LONG_INTERVAL_MS = 30 * 60 * 1000;
     private static final long DEFAULT_WALLED_GARDEN_INTERVAL_MS = 30 * 60 * 1000;
 
     private static final int DEFAULT_MAX_SSID_BLACKLISTS = 7;
@@ -661,26 +661,34 @@
     }
 
     class DnsCheckingState extends State {
-        int dnsCheckSuccesses = 0;
-        int dnsCheckTries = 0;
-        String dnsCheckLogStr = "";
-        Set<Integer> ids = new HashSet<Integer>();
+        List<InetAddress> mDnsList;
+        int[] dnsCheckSuccesses;
+        String dnsCheckLogStr;
+        String[] dnsResponseStrs;
+        /** Keeps track of active dns pings.  Map is from pingID to index in mDnsList */
+        HashMap<Integer, Integer> idDnsMap = new HashMap<Integer, Integer>();
 
         @Override
         public void enter() {
-            dnsCheckSuccesses = 0;
-            dnsCheckTries = 0;
-            ids.clear();
-            InetAddress dns = mDnsPinger.getDns();
+            mDnsList = mDnsPinger.getDnsList();
+            int numDnses = mDnsList.size();
+            dnsCheckSuccesses = new int[numDnses];
+            dnsResponseStrs = new String[numDnses];
+            for (int i = 0; i < numDnses; i++)
+                dnsResponseStrs[i] = "";
+
             if (DBG) {
-                Slog.d(WWSM_TAG, "Starting DNS pings at " + SystemClock.elapsedRealtime());
                 dnsCheckLogStr = String.format("Pinging %s on ssid [%s]: ",
-                        mDnsPinger.getDns(), mConnectionInfo.getSSID());
+                        mDnsList, mConnectionInfo.getSSID());
+                Slog.d(WWSM_TAG, dnsCheckLogStr);
             }
 
+            idDnsMap.clear();
             for (int i=0; i < mNumDnsPings; i++) {
-                ids.add(mDnsPinger.pingDnsAsync(dns, mDnsPingTimeoutMs,
-                        DNS_INTRATEST_PING_INTERVAL * i));
+                for (int j = 0; j < numDnses; j++) {
+                    idDnsMap.put(mDnsPinger.pingDnsAsync(mDnsList.get(j), mDnsPingTimeoutMs,
+                            DNS_INTRATEST_PING_INTERVAL * i), j);
+                }
             }
         }
 
@@ -693,27 +701,24 @@
             int pingID = msg.arg1;
             int pingResponseTime = msg.arg2;
 
-            if (!ids.contains(pingID)) {
+            Integer dnsServerId = idDnsMap.get(pingID);
+            if (dnsServerId == null) {
                 Slog.w(WWSM_TAG, "Received a Dns response with unknown ID!");
                 return HANDLED;
             }
-            ids.remove(pingID);
-            dnsCheckTries++;
+
+            idDnsMap.remove(pingID);
             if (pingResponseTime >= 0)
-                dnsCheckSuccesses++;
+                dnsCheckSuccesses[dnsServerId]++;
 
             if (DBG) {
                 if (pingResponseTime >= 0) {
-                    dnsCheckLogStr += "|" + pingResponseTime;
+                    dnsResponseStrs[dnsServerId] += "|" + pingResponseTime;
                 } else {
-                    dnsCheckLogStr += "|x";
+                    dnsResponseStrs[dnsServerId] += "|x";
                 }
             }
 
-            if (VDBG) {
-                Slog.v(WWSM_TAG, dnsCheckLogStr);
-            }
-
             /**
              * After a full ping count, if we have more responses than this
              * cutoff, the outcome is success; else it is 'failure'.
@@ -723,10 +728,10 @@
              * Our final success count will be at least this big, so we're
              * guaranteed to succeed.
              */
-            if (dnsCheckSuccesses >= mMinDnsResponses) {
+            if (dnsCheckSuccesses[dnsServerId] >= mMinDnsResponses) {
                 // DNS CHECKS OK, NOW WALLED GARDEN
                 if (DBG) {
-                    Slog.d(WWSM_TAG, dnsCheckLogStr + "|  SUCCESS");
+                    Slog.d(WWSM_TAG, makeLogString() + "  SUCCESS");
                 }
 
                 if (!shouldCheckWalledGarden()) {
@@ -748,14 +753,9 @@
                 return HANDLED;
             }
 
-            /**
-             * Our final count will be at most the current count plus the
-             * remaining pings - we're guaranteed to fail.
-             */
-            int remainingChecks = mNumDnsPings - dnsCheckTries;
-            if (remainingChecks + dnsCheckSuccesses < mMinDnsResponses) {
+            if (idDnsMap.isEmpty()) {
                 if (DBG) {
-                    Slog.d(WWSM_TAG, dnsCheckLogStr + "|  FAILURE");
+                    Slog.d(WWSM_TAG, makeLogString() + "  FAILURE");
                 }
                 transitionTo(mDnsCheckFailureState);
                 return HANDLED;
@@ -764,12 +764,18 @@
             return HANDLED;
         }
 
+        private String makeLogString() {
+            String logStr = dnsCheckLogStr;
+            for (String respStr : dnsResponseStrs)
+                logStr += " [" + respStr + "]";
+            return logStr;
+        }
+
         @Override
         public void exit() {
             mDnsPinger.cancelPings();
         }
 
-
         private boolean shouldCheckWalledGarden() {
             if (!mWalledGardenTestEnabled) {
                 if (VDBG)
@@ -809,7 +815,8 @@
         int checkGuard = 0;
         Long lastCheckTime = null;
 
-        int curPingID = 0;
+        /** Keeps track of dns pings.  Map is from pingID to InetAddress used for ping */
+        HashMap<Integer, InetAddress> pingInfoMap = new HashMap<Integer, InetAddress>();
 
         @Override
         public void enter() {
@@ -817,7 +824,7 @@
             signalUnstable = false;
             checkGuard++;
             unstableSignalChecks = false;
-            curPingID = 0;
+            pingInfoMap.clear();
             triggerSingleDnsCheck();
         }
 
@@ -853,32 +860,37 @@
                         return HANDLED;
                     }
                     lastCheckTime = SystemClock.elapsedRealtime();
-                    curPingID = mDnsPinger.pingDnsAsync(mDnsPinger.getDns(),
-                            mDnsPingTimeoutMs, 0);
+                    pingInfoMap.clear();
+                    for (InetAddress curDns: mDnsPinger.getDnsList()) {
+                        pingInfoMap.put(mDnsPinger.pingDnsAsync(curDns, mDnsPingTimeoutMs, 0),
+                                curDns);
+                    }
                     return HANDLED;
                 case DnsPinger.DNS_PING_RESULT:
-                    if ((short) msg.arg1 != curPingID) {
-                        if (VDBG) {
-                            Slog.v(WWSM_TAG, "Received non-matching DnsPing w/ id: " +
-                                    msg.arg1);
-                        }
+                    InetAddress curDnsServer = pingInfoMap.get(msg.arg1);
+                    if (curDnsServer == null) {
                         return HANDLED;
                     }
+                    pingInfoMap.remove(msg.arg1);
                     int responseTime = msg.arg2;
                     if (responseTime >= 0) {
                         if (VDBG) {
-                            Slog.v(WWSM_TAG, "Ran a single DNS ping. Response time: "
-                                    + responseTime);
+                            Slog.v(WWSM_TAG, "Single DNS ping OK. Response time: "
+                                    + responseTime + " from DNS " + curDnsServer);
                         }
+                        pingInfoMap.clear();
 
                         checkGuard++;
                         unstableSignalChecks = false;
                         triggerSingleDnsCheck();
                     } else {
-                        if (DBG) {
-                            Slog.d(WWSM_TAG, "Single dns ping failure. Starting full checks.");
+                        if (pingInfoMap.isEmpty()) {
+                            if (DBG) {
+                                Slog.d(WWSM_TAG, "Single dns ping failure. All dns servers failed, "
+                                        + "starting full checks.");
+                            }
+                            transitionTo(mDnsCheckingState);
                         }
-                        transitionTo(mDnsCheckingState);
                     }
                     return HANDLED;
             }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index b77fd76..2d57363 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -51,14 +51,16 @@
      */
     public int groupOwnerIntent = -1;
 
-    public boolean isPersistent;
-
-    public boolean joinExistingGroup;
-
     /**
-     * Channel frequency in MHz
+     * Indicates whether the configuration is saved
      */
-    public int channel;
+    public enum Persist {
+        SYSTEM_DEFAULT,
+        YES,
+        NO
+    }
+
+    public Persist persist = Persist.SYSTEM_DEFAULT;
 
     public WifiP2pConfig() {
         //set defaults
@@ -112,9 +114,7 @@
         sbuf.append("\n address: ").append(deviceAddress);
         sbuf.append("\n wps: ").append(wpsConfig);
         sbuf.append("\n groupOwnerIntent: ").append(groupOwnerIntent);
-        sbuf.append("\n isPersistent: ").append(isPersistent);
-        sbuf.append("\n joinExistingGroup: ").append(joinExistingGroup);
-        sbuf.append("\n channel: ").append(channel);
+        sbuf.append("\n persist: ").append(persist.toString());
         return sbuf.toString();
     }
 
@@ -136,9 +136,7 @@
         dest.writeString(deviceAddress);
         dest.writeParcelable(wpsConfig, flags);
         dest.writeInt(groupOwnerIntent);
-        dest.writeInt(isPersistent ? 1 : 0);
-        dest.writeInt(joinExistingGroup ? 1 : 0);
-        dest.writeInt(channel);
+        dest.writeString(persist.name());
     }
 
     /** Implement the Parcelable interface {@hide} */
@@ -150,9 +148,7 @@
                 config.deviceAddress = in.readString();
                 config.wpsConfig = (WpsConfiguration) in.readParcelable(null);
                 config.groupOwnerIntent = in.readInt();
-                config.isPersistent = (in.readInt() == 1);
-                config.joinExistingGroup = (in.readInt() == 1);
-                config.channel = in.readInt();
+                config.persist = Persist.valueOf(in.readString());
                 return config;
             }
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
index 4ec23b8..50f624a 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
@@ -51,8 +51,10 @@
         }
     }
 
-    public void clear() {
+    public boolean clear() {
+        if (mDevices.isEmpty()) return false;
         mDevices.clear();
+        return true;
     }
 
     public void add(WifiP2pDevice device) {
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pStatus.aidl b/wifi/java/android/net/wifi/p2p/WifiP2pInfo.aidl
similarity index 95%
rename from wifi/java/android/net/wifi/p2p/WifiP2pStatus.aidl
rename to wifi/java/android/net/wifi/p2p/WifiP2pInfo.aidl
index 7bab5d3..a347148 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pStatus.aidl
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pInfo.aidl
@@ -16,4 +16,4 @@
 
 package android.net.wifi.p2p;
 
-parcelable WifiP2pStatus;
+parcelable WifiP2pInfo;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java
new file mode 100644
index 0000000..9dc2fbf
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * A class representing connection info on Wi-fi P2p
+ * @hide
+ */
+public class WifiP2pInfo implements Parcelable {
+
+    public boolean groupFormed;
+
+    public boolean isGroupOwner;
+
+    public InetAddress groupOwnerAddress;
+
+    public WifiP2pInfo() {
+    }
+
+    public String toString() {
+        StringBuffer sbuf = new StringBuffer();
+        sbuf.append("groupFormed: ").append(groupFormed)
+            .append("isGroupOwner: ").append(isGroupOwner)
+            .append("groupOwnerAddress: ").append(groupOwnerAddress);
+        return sbuf.toString();
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** copy constructor {@hide} */
+    public WifiP2pInfo(WifiP2pInfo source) {
+        if (source != null) {
+            groupFormed = source.groupFormed;
+            isGroupOwner = source.isGroupOwner;
+            groupOwnerAddress = source.groupOwnerAddress;
+       }
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeByte(groupFormed ? (byte)1 : (byte)0);
+        dest.writeByte(isGroupOwner ? (byte)1 : (byte)0);
+
+        if (groupOwnerAddress != null) {
+            dest.writeByte((byte)1);
+            dest.writeByteArray(groupOwnerAddress.getAddress());
+        } else {
+            dest.writeByte((byte)0);
+        }
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WifiP2pInfo> CREATOR =
+        new Creator<WifiP2pInfo>() {
+            public WifiP2pInfo createFromParcel(Parcel in) {
+                WifiP2pInfo info = new WifiP2pInfo();
+                info.groupFormed = (in.readByte() == 1);
+                info.isGroupOwner = (in.readByte() == 1);
+                if (in.readByte() == 1) {
+                    try {
+                        info.groupOwnerAddress = InetAddress.getByAddress(in.createByteArray());
+                    } catch (UnknownHostException e) {}
+                }
+                return info;
+            }
+
+            public WifiP2pInfo[] newArray(int size) {
+                return new WifiP2pInfo[size];
+            }
+        };
+}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index cc1f062..25daf1c 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -95,6 +95,12 @@
         "android.net.wifi.CONNECTION_STATE_CHANGE";
 
     /**
+     * The lookup key for a {@link android.net.wifi.p2p.WifiP2pInfo} object
+     * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
+     */
+    public static final String EXTRA_WIFI_P2P_INFO = "wifiP2pInfo";
+
+    /**
      * The lookup key for a {@link android.net.NetworkInfo} object associated with the
      * Wi-Fi network. Retrieve with
      * {@link android.content.Intent#getParcelableExtra(String)}.
@@ -145,57 +151,38 @@
     public static final int ENABLE_P2P_FAILED                       = BASE + 2;
     public static final int ENABLE_P2P_SUCCEEDED                    = BASE + 3;
 
-    /* arg1 on ENABLE_P2P_FAILED indicates a reason for failure */
+    public static final int DISABLE_P2P                             = BASE + 4;
+    public static final int DISABLE_P2P_FAILED                      = BASE + 5;
+    public static final int DISABLE_P2P_SUCCEEDED                   = BASE + 6;
+
+    public static final int DISCOVER_PEERS                          = BASE + 7;
+    public static final int DISCOVER_PEERS_FAILED                   = BASE + 8;
+    public static final int DISCOVER_PEERS_SUCCEEDED                = BASE + 9;
+
+    public static final int CONNECT                                 = BASE + 10;
+    public static final int CONNECT_FAILED                          = BASE + 11;
+    public static final int CONNECT_SUCCEEDED                       = BASE + 12;
+
+    public static final int CREATE_GROUP                            = BASE + 13;
+    public static final int CREATE_GROUP_FAILED                     = BASE + 14;
+    public static final int CREATE_GROUP_SUCCEEDED                  = BASE + 15;
+
+    public static final int REMOVE_GROUP                            = BASE + 16;
+    public static final int REMOVE_GROUP_FAILED                     = BASE + 17;
+    public static final int REMOVE_GROUP_SUCCEEDED                  = BASE + 18;
+
+    public static final int REQUEST_PEERS                           = BASE + 19;
+    public static final int RESPONSE_PEERS                          = BASE + 20;
+
+    public static final int REQUEST_CONNECTION_INFO                 = BASE + 21;
+    public static final int RESPONSE_CONNECTION_INFO                = BASE + 22;
+
+    /* arg1 values on response messages from the framework */
     public static final int P2P_UNSUPPORTED     = 1;
 
-    public static final int DISABLE_P2P                             = BASE + 5;
-    public static final int DISABLE_P2P_FAILED                      = BASE + 6;
-    public static final int DISABLE_P2P_SUCCEEDED                   = BASE + 7;
-
-    public static final int START_LISTEN_MODE                       = BASE + 9;
-    public static final int START_LISTEN_FAILED                     = BASE + 10;
-    public static final int START_LISTEN_SUCCEEDED                  = BASE + 11;
-
-    public static final int DISCOVER_PEERS                          = BASE + 13;
-    public static final int DISCOVER_PEERS_FAILED                   = BASE + 14;
-    public static final int DISCOVER_PEERS_SUCCEDED                 = BASE + 15;
-
-    public static final int CANCEL_DISCOVER_PEERS                   = BASE + 17;
-    public static final int CANCEL_DISCOVER_PEERS_FAILED            = BASE + 18;
-    public static final int CANCEL_DISCOVER_PEERS_SUCCEDED          = BASE + 19;
-
-    public static final int CONNECT                                 = BASE + 21;
-    public static final int CONNECT_FAILED                          = BASE + 22;
-    public static final int CONNECT_SUCCEEDED                       = BASE + 23;
-
-    public static final int CANCEL_CONNECT                          = BASE + 25;
-    public static final int CANCEL_CONNECT_FAILED                   = BASE + 26;
-    public static final int CANCEL_CONNECT_SUCCEDED                 = BASE + 27;
-
-    public static final int REJECT                                  = BASE + 28;
-    public static final int REJECT_FAILED                           = BASE + 29;
-    public static final int REJECT_SUCCEEDED                        = BASE + 30;
-
-    public static final int CREATE_GROUP                            = BASE + 31;
-    public static final int CREATE_GROUP_FAILED                     = BASE + 32;
-    public static final int CREATE_GROUP_SUCCEEDED                  = BASE + 33;
-
-    public static final int REMOVE_GROUP                            = BASE + 34;
-    public static final int REMOVE_GROUP_FAILED                     = BASE + 35;
-    public static final int REMOVE_GROUP_SUCCEEDED                  = BASE + 36;
-
-    public static final int REQUEST_SETTINGS                        = BASE + 37;
-    public static final int RESPONSE_SETTINGS                       = BASE + 38;
-
-    public static final int REQUEST_PEERS                           = BASE + 39;
-    public static final int RESPONSE_PEERS                          = BASE + 40;
-
-    public static final int REQUEST_CONNECTION_STATUS               = BASE + 41;
-    public static final int RESPONSE_CONNECTION_STATUS              = BASE + 42;
-
-    public static final int WPS_PBC                                 = BASE + 43;
-    public static final int WPS_PIN                                 = BASE + 44;
-    public static final int WPS_PIN_AVAILABLE                       = BASE + 45;
+    public static final int WPS_PBC                                 = BASE + 23;
+    public static final int WPS_PIN                                 = BASE + 24;
+    public static final int WPS_PIN_AVAILABLE                       = BASE + 25;
 
     /**
      * Create a new WifiP2pManager instance. Applications use
@@ -269,17 +256,6 @@
     }
 
     /**
-     * Set device in listen mode. This will make the device discoverable by
-     * another peer.
-     * A dialog to the user is thrown to request his permission since it can
-     * have a significant impact on power consumption
-     */
-     public void setListenState(Channel c, int timeout) {
-        if (c == null) return;
-        c.mAsyncChannel.sendMessage(START_LISTEN_MODE, timeout);
-     }
-
-    /**
      * Initiates peer discovery
      */
     public void discoverPeers(Channel c) {
@@ -288,22 +264,6 @@
     }
 
     /**
-     * Initiates peer discovery with a timeout
-     */
-    public void discoverPeers(Channel c, int timeout) {
-        if (c == null) return;
-        c.mAsyncChannel.sendMessage(DISCOVER_PEERS, timeout);
-    }
-
-    /**
-     * Cancel any existing peer discovery operation
-     */
-    public void cancelPeerDiscovery(Channel c) {
-        if (c == null) return;
-        c.mAsyncChannel.sendMessage(CANCEL_DISCOVER_PEERS);
-    }
-
-    /**
      * Start a p2p connection
      *
      * @param peer Configuration described in a {@link WifiP2pConfig} object.
@@ -314,14 +274,6 @@
     }
 
     /**
-     * Cancel any ongoing negotiation or disconnect from an existing group
-     */
-    public void disconnect(Channel c) {
-        if (c == null) return;
-        c.mAsyncChannel.sendMessage(CANCEL_CONNECT);
-    }
-
-    /**
      * Create a p2p group. This is essentially an access point that can accept
      * client connections.
      */
@@ -340,15 +292,6 @@
     }
 
     /**
-     * Request current p2p settings. This returns a RESPONSE_SETTINGS on the source
-     * handler.
-     */
-    public void requestP2pSettings(Channel c) {
-        if (c == null) return;
-        c.mAsyncChannel.sendMessage(REQUEST_SETTINGS);
-    }
-
-    /**
      * Request the list of peers. This returns a RESPONSE_PEERS on the source
      * handler.
      */
@@ -365,12 +308,19 @@
     }
 
     /**
-     * Request device connection status. This returns a RESPONSE_CONNECTION_STATUS on
+     * Request device connection info. This returns a RESPONSE_CONNECTION_INFO on
      * the source handler.
      */
-    public void requestConnectionStatus(Channel c) {
+    public void requestConnectionInfo(Channel c) {
         if (c == null) return;
-        c.mAsyncChannel.sendMessage(REQUEST_CONNECTION_STATUS);
+        c.mAsyncChannel.sendMessage(REQUEST_CONNECTION_INFO);
+    }
+
+    /**
+     * Fetch p2p connection status from a RESPONSE_CONNECTION_INFO message
+     */
+    public WifiP2pInfo connectionInfoInResponse(Message msg) {
+        return (WifiP2pInfo) msg.obj;
     }
 
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 4447971..adf13be4 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -93,12 +93,25 @@
     private int mWifiApState = WifiManager.WIFI_AP_STATE_DISABLED;
 
     private P2pStateMachine mP2pStateMachine;
-    private AsyncChannel mReplyChannel = new AsyncChannel();;
+    private AsyncChannel mReplyChannel = new AsyncChannel();
     private AsyncChannel mWifiChannel;
 
-    private static final int GROUP_NEGOTIATION_WAIT_TIME_MS = 60 * 1000;
+    /* Two minutes comes from the wpa_supplicant setting */
+    private static final int GROUP_NEGOTIATION_WAIT_TIME_MS = 120 * 1000;
     private static int mGroupNegotiationTimeoutIndex = 0;
 
+    /**
+     * Delay between restarts upon failure to setup connection with supplicant
+     */
+    private static final int P2P_RESTART_INTERVAL_MSECS = 5000;
+
+    /**
+     * Number of times we attempt to restart p2p
+     */
+    private static final int P2P_RESTART_TRIES = 5;
+
+    private int mP2pRestartCount = 0;
+
     private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
 
     /* Message sent to WifiStateMachine to indicate p2p enable is pending */
@@ -115,14 +128,17 @@
     private final boolean mP2pSupported;
 
     private NetworkInfo mNetworkInfo;
-    private LinkProperties mLinkProperties;
+
+    /* Is chosen as a unique range to avoid conflict with
+       the range defined in Tethering.java */
+    private static final String[] DHCP_RANGE = {"192.168.49.2", "192.168.49.254"};
+    private static final String SERVER_ADDRESS = "192.168.49.1";
 
     public WifiP2pService(Context context) {
         mContext = context;
 
         mInterface = SystemProperties.get("wifi.interface", "wlan0");
         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, "");
-        mLinkProperties = new LinkProperties();
 
         mP2pSupported = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_wifi_p2p_support);
@@ -205,6 +221,7 @@
         private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState();
         private P2pDisablingState mP2pDisablingState = new P2pDisablingState();
         private P2pDisabledState mP2pDisabledState = new P2pDisabledState();
+        private WaitForUserActionState mWaitForUserActionState = new WaitForUserActionState();
         private WaitForWifiDisableState mWaitForWifiDisableState = new WaitForWifiDisableState();
         private P2pEnablingState mP2pEnablingState = new P2pEnablingState();
         private P2pEnabledState mP2pEnabledState = new P2pEnabledState();
@@ -216,11 +233,9 @@
         private WifiMonitor mWifiMonitor = new WifiMonitor(this);
 
         private WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
+        private WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
         private WifiP2pGroup mGroup;
 
-        // Saved enable request message so the state machine can send an appropriate response
-        private Message mSavedEnableRequestMessage;
-
         // Saved WifiP2pConfig from GO negotiation request
         private WifiP2pConfig mSavedGoNegotiationConfig;
 
@@ -237,7 +252,8 @@
                 addState(mP2pNotSupportedState, mDefaultState);
                 addState(mP2pDisablingState, mDefaultState);
                 addState(mP2pDisabledState, mDefaultState);
-                addState(mWaitForWifiDisableState, mDefaultState);
+                    addState(mWaitForUserActionState, mP2pDisabledState);
+                    addState(mWaitForWifiDisableState, mP2pDisabledState);
                 addState(mP2pEnablingState, mDefaultState);
                 addState(mP2pEnabledState, mDefaultState);
                     addState(mInactiveState, mP2pEnabledState);
@@ -251,27 +267,26 @@
             }
         }
 
-    // TODO: Respond to every p2p request with success/failure
     class DefaultState extends State {
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
                     if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
-                        if (DBG) Slog.d(TAG, "Full connection with WifiStateMachine established");
+                        if (DBG) logd("Full connection with WifiStateMachine established");
                         mWifiChannel = (AsyncChannel) message.obj;
                     } else {
-                        Slog.e(TAG, "Full connection failure, error = " + message.arg1);
+                        loge("Full connection failure, error = " + message.arg1);
                         mWifiChannel = null;
                     }
                     break;
 
                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
                     if (message.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
-                        Slog.e(TAG, "Send failed, client connection lost");
+                        loge("Send failed, client connection lost");
                     } else {
-                        Slog.e(TAG, "Client connection lost with reason: " + message.arg1);
+                        loge("Client connection lost with reason: " + message.arg1);
                     }
                     mWifiChannel = null;
                     break;
@@ -286,47 +301,35 @@
                     deferMessage(message);
                     break;
                 case WifiP2pManager.ENABLE_P2P:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED);
+                    replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED);
                     break;
                 case WifiP2pManager.DISABLE_P2P:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED);
-                    break;
-                case WifiP2pManager.START_LISTEN_MODE:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED);
+                    replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED);
                     break;
                 case WifiP2pManager.DISCOVER_PEERS:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED);
-                    break;
-                case WifiP2pManager.CANCEL_DISCOVER_PEERS:
-                    mReplyChannel.replyToMessage(message,
-                            WifiP2pManager.CANCEL_DISCOVER_PEERS_FAILED);
+                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED);
                     break;
                 case WifiP2pManager.CONNECT:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
-                    break;
-                case WifiP2pManager.CANCEL_CONNECT:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED);
-                    break;
-                case WifiP2pManager.REJECT:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.REJECT_FAILED);
+                    replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
                     break;
                 case WifiP2pManager.CREATE_GROUP:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED);
+                    replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED);
                     break;
                 case WifiP2pManager.REMOVE_GROUP:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED);
+                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED);
                     break;
-                // TODO: fix
-                case WifiP2pManager.REQUEST_SETTINGS:
                 case WifiP2pManager.REQUEST_PEERS:
-                case WifiP2pManager.REQUEST_CONNECTION_STATUS:
+                    replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, mPeers);
+                    break;
+                case WifiP2pManager.REQUEST_CONNECTION_INFO:
+                    replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, mWifiP2pInfo);
                     break;
                 // Ignore
                 case WIFI_DISABLE_USER_ACCEPT:
                 case GROUP_NEGOTIATION_TIMED_OUT:
                     break;
                 default:
-                    Slog.e(TAG, "Unhandled message " + message);
+                    loge("Unhandled message " + message);
                     return NOT_HANDLED;
             }
             return HANDLED;
@@ -339,17 +342,33 @@
             switch (message.what) {
                 // Allow Wi-Fi to proceed
                 case WifiStateMachine.WIFI_ENABLE_PENDING:
-                    mReplyChannel.replyToMessage(message, WIFI_ENABLE_PROCEED);
+                    replyToMessage(message, WIFI_ENABLE_PROCEED);
                     break;
                 case WifiP2pManager.ENABLE_P2P:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED,
+                    replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED,
                             WifiP2pManager.P2P_UNSUPPORTED);
                     break;
                 case WifiP2pManager.DISABLE_P2P:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED,
+                    replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED,
                             WifiP2pManager.P2P_UNSUPPORTED);
                     break;
-                default:
+                case WifiP2pManager.DISCOVER_PEERS:
+                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
+                            WifiP2pManager.P2P_UNSUPPORTED);
+                    break;
+                case WifiP2pManager.CONNECT:
+                    replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
+                            WifiP2pManager.P2P_UNSUPPORTED);
+                    break;
+                case WifiP2pManager.CREATE_GROUP:
+                    replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
+                            WifiP2pManager.P2P_UNSUPPORTED);
+                    break;
+                case WifiP2pManager.REMOVE_GROUP:
+                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
+                            WifiP2pManager.P2P_UNSUPPORTED);
+                    break;
+               default:
                     return NOT_HANDLED;
             }
             return HANDLED;
@@ -359,17 +378,27 @@
     class P2pDisablingState extends State {
         @Override
         public void enter() {
-            if (DBG) Slog.d(TAG, getName());
-            transitionTo(mP2pDisabledState);
+            if (DBG) logd(getName());
+            logd("stopping supplicant");
+            if (!WifiNative.stopSupplicant()) {
+                loge("Failed to stop supplicant, issue kill");
+                WifiNative.killSupplicant();
+            }
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 case WifiMonitor.SUP_DISCONNECTION_EVENT:
+                    logd("Supplicant connection lost");
+                    WifiNative.closeSupplicantConnection();
                     transitionTo(mP2pDisabledState);
                     break;
+                case WifiP2pManager.ENABLE_P2P:
+                case WifiP2pManager.DISABLE_P2P:
+                    deferMessage(message);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -381,23 +410,22 @@
     class P2pDisabledState extends State {
        @Override
         public void enter() {
-            if (DBG) Slog.d(TAG, getName());
+            if (DBG) logd(getName());
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 case WifiP2pManager.ENABLE_P2P:
-                    mSavedEnableRequestMessage = Message.obtain(message);
                     OnClickListener listener = new OnClickListener() {
                         @Override
                         public void onClick(DialogInterface dialog, int which) {
                             if (which == DialogInterface.BUTTON_POSITIVE) {
                                 sendMessage(WIFI_DISABLE_USER_ACCEPT);
                             } else {
-                                mReplyChannel.replyToMessage(mSavedEnableRequestMessage,
-                                        WifiP2pManager.ENABLE_P2P_FAILED);
+                                logd("User rejected enabling p2p");
+                                //ignore
                             }
                         }
                     };
@@ -414,17 +442,43 @@
                             .create();
                         dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
                         dialog.show();
+                        transitionTo(mWaitForUserActionState);
                     } else {
                         mWifiChannel.sendMessage(P2P_ENABLE_PENDING);
                         transitionTo(mWaitForWifiDisableState);
                     }
+                    replyToMessage(message, WifiP2pManager.ENABLE_P2P_SUCCEEDED);
                     break;
+                case WifiP2pManager.DISABLE_P2P:
+                    replyToMessage(message, WifiP2pManager.DISABLE_P2P_SUCCEEDED);
+                    break;
+                case WifiStateMachine.WIFI_ENABLE_PENDING:
+                    replyToMessage(message, WIFI_ENABLE_PROCEED);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    class WaitForUserActionState extends State {
+        @Override
+        public void enter() {
+            if (DBG) logd(getName());
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) logd(getName() + message.toString());
+            switch (message.what) {
                 case WIFI_DISABLE_USER_ACCEPT:
                     mWifiChannel.sendMessage(P2P_ENABLE_PENDING);
                     transitionTo(mWaitForWifiDisableState);
                     break;
-                case WifiStateMachine.WIFI_ENABLE_PENDING:
-                    mReplyChannel.replyToMessage(message, WIFI_ENABLE_PROCEED);
+                case WifiP2pManager.ENABLE_P2P:
+                case WifiP2pManager.DISABLE_P2P:
+                    deferMessage(message);
                     break;
                 default:
                     return NOT_HANDLED;
@@ -436,31 +490,42 @@
     class WaitForWifiDisableState extends State {
         @Override
         public void enter() {
-            if (DBG) Slog.d(TAG, getName());
+            if (DBG) logd(getName());
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 case WifiStateMachine.P2P_ENABLE_PROCEED:
                     try {
                         mNwService.wifiFirmwareReload(mInterface, "P2P");
                     } catch (Exception e) {
-                        Slog.e(TAG, "Failed to reload p2p firmware " + e);
+                        loge("Failed to reload p2p firmware " + e);
                         // continue
                     }
+
+                    //A runtime crash can leave the interface up and
+                    //this affects p2p when supplicant starts up.
+                    //Ensure interface is down before a supplicant start.
+                    try {
+                        mNwService.setInterfaceDown(mInterface);
+                    } catch (Exception e) {
+                        if (DBG) Slog.w(TAG, "Unable to bring down wlan interface: " + e);
+                    }
+
                     if (WifiNative.startSupplicant()) {
-                        Slog.d(TAG, "Wi-fi Direct start successful");
                         mWifiMonitor.startMonitoring();
                         transitionTo(mP2pEnablingState);
                     } else {
                         notifyP2pEnableFailure();
-                        mReplyChannel.replyToMessage(mSavedEnableRequestMessage,
-                                WifiP2pManager.ENABLE_P2P_FAILED);
                         transitionTo(mP2pDisabledState);
                     }
                     break;
+                case WifiP2pManager.ENABLE_P2P:
+                case WifiP2pManager.DISABLE_P2P:
+                    deferMessage(message);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -471,22 +536,32 @@
     class P2pEnablingState extends State {
         @Override
         public void enter() {
-            if (DBG) Slog.d(TAG, getName());
+            if (DBG) logd(getName());
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 case WifiMonitor.SUP_CONNECTION_EVENT:
-                    mReplyChannel.replyToMessage(mSavedEnableRequestMessage,
-                            WifiP2pManager.ENABLE_P2P_SUCCEEDED);
+                    logd("P2p start successful");
                     transitionTo(mInactiveState);
                     break;
-                case WifiP2pManager.DISABLE_P2P:
-                    //TODO: fix
-                    WifiNative.killSupplicant();
+                case WifiMonitor.SUP_DISCONNECTION_EVENT:
+                    if (++mP2pRestartCount <= P2P_RESTART_TRIES) {
+                        loge("Failed to start p2p, retry");
+                        WifiNative.killSupplicant();
+                        sendMessageDelayed(WifiP2pManager.ENABLE_P2P, P2P_RESTART_INTERVAL_MSECS);
+                    } else {
+                        loge("Failed " + mP2pRestartCount + " times to start p2p, quit ");
+                        mP2pRestartCount = 0;
+                    }
                     transitionTo(mP2pDisabledState);
+                    break;
+                case WifiP2pManager.ENABLE_P2P:
+                case WifiP2pManager.DISABLE_P2P:
+                    deferMessage(message);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -497,27 +572,32 @@
     class P2pEnabledState extends State {
         @Override
         public void enter() {
-            if (DBG) Slog.d(TAG, getName());
+            if (DBG) logd(getName());
             sendP2pStateChangedBroadcast(true);
             mNetworkInfo.setIsAvailable(true);
+            //Start listening for new connections
+            WifiNative.p2pListen();
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
+                case WifiP2pManager.ENABLE_P2P:
+                    replyToMessage(message, WifiP2pManager.ENABLE_P2P_SUCCEEDED);
+                    break;
                 case WifiP2pManager.DISABLE_P2P:
-                    // TODO: use stopSupplicant after control channel fixed
-                    WifiNative.killSupplicant();
+                    if (mPeers.clear()) sendP2pPeersChangedBroadcast();
+                    replyToMessage(message, WifiP2pManager.DISABLE_P2P_SUCCEEDED);
                     transitionTo(mP2pDisablingState);
                     break;
                 case WifiP2pManager.DISCOVER_PEERS:
                     int timeout = message.arg1;
-                    WifiNative.p2pFlush();
-                    WifiNative.p2pFind(timeout);
-                   break;
-                case WifiP2pManager.REQUEST_PEERS:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, mPeers);
+                    if (WifiNative.p2pFind(timeout)) {
+                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);
+                    } else {
+                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED);
+                    }
                     break;
                 case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
                     WifiP2pDevice device = (WifiP2pDevice) message.obj;
@@ -529,23 +609,34 @@
                     if (mPeers.remove(device)) sendP2pPeersChangedBroadcast();
                     break;
                 case WifiP2pManager.CONNECT:
-                    if (DBG) Slog.d(TAG, getName() + " sending connect");
+                    if (DBG) logd(getName() + " sending connect");
                     mSavedConnectConfig = (WifiP2pConfig) message.obj;
-                    String pin = WifiNative.p2pConnect(mSavedConnectConfig);
-                    try {
-                        Integer.parseInt(pin);
-                        notifyWpsPin(pin, mSavedConnectConfig.deviceAddress);
-                    } catch (NumberFormatException ignore) {
-                        // do nothing if p2pConnect did not return a pin
+                    int netId = configuredNetworkId(mSavedConnectConfig.deviceAddress);
+                    if (netId >= 0) {
+                        //TODO: if failure, remove config and do a regular p2pConnect()
+                        WifiNative.p2pReinvoke(netId, mSavedConnectConfig.deviceAddress);
+                    } else {
+                        //TODO: Check if device is a GO and "join"
+                        String pin = WifiNative.p2pConnect(mSavedConnectConfig, false);
+                        try {
+                            Integer.parseInt(pin);
+                            notifyWpsPin(pin, mSavedConnectConfig.deviceAddress);
+                        } catch (NumberFormatException ignore) {
+                            // do nothing if p2pConnect did not return a pin
+                        }
                     }
                     updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.INVITED);
                     sendP2pPeersChangedBroadcast();
+                    replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
                     transitionTo(mGroupNegotiationState);
                     break;
-                case WifiP2pManager.REJECT:
-                    if (DBG) Slog.d(TAG, getName() + " sending reject");
-                    WifiNative.p2pReject((String) message.obj);
-                    break;
+                case WifiMonitor.SUP_DISCONNECTION_EVENT:  /* Supplicant died */
+                    loge("Connection lost, restart p2p");
+                    WifiNative.killSupplicant();
+                    WifiNative.closeSupplicantConnection();
+                    if (mPeers.clear()) sendP2pPeersChangedBroadcast();
+                    transitionTo(mP2pDisabledState);
+                    sendMessageDelayed(WifiP2pManager.ENABLE_P2P, P2P_RESTART_INTERVAL_MSECS);
                 default:
                     return NOT_HANDLED;
             }
@@ -561,28 +652,30 @@
 
     class InactiveState extends State {
         @Override public void enter() {
-            if (DBG) Slog.d(TAG, getName());
+            if (DBG) logd(getName());
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 case WifiMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT:
                     mSavedGoNegotiationConfig = (WifiP2pConfig) message.obj;
                     notifyP2pGoNegotationRequest(mSavedGoNegotiationConfig);
                     break;
                 case WifiP2pManager.CREATE_GROUP:
-                    WifiNative.p2pGroupAdd();
+                    if (WifiNative.p2pGroupAdd()) {
+                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_SUCCEEDED);
+                    } else {
+                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED);
+                    }
                     transitionTo(mGroupNegotiationState);
                     break;
                 case WifiMonitor.P2P_INVITATION_RECEIVED_EVENT:
                     WifiP2pGroup group = (WifiP2pGroup) message.obj;
                     notifyP2pInvitationReceived(group);
                     break;
-                case WifiP2pManager.REQUEST_PEERS:
-                    return NOT_HANDLED;
-               default:
+                default:
                     return NOT_HANDLED;
             }
             return HANDLED;
@@ -592,31 +685,32 @@
     class GroupNegotiationState extends State {
         @Override
         public void enter() {
-            if (DBG) Slog.d(TAG, getName());
+            if (DBG) logd(getName());
             sendMessageDelayed(obtainMessage(GROUP_NEGOTIATION_TIMED_OUT,
                     ++mGroupNegotiationTimeoutIndex, 0), GROUP_NEGOTIATION_WAIT_TIME_MS);
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 // We ignore these right now, since we get a GROUP_STARTED notification
                 // afterwards
                 case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:
                 case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:
-                    if (DBG) Slog.d(TAG, getName() + " go success");
+                    if (DBG) logd(getName() + " go success");
                     break;
                 case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
                 case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
-                    if (DBG) Slog.d(TAG, getName() + " go failure");
+                    if (DBG) logd(getName() + " go failure");
                     updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.FAILED);
                     mSavedConnectConfig = null;
+                    sendP2pPeersChangedBroadcast();
                     transitionTo(mInactiveState);
                     break;
                 case WifiMonitor.P2P_GROUP_STARTED_EVENT:
                     mGroup = (WifiP2pGroup) message.obj;
-                    if (DBG) Slog.d(TAG, getName() + " group started");
+                    if (DBG) logd(getName() + " group started");
                     if (mGroup.isGroupOwner()) {
                         startDhcpServer(mGroup.getInterface());
                     } else {
@@ -629,14 +723,12 @@
                     }
                     transitionTo(mGroupCreatedState);
                     break;
-                case WifiP2pManager.CANCEL_CONNECT:
-                    // TODO: fix
-                    break;
                 case GROUP_NEGOTIATION_TIMED_OUT:
                     if (mGroupNegotiationTimeoutIndex == message.arg1) {
-                        if (DBG) Slog.d(TAG, "Group negotiation timed out");
+                        if (DBG) logd("Group negotiation timed out");
                         updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.FAILED);
                         mSavedConnectConfig = null;
+                        sendP2pPeersChangedBroadcast();
                         transitionTo(mInactiveState);
                     }
                     break;
@@ -650,17 +742,19 @@
     class GroupCreatedState extends State {
         @Override
         public void enter() {
-            if (DBG) Slog.d(TAG, getName());
+            if (DBG) logd(getName());
             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
 
+            //DHCP server has already been started if I am a group owner
             if (mGroup.isGroupOwner()) {
+                setWifiP2pInfoOnGroupFormation(SERVER_ADDRESS);
                 sendP2pConnectionChangedBroadcast();
             }
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 case WifiMonitor.AP_STA_CONNECTED_EVENT:
                     //After a GO setup, STA connected event comes with interface address
@@ -668,7 +762,7 @@
                     String deviceAddress = getDeviceAddress(interfaceAddress);
                     mGroup.addClient(deviceAddress);
                     updateDeviceStatus(deviceAddress, Status.CONNECTED);
-                    if (DBG) Slog.d(TAG, getName() + " ap sta connected");
+                    if (DBG) logd(getName() + " ap sta connected");
                     sendP2pPeersChangedBroadcast();
                     break;
                 case WifiMonitor.AP_STA_DISCONNECTED_EVENT:
@@ -676,40 +770,37 @@
                     deviceAddress = getDeviceAddress(interfaceAddress);
                     updateDeviceStatus(deviceAddress, Status.AVAILABLE);
                     if (mGroup.removeClient(deviceAddress)) {
-                        if (DBG) Slog.d(TAG, "Removed client " + deviceAddress);
-                        if (mGroup.isClientListEmpty()) {
-                            Slog.d(TAG, "Client list empty, killing p2p connection");
-                            sendMessage(WifiP2pManager.REMOVE_GROUP);
-                        } else {
-                            // Just send a notification
-                            sendP2pPeersChangedBroadcast();
-                        }
+                        if (DBG) logd("Removed client " + deviceAddress);
+                        sendP2pPeersChangedBroadcast();
                     } else {
-                        if (DBG) Slog.d(TAG, "Failed to remove client " + deviceAddress);
+                        if (DBG) logd("Failed to remove client " + deviceAddress);
                         for (WifiP2pDevice c : mGroup.getClientList()) {
-                            if (DBG) Slog.d(TAG,"client " + c.deviceAddress);
+                            if (DBG) logd("client " + c.deviceAddress);
                         }
                     }
-                    if (DBG) Slog.e(TAG, getName() + " ap sta disconnected");
+                    if (DBG) loge(getName() + " ap sta disconnected");
                     break;
                 case DhcpStateMachine.CMD_POST_DHCP_ACTION:
                     DhcpInfoInternal dhcpInfo = (DhcpInfoInternal) message.obj;
-                    if (DBG) Slog.d(TAG, "DhcpInfo: " + dhcpInfo);
-                    if (dhcpInfo != null) {
-                        mLinkProperties = dhcpInfo.makeLinkProperties();
-                        mLinkProperties.setInterfaceName(mGroup.getInterface());
+                    if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS &&
+                            dhcpInfo != null) {
+                        if (DBG) logd("DhcpInfo: " + dhcpInfo);
+                        setWifiP2pInfoOnGroupFormation(dhcpInfo.serverAddress);
                         sendP2pConnectionChangedBroadcast();
+                    } else {
+                        WifiNative.p2pGroupRemove(mGroup.getInterface());
                     }
                     break;
-                //disconnect & remove group have same effect when connected
-                case WifiP2pManager.CANCEL_CONNECT:
                 case WifiP2pManager.REMOVE_GROUP:
-                    if (DBG) Slog.e(TAG, getName() + " remove group");
-                    WifiNative.p2pFlush();
-                    WifiNative.p2pGroupRemove(mGroup.getInterface());
+                    if (DBG) loge(getName() + " remove group");
+                    if (WifiNative.p2pGroupRemove(mGroup.getInterface())) {
+                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
+                    } else {
+                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED);
+                    }
                     break;
                 case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
-                    if (DBG) Slog.e(TAG, getName() + " group removed");
+                    if (DBG) loge(getName() + " group removed");
                     Collection <WifiP2pDevice> devices = mGroup.getClientList();
                     boolean changed = false;
                     for (WifiP2pDevice d : mPeers.getDeviceList()) {
@@ -722,7 +813,7 @@
                     if (mGroup.isGroupOwner()) {
                         stopDhcpServer();
                     } else {
-                        if (DBG) Slog.d(TAG, "stop DHCP client");
+                        if (DBG) logd("stop DHCP client");
                         mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
                         mDhcpStateMachine.quit();
                         mDhcpStateMachine = null;
@@ -735,33 +826,30 @@
                 case WifiMonitor.P2P_DEVICE_LOST_EVENT:
                     WifiP2pDevice device = (WifiP2pDevice) message.obj;
                     if (device.equals(mGroup.getOwner())) {
-                        Slog.d(TAG, "Lost the group owner, killing p2p connection");
-                        WifiNative.p2pFlush();
+                        logd("Lost the group owner, killing p2p connection");
                         WifiNative.p2pGroupRemove(mGroup.getInterface());
-                    } else if (mGroup.removeClient(device) && mGroup.isClientListEmpty()) {
-                        Slog.d(TAG, "Client list empty, killing p2p connection");
-                        WifiNative.p2pFlush();
-                        WifiNative.p2pGroupRemove(mGroup.getInterface());
+                    } else {
+                        mGroup.removeClient(device);
                     }
                     return NOT_HANDLED; // Do the regular device lost handling
                 case WifiP2pManager.DISABLE_P2P:
                     sendMessage(WifiP2pManager.REMOVE_GROUP);
                     deferMessage(message);
                     break;
-                case WifiP2pManager.DISCOVER_PEERS:
-                    int timeout = message.arg1;
-                    WifiNative.p2pFind(timeout);
-                    break;
                 case WifiP2pManager.CONNECT:
                     WifiP2pConfig config = (WifiP2pConfig) message.obj;
-                    Slog.d(TAG, "Inviting device : " + config.deviceAddress);
-                    WifiNative.p2pInvite(mGroup, config.deviceAddress);
-                    updateDeviceStatus(config.deviceAddress, Status.INVITED);
-                    sendP2pPeersChangedBroadcast();
+                    logd("Inviting device : " + config.deviceAddress);
+                    if (WifiNative.p2pInvite(mGroup, config.deviceAddress)) {
+                        updateDeviceStatus(config.deviceAddress, Status.INVITED);
+                        sendP2pPeersChangedBroadcast();
+                        replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
+                    } else {
+                        replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
+                    }
                     // TODO: figure out updating the status to declined when invitation is rejected
                     break;
                 case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
-                    Slog.d(TAG,"===> INVITATION RESULT EVENT : " + message.obj);
+                    logd("===> INVITATION RESULT EVENT : " + message.obj);
                     break;
                 case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
                     notifyP2pProvDiscPbcRequest((WifiP2pDevice) message.obj);
@@ -782,7 +870,9 @@
         }
 
         public void exit() {
+            setWifiP2pInfoOnGroupTermination();
             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
+            sendP2pConnectionChangedBroadcast();
         }
     }
 
@@ -806,52 +896,42 @@
     }
 
     private void sendP2pConnectionChangedBroadcast() {
-        if (DBG) Slog.d(TAG, "sending p2p connection changed broadcast");
+        if (DBG) logd("sending p2p connection changed broadcast");
         Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
+        intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo));
         intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
-        intent.putExtra(WifiP2pManager.EXTRA_LINK_PROPERTIES,
-                new LinkProperties (mLinkProperties));
         mContext.sendStickyBroadcast(intent);
     }
 
     private void startDhcpServer(String intf) {
-        /* Is chosen as a unique range to avoid conflict with
-           the range defined in Tethering.java */
-        String[] dhcp_range = {"192.168.49.2", "192.168.49.254"};
-        String serverAddress = "192.168.49.1";
-
-        mLinkProperties.clear();
-        mLinkProperties.setInterfaceName(mGroup.getInterface());
-
         InterfaceConfiguration ifcg = null;
         try {
             ifcg = mNwService.getInterfaceConfig(intf);
             ifcg.addr = new LinkAddress(NetworkUtils.numericToInetAddress(
-                        serverAddress), 24);
+                        SERVER_ADDRESS), 24);
             ifcg.interfaceFlags = "[up]";
             mNwService.setInterfaceConfig(intf, ifcg);
             /* This starts the dnsmasq server */
-            mNwService.startTethering(dhcp_range);
+            mNwService.startTethering(DHCP_RANGE);
         } catch (Exception e) {
-            Slog.e(TAG, "Error configuring interface " + intf + ", :" + e);
+            loge("Error configuring interface " + intf + ", :" + e);
             return;
         }
 
-        mLinkProperties.addDns(NetworkUtils.numericToInetAddress(serverAddress));
-        Slog.d(TAG, "Started Dhcp server on " + intf);
-    }
+        logd("Started Dhcp server on " + intf);
+   }
 
     private void stopDhcpServer() {
         try {
             mNwService.stopTethering();
         } catch (Exception e) {
-            Slog.e(TAG, "Error stopping Dhcp server" + e);
+            loge("Error stopping Dhcp server" + e);
             return;
         }
 
-        Slog.d(TAG, "Stopped Dhcp server");
+        logd("Stopped Dhcp server");
     }
 
     private void notifyP2pEnableFailure() {
@@ -888,7 +968,7 @@
             .setView(textEntryView)
             .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
                         public void onClick(DialogInterface dialog, int which) {
-                            if (DBG) Slog.d(TAG, getName() + " connect " + pin.getText());
+                            if (DBG) logd(getName() + " connect " + pin.getText());
 
                             if (pin.getVisibility() == View.GONE) {
                                 mSavedGoNegotiationConfig.wpsConfig.setup = Setup.PBC;
@@ -903,10 +983,8 @@
             .setNegativeButton(r.getString(R.string.cancel), new OnClickListener() {
                         @Override
                         public void onClick(DialogInterface dialog, int which) {
-                                if (DBG) Slog.d(TAG, getName() + " reject");
-                                sendMessage(WifiP2pManager.REJECT,
-                                        mSavedGoNegotiationConfig.deviceAddress);
-                                mSavedGoNegotiationConfig = null;
+                            if (DBG) logd(getName() + " ignore connect");
+                            mSavedGoNegotiationConfig = null;
                         }
                     })
             .create();
@@ -935,7 +1013,7 @@
             .setView(textEntryView)
             .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
                         public void onClick(DialogInterface dialog, int which) {
-                                if (DBG) Slog.d(TAG, getName() + " wps_pbc");
+                                if (DBG) logd(getName() + " wps_pbc");
                                 sendMessage(WifiP2pManager.WPS_PBC);
                         }
                     })
@@ -961,7 +1039,7 @@
             .setView(textEntryView)
             .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
                     public void onClick(DialogInterface dialog, int which) {
-                        if (DBG) Slog.d(TAG, getName() + " wps_pin");
+                        if (DBG) logd(getName() + " wps_pin");
                         sendMessage(WifiP2pManager.WPS_PIN, pin.getText().toString());
                     }
                     })
@@ -989,8 +1067,7 @@
                         public void onClick(DialogInterface dialog, int which) {
                                 WifiP2pConfig config = new WifiP2pConfig();
                                 config.deviceAddress = mSavedP2pGroup.getOwner().deviceAddress;
-                                config.joinExistingGroup = true;
-                                if (DBG) Slog.d(TAG, getName() + " connect to invited group");
+                                if (DBG) logd(getName() + " connect to invited group");
                                 sendMessage(WifiP2pManager.CONNECT, config);
                                 mSavedP2pGroup = null;
                         }
@@ -1014,6 +1091,23 @@
         }
     }
 
+    //TODO: implement when wpa_supplicant is fixed
+    private int configuredNetworkId(String deviceAddress) {
+        return -1;
+    }
+
+    private void setWifiP2pInfoOnGroupFormation(String serverAddress) {
+        mWifiP2pInfo.groupFormed = true;
+        mWifiP2pInfo.isGroupOwner = mGroup.isGroupOwner();
+        mWifiP2pInfo.groupOwnerAddress = NetworkUtils.numericToInetAddress(serverAddress);
+    }
+
+    private void setWifiP2pInfoOnGroupTermination() {
+        mWifiP2pInfo.groupFormed = false;
+        mWifiP2pInfo.isGroupOwner = false;
+        mWifiP2pInfo.groupOwnerAddress = null;
+    }
+
     private String getDeviceAddress(String interfaceAddress) {
         for (WifiP2pDevice d : mPeers.getDeviceList()) {
             if (interfaceAddress.equals(WifiNative.p2pGetInterfaceAddress(d.deviceAddress))) {
@@ -1023,5 +1117,25 @@
         return null;
     }
 
+    //State machine initiated requests can have replyTo set to null indicating
+    //there are no recepients, we ignore those reply actions
+    private void replyToMessage(Message msg, int what) {
+        if (msg.replyTo == null) return;
+        mReplyChannel.replyToMessage(msg, what);
+    }
+
+    private void replyToMessage(Message msg, int what, Object obj) {
+        if (msg.replyTo == null) return;
+        mReplyChannel.replyToMessage(msg, what, obj);
+    }
+
+    private void logd(String s) {
+        Slog.d(TAG, s);
+    }
+
+    private void loge(String s) {
+        Slog.e(TAG, s);
+    }
+
     }
 }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pStatus.java b/wifi/java/android/net/wifi/p2p/WifiP2pStatus.java
deleted file mode 100644
index 1c9b76c..0000000
--- a/wifi/java/android/net/wifi/p2p/WifiP2pStatus.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.p2p;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-/**
- * A class representing Wi-fi P2p status
- * @hide
- */
-public class WifiP2pStatus implements Parcelable {
-
-    //Comes from the wpa_supplicant
-    enum p2p_status_code {
-        SUCCESS,
-        FAIL_INFO_CURRENTLY_UNAVAILABLE,
-        FAIL_INCOMPATIBLE_PARAMS,
-        FAIL_LIMIT_REACHED,
-        FAIL_INVALID_PARAMS,
-        FAIL_UNABLE_TO_ACCOMMODATE,
-        FAIL_PREV_PROTOCOL_ERROR,
-        FAIL_NO_COMMON_CHANNELS,
-        FAIL_UNKNOWN_GROUP,
-        FAIL_BOTH_GO_INTENT_15,
-        FAIL_INCOMPATIBLE_PROV_METHOD,
-        FAIL_REJECTED_BY_USER
-    };
-
-    public WifiP2pStatus() {
-    }
-
-    //TODO: add support
-    public String toString() {
-        StringBuffer sbuf = new StringBuffer();
-        return sbuf.toString();
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    public int describeContents() {
-        return 0;
-    }
-
-    /** copy constructor {@hide} */
-    //TODO: implement
-    public WifiP2pStatus(WifiP2pStatus source) {
-        if (source != null) {
-       }
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    // STOPSHIP: implement
-    public void writeToParcel(Parcel dest, int flags) {
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    public static final Creator<WifiP2pStatus> CREATOR =
-        new Creator<WifiP2pStatus>() {
-            public WifiP2pStatus createFromParcel(Parcel in) {
-                WifiP2pStatus status = new WifiP2pStatus();
-                return status;
-            }
-
-            public WifiP2pStatus[] newArray(int size) {
-                return new WifiP2pStatus[size];
-            }
-        };
-}