Merge "Introduce hidden API Contacts.CONTENT_FREQUENT_URI"
diff --git a/Android.mk b/Android.mk
index 335fb73..3b0fc59 100644
--- a/Android.mk
+++ b/Android.mk
@@ -158,6 +158,11 @@
 	core/java/com/android/internal/os/IResultReceiver.aidl \
 	core/java/com/android/internal/statusbar/IStatusBar.aidl \
 	core/java/com/android/internal/statusbar/IStatusBarService.aidl \
+	core/java/com/android/internal/textservice/ISpellCheckerService.aidl \
+	core/java/com/android/internal/textservice/ISpellCheckerSession.aidl \
+	core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl \
+	core/java/com/android/internal/textservice/ITextServicesManager.aidl \
+	core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl \
 	core/java/com/android/internal/view/IInputContext.aidl \
 	core/java/com/android/internal/view/IInputContextCallback.aidl \
 	core/java/com/android/internal/view/IInputMethod.aidl \
@@ -266,6 +271,11 @@
 	frameworks/base/core/java/android/view/Surface.aidl \
 	frameworks/base/core/java/android/view/WindowManager.aidl \
 	frameworks/base/core/java/android/widget/RemoteViews.aidl \
+	frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerService.aidl \
+	frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl \
+	frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl \
+	frameworks/base/core/java/com/android/internal/textservice/ITextServicesManager.aidl \
+	frameworks/base/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl \
 	frameworks/base/core/java/com/android/internal/view/IInputContext.aidl \
 	frameworks/base/core/java/com/android/internal/view/IInputMethod.aidl \
 	frameworks/base/core/java/com/android/internal/view/IInputMethodCallback.aidl \
diff --git a/api/current.txt b/api/current.txt
index d821c8e..f88001d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -21,6 +21,7 @@
     field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
     field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+    field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_WALLPAPER = "android.permission.BIND_WALLPAPER";
     field public static final java.lang.String BLUETOOTH = "android.permission.BLUETOOTH";
     field public static final java.lang.String BLUETOOTH_ADMIN = "android.permission.BLUETOOTH_ADMIN";
@@ -184,14 +185,14 @@
   public static final class R.attr {
     ctor public R.attr();
     field public static final int absListViewStyle = 16842858; // 0x101006a
-    field public static final int accessibilityEventTypes = 16843648; // 0x1010380
-    field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
-    field public static final int accessibilityFlags = 16843652; // 0x1010384
+    field public static final int accessibilityEventTypes = 16843647; // 0x101037f
+    field public static final int accessibilityFeedbackType = 16843649; // 0x1010381
+    field public static final int accessibilityFlags = 16843651; // 0x1010383
     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 actionBarSize = 16843499; // 0x10102eb
-    field public static final int actionBarSplitStyle = 16843670; // 0x1010396
+    field public static final int actionBarSplitStyle = 16843669; // 0x1010395
     field public static final int actionBarStyle = 16843470; // 0x10102ce
     field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4
     field public static final int actionBarTabStyle = 16843507; // 0x10102f3
@@ -207,10 +208,10 @@
     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 = 16843646; // 0x101037e
-    field public static final int actionModeStyle = 16843682; // 0x10103a2
+    field public static final int actionModeSelectAllDrawable = 16843645; // 0x101037d
+    field public static final int actionModeStyle = 16843681; // 0x10103a1
     field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
-    field public static final int actionProviderClass = 16843671; // 0x1010397
+    field public static final int actionProviderClass = 16843670; // 0x1010396
     field public static final int actionViewClass = 16843516; // 0x10102fc
     field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
     field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
@@ -222,7 +223,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 = 16843640; // 0x1010378
+    field public static final int alignmentMode = 16843639; // 0x1010377
     field public static final int allContactsName = 16843468; // 0x10102cc
     field public static final int allowBackup = 16843392; // 0x1010280
     field public static final int allowClearUserData = 16842757; // 0x1010005
@@ -256,8 +257,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 = 16843673; // 0x1010399
-    field public static final int backgroundStacked = 16843672; // 0x1010398
+    field public static final int backgroundSplit = 16843672; // 0x1010398
+    field public static final int backgroundStacked = 16843671; // 0x1010397
     field public static final int backupAgent = 16843391; // 0x101027f
     field public static final int baseline = 16843548; // 0x101031c
     field public static final int baselineAlignBottom = 16843042; // 0x1010122
@@ -266,7 +267,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 = 16843659; // 0x101038b
+    field public static final int bottomChevronDrawable = 16843658; // 0x101038a
     field public static final int bottomDark = 16842953; // 0x10100c9
     field public static final int bottomLeftRadius = 16843179; // 0x10101ab
     field public static final int bottomMedium = 16842958; // 0x10100ce
@@ -285,7 +286,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 = 16843653; // 0x1010385
+    field public static final int canRetrieveWindowContent = 16843652; // 0x1010384
     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
@@ -314,18 +315,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 = 16843678; // 0x101039e
+    field public static final int colorActivatedHighlight = 16843677; // 0x101039d
     field public static final int colorBackground = 16842801; // 0x1010031
     field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
-    field public static final int colorFocusedHighlight = 16843677; // 0x101039d
+    field public static final int colorFocusedHighlight = 16843676; // 0x101039c
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
-    field public static final int colorLongPressedHighlight = 16843676; // 0x101039c
-    field public static final int colorMultiSelectHighlight = 16843679; // 0x101039f
-    field public static final int colorPressedHighlight = 16843675; // 0x101039b
-    field public static final int columnCount = 16843637; // 0x1010375
+    field public static final int colorLongPressedHighlight = 16843675; // 0x101039b
+    field public static final int colorMultiSelectHighlight = 16843678; // 0x101039e
+    field public static final int colorPressedHighlight = 16843674; // 0x101039a
+    field public static final int columnCount = 16843636; // 0x1010374
     field public static final int columnDelay = 16843215; // 0x10101cf
-    field public static final int columnOrderPreserved = 16843638; // 0x1010376
+    field public static final int columnOrderPreserved = 16843637; // 0x1010375
     field public static final int columnWidth = 16843031; // 0x1010117
     field public static final int compatibleWidthLimitDp = 16843621; // 0x1010365
     field public static final int completionHint = 16843122; // 0x1010172
@@ -379,11 +380,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 = 16843681; // 0x10103a1
+    field public static final int drawableEnd = 16843680; // 0x10103a0
     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 = 16843680; // 0x10103a0
+    field public static final int drawableStart = 16843679; // 0x101039f
     field public static final int drawableTop = 16843117; // 0x101016d
     field public static final int drawingCacheQuality = 16842984; // 0x10100e8
     field public static final int dropDownAnchor = 16843363; // 0x1010263
@@ -440,7 +441,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 = 16843665; // 0x1010391
+    field public static final int feedbackCount = 16843664; // 0x1010390
     field public static final int fillAfter = 16843197; // 0x10101bd
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillEnabled = 16843343; // 0x101024f
@@ -493,7 +494,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 = 16843655; // 0x1010387
+    field public static final int handleDrawable = 16843654; // 0x1010386
     field public static final int handleProfiling = 16842786; // 0x1010022
     field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
     field public static final int hardwareAccelerated = 16843475; // 0x10102d3
@@ -502,12 +503,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 = 16843662; // 0x101038e
+    field public static final int hitRadius = 16843661; // 0x101038d
     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 = 16843667; // 0x1010393
+    field public static final int horizontalOffset = 16843666; // 0x1010392
     field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
     field public static final int horizontalSpacing = 16843028; // 0x1010114
     field public static final int host = 16842792; // 0x1010028
@@ -553,7 +554,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 = 16843647; // 0x101037f
+    field public static final int isAuxiliary = 16843646; // 0x101037e
     field public static final int isDefault = 16843297; // 0x1010221
     field public static final int isIndicator = 16843079; // 0x1010147
     field public static final int isModifier = 16843334; // 0x1010246
@@ -606,8 +607,8 @@
     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_columnFlexibility = 16843645; // 0x101037d
-    field public static final int layout_columnSpan = 16843644; // 0x101037c
+    field public static final int layout_columnFlexibility = 16843644; // 0x101037c
+    field public static final int layout_columnSpan = 16843643; // 0x101037b
     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
@@ -615,9 +616,9 @@
     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 = 16843641; // 0x1010379
-    field public static final int layout_rowFlexibility = 16843643; // 0x101037b
-    field public static final int layout_rowSpan = 16843642; // 0x101037a
+    field public static final int layout_row = 16843640; // 0x1010378
+    field public static final int layout_rowFlexibility = 16843642; // 0x101037a
+    field public static final int layout_rowSpan = 16843641; // 0x1010379
     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
@@ -627,7 +628,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 = 16843656; // 0x1010388
+    field public static final int leftChevronDrawable = 16843655; // 0x1010387
     field public static final int lineSpacingExtra = 16843287; // 0x1010217
     field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
     field public static final int lines = 16843092; // 0x1010154
@@ -639,8 +640,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 = 16843668; // 0x1010394
-    field public static final int listPreferredItemHeightSmall = 16843669; // 0x1010395
+    field public static final int listPreferredItemHeightLarge = 16843667; // 0x1010393
+    field public static final int listPreferredItemHeightSmall = 16843668; // 0x1010394
     field public static final int listSelector = 16843003; // 0x10100fb
     field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208
     field public static final int listViewStyle = 16842868; // 0x1010074
@@ -671,8 +672,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 = 16843684; // 0x10103a4
-    field public static final int minResizeWidth = 16843683; // 0x10103a3
+    field public static final int minResizeHeight = 16843683; // 0x10103a3
+    field public static final int minResizeWidth = 16843682; // 0x10103a2
     field public static final int minSdkVersion = 16843276; // 0x101020c
     field public static final int minWidth = 16843071; // 0x101013f
     field public static final int mode = 16843134; // 0x101017e
@@ -688,7 +689,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 = 16843651; // 0x1010383
+    field public static final int notificationTimeout = 16843650; // 0x1010382
     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
@@ -702,11 +703,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 = 16843661; // 0x101038d
+    field public static final int outerRadius = 16843660; // 0x101038c
     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 = 16843649; // 0x1010381
+    field public static final int packageNames = 16843648; // 0x1010380
     field public static final int padding = 16842965; // 0x10100d5
     field public static final int paddingBottom = 16842969; // 0x10100d9
     field public static final int paddingLeft = 16842966; // 0x10100d6
@@ -791,17 +792,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 = 16843657; // 0x1010389
+    field public static final int rightChevronDrawable = 16843656; // 0x1010388
     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 = 16843635; // 0x1010373
+    field public static final int rowCount = 16843634; // 0x1010372
     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 = 16843636; // 0x1010374
+    field public static final int rowOrderPreserved = 16843635; // 0x1010373
     field public static final int saveEnabled = 16842983; // 0x10100e7
     field public static final int scaleGravity = 16843262; // 0x10101fe
     field public static final int scaleHeight = 16843261; // 0x10101fd
@@ -867,7 +868,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 = 16843664; // 0x1010390
+    field public static final int snapMargin = 16843663; // 0x101038f
     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,7 +916,7 @@
     field public static final int subtitleTextStyle = 16843513; // 0x10102f9
     field public static final int suggestActionMsg = 16843228; // 0x10101dc
     field public static final int suggestActionMsgColumn = 16843229; // 0x10101dd
-    field public static final int suggestionsEnabled = 16843634; // 0x1010372
+    field public static final int suggestionsEnabled = 16843633; // 0x1010371
     field public static final int summary = 16843241; // 0x10101e9
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
@@ -932,7 +933,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 = 16843654; // 0x1010386
+    field public static final int targetDrawables = 16843653; // 0x1010385
     field public static final int targetPackage = 16842785; // 0x1010021
     field public static final int targetSdkVersion = 16843376; // 0x1010270
     field public static final int taskAffinity = 16842770; // 0x1010012
@@ -947,7 +948,7 @@
     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 = 16843674; // 0x101039a
+    field public static final int textAllCaps = 16843673; // 0x1010399
     field public static final int textAppearance = 16842804; // 0x1010034
     field public static final int textAppearanceButton = 16843271; // 0x1010207
     field public static final int textAppearanceInverse = 16842805; // 0x1010035
@@ -988,9 +989,8 @@
     field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
     field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
     field public static final int textEditSidePasteWindowLayout = 16843614; // 0x101035e
-    field public static final int textEditSuggestionItemLayout = 16843633; // 0x1010371
-    field public static final int textEditSuggestionsBottomWindowLayout = 16843631; // 0x101036f
-    field public static final int textEditSuggestionsTopWindowLayout = 16843632; // 0x1010370
+    field public static final int textEditSuggestionItemLayout = 16843632; // 0x1010370
+    field public static final int textEditSuggestionsWindowLayout = 16843631; // 0x101036f
     field public static final int textFilterEnabled = 16843007; // 0x10100ff
     field public static final int textIsSelectable = 16843542; // 0x1010316
     field public static final int textOff = 16843045; // 0x1010125
@@ -1023,7 +1023,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 = 16843658; // 0x101038a
+    field public static final int topChevronDrawable = 16843657; // 0x1010389
     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,7 +1039,7 @@
     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 = 16843639; // 0x1010377
+    field public static final int useDefaultMargins = 16843638; // 0x1010376
     field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
     field public static final int useLevel = 16843167; // 0x101019f
     field public static final int userVisible = 16843409; // 0x1010291
@@ -1053,10 +1053,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 = 16843666; // 0x1010392
+    field public static final int verticalOffset = 16843665; // 0x1010391
     field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
     field public static final int verticalSpacing = 16843029; // 0x1010115
-    field public static final int vibrationDuration = 16843663; // 0x101038f
+    field public static final int vibrationDuration = 16843662; // 0x101038e
     field public static final int visibility = 16842972; // 0x10100dc
     field public static final int visible = 16843156; // 0x1010194
     field public static final int vmSafeMode = 16843448; // 0x10102b8
@@ -1073,7 +1073,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 = 16843660; // 0x101038c
+    field public static final int waveDrawable = 16843659; // 0x101038b
     field public static final int webTextViewStyle = 16843449; // 0x10102b9
     field public static final int webViewStyle = 16842885; // 0x1010085
     field public static final int weekDayTextAppearance = 16843592; // 0x1010348
@@ -4784,6 +4784,7 @@
     field public static final java.lang.String SENSOR_SERVICE = "sensor";
     field public static final java.lang.String STORAGE_SERVICE = "storage";
     field public static final java.lang.String TELEPHONY_SERVICE = "phone";
+    field public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
     field public static final java.lang.String UI_MODE_SERVICE = "uimode";
     field public static final java.lang.String USB_SERVICE = "usb";
     field public static final java.lang.String VIBRATOR_SERVICE = "vibrator";
@@ -17942,6 +17943,30 @@
 
 }
 
+package android.service.textservice {
+
+  public abstract class SpellCheckerService extends android.app.Service {
+    ctor public SpellCheckerService();
+    method public void cancel();
+    method public abstract android.view.textservice.SuggestionsInfo getSuggestions(android.view.textservice.TextInfo, int, java.lang.String);
+    method public android.view.textservice.SuggestionsInfo[] getSuggestionsMultiple(android.view.textservice.TextInfo[], java.lang.String, int, boolean);
+    method public final android.os.IBinder onBind(android.content.Intent);
+    field public static final java.lang.String SERVICE_INTERFACE;
+  }
+
+  public class SpellCheckerSession {
+    method public void close();
+    method public void getSuggestions(android.view.textservice.TextInfo, int);
+    method public void getSuggestions(android.view.textservice.TextInfo[], int, boolean);
+    method public boolean isSessionDisconnected();
+  }
+
+  public static abstract interface SpellCheckerSession.SpellCheckerSessionListener {
+    method public abstract void onGetSuggestions(android.view.textservice.SuggestionsInfo[]);
+  }
+
+}
+
 package android.service.wallpaper {
 
   public abstract class WallpaperService extends android.app.Service {
@@ -21005,6 +21030,11 @@
     method public void onPrepareSubMenu(android.view.SubMenu);
   }
 
+  public abstract interface CollapsibleActionView {
+    method public abstract void onActionViewCollapsed();
+    method public abstract void onActionViewExpanded();
+  }
+
   public abstract interface ContextMenu implements android.view.Menu {
     method public abstract void clearHeader();
     method public abstract android.view.ContextMenu setHeaderIcon(int);
@@ -22715,10 +22745,8 @@
     ctor public ViewDebug();
     method public static void dumpCapturedView(java.lang.String, java.lang.Object);
     method public static void startHierarchyTracing(java.lang.String, android.view.View);
-    method public static void startLooperProfiling(java.io.File);
     method public static void startRecyclerTracing(java.lang.String, android.view.View);
     method public static void stopHierarchyTracing();
-    method public static void stopLooperProfiling();
     method public static void stopRecyclerTracing();
     method public static void trace(android.view.View, android.view.ViewDebug.RecyclerTraceType, int...);
     method public static void trace(android.view.View, android.view.ViewDebug.HierarchyTraceType);
@@ -24019,6 +24047,54 @@
 
 }
 
+package android.view.textservice {
+
+  public final class SpellCheckerInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.content.ComponentName getComponent();
+    method public java.lang.String getId();
+    method public java.lang.String getPackageName();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class SuggestionsInfo implements android.os.Parcelable {
+    ctor public SuggestionsInfo(int, java.lang.String[]);
+    ctor public SuggestionsInfo(int, java.lang.String[], int, int);
+    ctor public SuggestionsInfo(android.os.Parcel);
+    method public int describeContents();
+    method public int getCookie();
+    method public int getSequence();
+    method public java.lang.String getSuggestionAt(int);
+    method public int getSuggestionsAttributes();
+    method public int getSuggestionsCount();
+    method public void setCookieAndSequence(int, int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int RESULT_ATTR_IN_THE_DICTIONARY = 1; // 0x1
+    field public static final int RESULT_ATTR_LOOKS_TYPO = 4; // 0x4
+    field public static final int RESULT_ATTR_SUGGESTIONS_AVAILABLE = 2; // 0x2
+  }
+
+  public final class TextInfo implements android.os.Parcelable {
+    ctor public TextInfo(java.lang.String);
+    ctor public TextInfo(java.lang.String, int, int);
+    ctor public TextInfo(android.os.Parcel);
+    method public int describeContents();
+    method public int getCookie();
+    method public int getSequence();
+    method public java.lang.String getText();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class TextServicesManager {
+    method public android.view.textservice.SpellCheckerInfo getCurrentSpellChecker(java.util.Locale);
+    method public android.service.textservice.SpellCheckerSession newSpellCheckerSession(android.view.textservice.SpellCheckerInfo, java.util.Locale, android.service.textservice.SpellCheckerSession.SpellCheckerSessionListener);
+  }
+
+}
+
 package android.webkit {
 
   public final deprecated class CacheManager {
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 3fb1736..6dfa12b 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -468,10 +468,16 @@
         String profileFile = null;
         boolean start = false;
         boolean wall = false;
+        int profileType = 0;
         
         String process = null;
         
         String cmd = nextArgRequired();
+        if ("looper".equals(cmd)) {
+            cmd = nextArgRequired();
+            profileType = 1;
+        }
+
         if ("start".equals(cmd)) {
             start = true;
             wall = "--wall".equals(nextOption());
@@ -516,7 +522,7 @@
             } else if (start) {
                 //removeWallOption();
             }
-            if (!mAm.profileControl(process, start, profileFile, fd)) {
+            if (!mAm.profileControl(process, start, profileFile, fd, profileType)) {
                 wall = false;
                 throw new AndroidException("PROFILE FAILED on process " + process);
             }
@@ -1076,8 +1082,8 @@
                 "       am broadcast <INTENT>\n" +
                 "       am instrument [-r] [-e <NAME> <VALUE>] [-p] [-w]\n" +
                 "               [--no-window-animation] <COMPONENT>\n" +
-                "       am profile start <PROCESS> <FILE>\n" +
-                "       am profile stop <PROCESS>\n" +
+                "       am profile [looper] start <PROCESS> <FILE>\n" +
+                "       am profile [looper] stop <PROCESS>\n" +
                 "       am dumpheap [flags] <PROCESS> <FILE>\n" +
                 "       am monitor [--gdb <port>]\n" +
                 "       am screen-compat [on|off] <PACKAGE>\n" +
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 2a731a3..b7cd829 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1104,10 +1104,11 @@
             data.enforceInterface(IActivityManager.descriptor);
             String process = data.readString();
             boolean start = data.readInt() != 0;
+            int profileType = data.readInt();
             String path = data.readString();
             ParcelFileDescriptor fd = data.readInt() != 0
                     ? data.readFileDescriptor() : null;
-            boolean res = profileControl(process, start, path, fd);
+            boolean res = profileControl(process, start, path, fd, profileType);
             reply.writeNoException();
             reply.writeInt(res ? 1 : 0);
             return true;
@@ -2888,13 +2889,14 @@
     }
     
     public boolean profileControl(String process, boolean start,
-            String path, ParcelFileDescriptor fd) throws RemoteException
+            String path, ParcelFileDescriptor fd, int profileType) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeString(process);
         data.writeInt(start ? 1 : 0);
+        data.writeInt(profileType);
         data.writeString(path);
         if (fd != null) {
             data.writeInt(1);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f6cd866..9bbbd6c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -676,11 +676,12 @@
             queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
         }
 
-        public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) {
+        public void profilerControl(boolean start, String path, ParcelFileDescriptor fd,
+                int profileType) {
             ProfilerControlData pcd = new ProfilerControlData();
             pcd.path = path;
             pcd.fd = fd;
-            queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0);
+            queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0, profileType);
         }
 
         public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) {
@@ -954,7 +955,7 @@
         }
 
         public void scheduleTrimMemory(int level) {
-            queueOrSendMessage(H.TRIM_MEMORY, level);
+            queueOrSendMessage(H.TRIM_MEMORY, null, level);
         }
     }
 
@@ -1148,7 +1149,7 @@
                     handleActivityConfigurationChanged((IBinder)msg.obj);
                     break;
                 case PROFILER_CONTROL:
-                    handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj);
+                    handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj, msg.arg2);
                     break;
                 case CREATE_BACKUP_AGENT:
                     handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
@@ -1184,8 +1185,10 @@
                     break;
                 case UPDATE_PACKAGE_COMPATIBILITY_INFO:
                     handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
+                    break;
                 case TRIM_MEMORY:
                     handleTrimMemory(msg.arg1);
+                    break;
             }
             if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
         }
@@ -3469,11 +3472,18 @@
         performConfigurationChanged(r.activity, mCompatConfiguration);
     }
 
-    final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
+    final void handleProfilerControl(boolean start, ProfilerControlData pcd, int profileType) {
         if (start) {
             try {
-                Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
-                        8 * 1024 * 1024, 0);
+                switch (profileType) {
+                    case 1:
+                        ViewDebug.startLooperProfiling(pcd.path, pcd.fd.getFileDescriptor());
+                        break;
+                    default:
+                        Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
+                                8 * 1024 * 1024, 0);
+                        break;
+                }
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Profiling failed on path " + pcd.path
                         + " -- can the process access this path?");
@@ -3485,7 +3495,15 @@
                 }
             }
         } else {
-            Debug.stopMethodTracing();
+            switch (profileType) {
+                case 1:
+                    ViewDebug.stopLooperProfiling();
+                    break;
+                default:
+                    Debug.stopMethodTracing();
+                    break;
+                    
+            }
         }
     }
 
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 942f245..9a5b527 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -376,10 +376,11 @@
         {
             data.enforceInterface(IApplicationThread.descriptor);
             boolean start = data.readInt() != 0;
+            int profileType = data.readInt();
             String path = data.readString();
             ParcelFileDescriptor fd = data.readInt() != 0
                     ? data.readFileDescriptor() : null;
-            profilerControl(start, path, fd);
+            profilerControl(start, path, fd, profileType);
             return true;
         }
         
@@ -936,10 +937,11 @@
     }
     
     public void profilerControl(boolean start, String path,
-            ParcelFileDescriptor fd) throws RemoteException {
+            ParcelFileDescriptor fd, int profileType) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeInt(start ? 1 : 0);
+        data.writeInt(profileType);
         data.writeString(path);
         if (fd != null) {
             data.writeInt(1);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index d2323e7..6289730 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -83,6 +83,7 @@
 import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityManager;
 import android.view.inputmethod.InputMethodManager;
+import android.view.textservice.TextServicesManager;
 import android.accounts.AccountManager;
 import android.accounts.IAccountManager;
 import android.app.admin.DevicePolicyManager;
@@ -320,6 +321,11 @@
                     return InputMethodManager.getInstance(ctx);
                 }});
 
+        registerService(TEXT_SERVICES_MANAGER_SERVICE, new ServiceFetcher() {
+                public Object createService(ContextImpl ctx) {
+                    return TextServicesManager.getInstance();
+                }});
+
         registerService(KEYGUARD_SERVICE, new ServiceFetcher() {
                 public Object getService(ContextImpl ctx) {
                     // TODO: why isn't this caching it?  It wasn't
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 93c821c..64d77e8 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -284,7 +284,7 @@
     
     // Turn on/off profiling in a particular process.
     public boolean profileControl(String process, boolean start,
-            String path, ParcelFileDescriptor fd) throws RemoteException;
+            String path, ParcelFileDescriptor fd, int profileType) throws RemoteException;
     
     public boolean shutdown(int timeout) throws RemoteException;
     
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 9de0bf4..d0607d0 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -105,7 +105,7 @@
             throws RemoteException;
     void scheduleLowMemory() throws RemoteException;
     void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException;
-    void profilerControl(boolean start, String path, ParcelFileDescriptor fd)
+    void profilerControl(boolean start, String path, ParcelFileDescriptor fd, int profileType)
             throws RemoteException;
     void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd)
             throws RemoteException;
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 1af0983..ca64c88 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -97,9 +97,10 @@
         }
     }
 
-    public void setIcon(String slot, int iconId, int iconLevel) {
+    public void setIcon(String slot, int iconId, int iconLevel, String contentDescription) {
         try {
-            mService.setIcon(slot, mContext.getPackageName(), iconId, iconLevel);
+            mService.setIcon(slot, mContext.getPackageName(), iconId, iconLevel,
+                    contentDescription);
         } catch (RemoteException ex) {
             // system process is dead anyway.
             throw new RuntimeException(ex);
diff --git a/core/java/android/content/ComponentCallbacks.java b/core/java/android/content/ComponentCallbacks.java
index 92b98fd..37cc141 100644
--- a/core/java/android/content/ComponentCallbacks.java
+++ b/core/java/android/content/ComponentCallbacks.java
@@ -56,11 +56,8 @@
     static final int TRIM_MEMORY_COMPLETE = 80;
 
     /** @hide */
-    static final int TRIM_MEMORY_MODERATE = 60;
+    static final int TRIM_MEMORY_MODERATE = 50;
 
     /** @hide */
-    static final int TRIM_MEMORY_BACKGROUND = 40;
-
-    /** @hide */
-    static final int TRIM_MEMORY_INVISIBLE = 20;
+    static final int TRIM_MEMORY_BACKGROUND = 20;
 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index fed6d81..0a2253c8 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1612,6 +1612,15 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
+     * {@link android.view.textservice.TextServicesManager} for accessing
+     * text services.
+     *
+     * @see #getSystemService
+     */
+    public static final String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
      * {@link android.appwidget.AppWidgetManager} for accessing AppWidgets.
      *
      * @hide
diff --git a/core/java/android/inputmethodservice/ExtractEditLayout.java b/core/java/android/inputmethodservice/ExtractEditLayout.java
index eafff49..5cfa998 100644
--- a/core/java/android/inputmethodservice/ExtractEditLayout.java
+++ b/core/java/android/inputmethodservice/ExtractEditLayout.java
@@ -172,7 +172,10 @@
 
         @Override
         public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
-            return mCallback.onActionItemClicked(this, item);
+            if (mCallback != null) {
+                return mCallback.onActionItemClicked(this, item);
+            }
+            return false;
         }
 
         @Override
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index a866436..b035c51 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -103,6 +103,10 @@
         public void interfaceRemoved(String iface) {
             mTracker.interfaceRemoved(iface);
         }
+
+        public void limitReached(String limitName, String iface) {
+            // Ignored.
+        }
     }
 
     private EthernetDataTracker() {
diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl
index 4436e6e..a97f203 100644
--- a/core/java/android/net/INetworkManagementEventObserver.aidl
+++ b/core/java/android/net/INetworkManagementEventObserver.aidl
@@ -52,4 +52,14 @@
      * @param iface The interface.
      */
     void interfaceRemoved(String iface);
+
+    /**
+     * A networking quota limit has been reached. The quota might not
+     * be specific to an interface.
+     *
+     * @param limitName The name of the limit that triggered.
+     * @param iface The interface on which the limit was detected.
+     */
+    void limitReached(String limitName, String iface);
+
 }
diff --git a/core/java/android/net/VpnBuilder.java b/core/java/android/net/VpnBuilder.java
new file mode 100644
index 0000000..4582523
--- /dev/null
+++ b/core/java/android/net/VpnBuilder.java
@@ -0,0 +1,413 @@
+/*
+ * 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;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.net.VpnConfig;
+
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.DatagramSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+
+/**
+ * VpnBuilder is a framework which enables applications to build their
+ * own VPN solutions. In general, it creates a virtual network interface,
+ * configures addresses and routing rules, and returns a file descriptor
+ * to the application. Each read from the descriptor retrieves an outgoing
+ * packet which was routed to the interface. Each write to the descriptor
+ * injects an incoming packet just like it was received from the interface.
+ * The framework is running on Internet Protocol (IP), so packets are
+ * always started with IP headers. The application then completes a VPN
+ * connection by processing and exchanging packets with a remote server
+ * over a secured tunnel.
+ *
+ * <p>Letting applications intercept packets raises huge security concerns.
+ * Besides, a VPN application can easily break the network, and two of them
+ * may conflict with each other. The framework takes several actions to
+ * address these issues. Here are some key points:
+ * <ul>
+ *   <li>User action is required to create a VPN connection.</li>
+ *   <li>There can be only one VPN connection running at the same time. The
+ *       existing interface is deactivated when a new one is created.</li>
+ *   <li>A system-managed notification is shown during the lifetime of a
+ *       VPN connection.</li>
+ *   <li>A system-managed dialog gives the information of the current VPN
+ *       connection. It also provides a button to disconnect.</li>
+ *   <li>The network is restored automatically when the file descriptor is
+ *       closed. It also covers the cases when a VPN application is crashed
+ *       or killed by the system.</li>
+ * </ul>
+ *
+ * <p>There are two primary methods in this class: {@link #prepare} and
+ * {@link #establish}. The former deals with the user action and stops
+ * the existing VPN connection created by another application. The latter
+ * creates a VPN interface using the parameters supplied to this builder.
+ * An application must call {@link #prepare} to grant the right to create
+ * an interface, and it can be revoked at any time by another application.
+ * The application got revoked is notified by an {@link #ACTION_VPN_REVOKED}
+ * broadcast. Here are the general steps to create a VPN connection:
+ * <ol>
+ *   <li>When the user press the button to connect, call {@link #prepare}
+ *       and launch the intent if necessary.</li>
+ *   <li>Register a receiver for {@link #ACTION_VPN_REVOKED} broadcasts.
+ *   <li>Connect to the remote server and negotiate the network parameters
+ *       of the VPN connection.</li>
+ *   <li>Use those parameters to configure a VpnBuilder and create a VPN
+ *       interface by calling {@link #establish}.</li>
+ *   <li>Start processing packets between the returned file descriptor and
+ *       the VPN tunnel.</li>
+ *   <li>When an {@link #ACTION_VPN_REVOKED} broadcast is received, the
+ *       interface is already deactivated by the framework. Close the file
+ *       descriptor and shut down the VPN tunnel gracefully.
+ * </ol>
+ * Methods in this class can be used in activities and services. However,
+ * the intent returned from {@link #prepare} must be launched from an
+ * activity. The broadcast receiver can be registered at any time, but doing
+ * it before calling {@link #establish} effectively avoids race conditions.
+ *
+ * <p class="note">Using this class requires
+ * {@link android.Manifest.permission#VPN} permission.
+ * @hide
+ */
+public class VpnBuilder {
+
+    /**
+     * Broadcast intent action indicating that the VPN application has been
+     * revoked. This can be only received by the target application on the
+     * receiver explicitly registered using {@link Context#registerReceiver}.
+     *
+     * <p>This is a protected intent that can only be sent by the system.
+     */
+    public static final String ACTION_VPN_REVOKED = VpnConfig.ACTION_VPN_REVOKED;
+
+    /**
+     * Use IConnectivityManager instead since those methods are hidden and
+     * not available in ConnectivityManager.
+     */
+    private static IConnectivityManager getService() {
+        return IConnectivityManager.Stub.asInterface(
+                ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
+    }
+
+    /**
+     * Prepare to establish a VPN connection. This method returns {@code null}
+     * if the VPN application is already prepared. Otherwise, it returns an
+     * {@link Intent} to a system activity. The application should launch the
+     * activity using {@link Activity#startActivityForResult} to get itself
+     * prepared. The activity may pop up a dialog to require user action, and
+     * the result will come back to the application through its
+     * {@link Activity#onActivityResult}. The application becomes prepared if
+     * the result is {@link Activity#RESULT_OK}, and it is granted to create a
+     * VPN interface by calling {@link #establish}.
+     *
+     * <p>Only one application can be granted at the same time. The right
+     * is revoked when another application is granted. The application
+     * losing the right will be notified by an {@link #ACTION_VPN_REVOKED}
+     * broadcast, and its VPN interface will be deactivated by the system.
+     * The application should then notify the remote server and disconnect
+     * gracefully. Unless the application becomes prepared again, subsequent
+     * calls to {@link #establish} will return {@code null}.
+     *
+     * @see #establish
+     * @see #ACTION_VPN_REVOKED
+     */
+    public static Intent prepare(Context context) {
+        try {
+            if (getService().prepareVpn(context.getPackageName(), null)) {
+                return null;
+            }
+        } catch (RemoteException e) {
+            // ignore
+        }
+        return VpnConfig.getIntentForConfirmation();
+    }
+
+    private VpnConfig mConfig = new VpnConfig();
+    private StringBuilder mAddresses = new StringBuilder();
+    private StringBuilder mRoutes = new StringBuilder();
+
+    /**
+     * Set the name of this session. It will be displayed in system-managed
+     * dialogs and notifications. This is recommended not required.
+     */
+    public VpnBuilder setSession(String session) {
+        mConfig.session = session;
+        return this;
+    }
+
+    /**
+     * Set the {@link PendingIntent} to an activity for users to configure
+     * the VPN connection. If it is not set, the button to configure will
+     * not be shown in system-managed dialogs.
+     */
+    public VpnBuilder setConfigureIntent(PendingIntent intent) {
+        mConfig.configureIntent = intent;
+        return this;
+    }
+
+    /**
+     * Set the maximum transmission unit (MTU) of the VPN interface. If it
+     * is not set, the default value in the operating system will be used.
+     *
+     * @throws IllegalArgumentException if the value is not positive.
+     */
+    public VpnBuilder setMtu(int mtu) {
+        if (mtu <= 0) {
+            throw new IllegalArgumentException("Bad mtu");
+        }
+        mConfig.mtu = mtu;
+        return this;
+    }
+
+    /**
+     * Private method to validate address and prefixLength.
+     */
+    private static void check(InetAddress address, int prefixLength) {
+        if (address.isLoopbackAddress()) {
+            throw new IllegalArgumentException("Bad address");
+        }
+        if (address instanceof Inet4Address) {
+            if (prefixLength < 0 || prefixLength > 32) {
+                throw new IllegalArgumentException("Bad prefixLength");
+            }
+        } else if (address instanceof Inet6Address) {
+            if (prefixLength < 0 || prefixLength > 128) {
+                throw new IllegalArgumentException("Bad prefixLength");
+            }
+        } else {
+            throw new IllegalArgumentException("Unsupported family");
+        }
+    }
+
+    /**
+     * Convenience method to add a network address to the VPN interface
+     * using a numeric address string. See {@link InetAddress} for the
+     * definitions of numeric address formats.
+     *
+     * @throws IllegalArgumentException if the address is invalid.
+     * @see #addAddress(InetAddress, int)
+     */
+    public VpnBuilder addAddress(String address, int prefixLength) {
+        return addAddress(InetAddress.parseNumericAddress(address), prefixLength);
+    }
+
+    /**
+     * Add a network address to the VPN interface. Both IPv4 and IPv6
+     * addresses are supported. At least one address must be set before
+     * calling {@link #establish}.
+     *
+     * @throws IllegalArgumentException if the address is invalid.
+     */
+    public VpnBuilder addAddress(InetAddress address, int prefixLength) {
+        check(address, prefixLength);
+
+        if (address.isAnyLocalAddress()) {
+            throw new IllegalArgumentException("Bad address");
+        }
+
+        mAddresses.append(String.format(" %s/%d", address.getHostAddress(), prefixLength));
+        return this;
+    }
+
+    /**
+     * Convenience method to add a network route to the VPN interface
+     * using a numeric address string. See {@link InetAddress} for the
+     * definitions of numeric address formats.
+     *
+     * @see #addRoute(InetAddress, int)
+     * @throws IllegalArgumentException if the route is invalid.
+     */
+    public VpnBuilder addRoute(String address, int prefixLength) {
+        return addRoute(InetAddress.parseNumericAddress(address), prefixLength);
+    }
+
+    /**
+     * Add a network route to the VPN interface. Both IPv4 and IPv6
+     * routes are supported.
+     *
+     * @throws IllegalArgumentException if the route is invalid.
+     */
+    public VpnBuilder addRoute(InetAddress address, int prefixLength) {
+        check(address, prefixLength);
+
+        int offset = prefixLength / 8;
+        byte[] bytes = address.getAddress();
+        if (offset < bytes.length) {
+            if ((byte)(bytes[offset] << (prefixLength % 8)) != 0) {
+                throw new IllegalArgumentException("Bad address");
+            }
+            while (++offset < bytes.length) {
+                if (bytes[offset] != 0) {
+                    throw new IllegalArgumentException("Bad address");
+                }
+            }
+        }
+
+        mRoutes.append(String.format(" %s/%d", address.getHostAddress(), prefixLength));
+        return this;
+    }
+
+    /**
+     * Convenience method to add a DNS server to the VPN connection
+     * using a numeric address string. See {@link InetAddress} for the
+     * definitions of numeric address formats.
+     *
+     * @throws IllegalArgumentException if the address is invalid.
+     * @see #addDnsServer(InetAddress)
+     */
+    public VpnBuilder addDnsServer(String address) {
+        return addDnsServer(InetAddress.parseNumericAddress(address));
+    }
+
+    /**
+     * Add a DNS server to the VPN connection. Both IPv4 and IPv6
+     * addresses are supported. If none is set, the DNS servers of
+     * the default network will be used.
+     *
+     * @throws IllegalArgumentException if the address is invalid.
+     */
+    public VpnBuilder addDnsServer(InetAddress address) {
+        if (address.isLoopbackAddress() || address.isAnyLocalAddress()) {
+            throw new IllegalArgumentException("Bad address");
+        }
+        if (mConfig.dnsServers == null) {
+            mConfig.dnsServers = new ArrayList<String>();
+        }
+        mConfig.dnsServers.add(address.getHostAddress());
+        return this;
+    }
+
+    /**
+     * Add a search domain to the DNS resolver.
+     */
+    public VpnBuilder addSearchDomain(String domain) {
+        if (mConfig.searchDomains == null) {
+            mConfig.searchDomains = new ArrayList<String>();
+        }
+        mConfig.searchDomains.add(domain);
+        return this;
+    }
+
+    /**
+     * Create a VPN interface using the parameters supplied to this builder.
+     * The interface works on IP packets, and a file descriptor is returned
+     * for the application to access them. Each read retrieves an outgoing
+     * packet which was routed to the interface. Each write injects an
+     * incoming packet just like it was received from the interface. The file
+     * descriptor is put into non-blocking mode by default to avoid blocking
+     * Java threads. To use the file descriptor completely in native space,
+     * see {@link ParcelFileDescriptor#detachFd()}. The application MUST
+     * close the file descriptor when the VPN connection is terminated. The
+     * VPN interface will be removed and the network will be restored by the
+     * framework automatically.
+     *
+     * <p>To avoid conflicts, there can be only one active VPN interface at
+     * the same time. Usually network parameters are never changed during the
+     * lifetime of a VPN connection. It is also common for an application to
+     * create a new file descriptor after closing the previous one. However,
+     * it is rare but not impossible to have two interfaces while performing a
+     * seamless handover. In this case, the old interface will be deactivated
+     * when the new one is configured successfully. Both file descriptors are
+     * valid but now outgoing packets will be routed to the new interface.
+     * Therefore, after draining the old file descriptor, the application MUST
+     * close it and start using the new file descriptor. If the new interface
+     * cannot be created, the existing interface and its file descriptor remain
+     * untouched.
+     *
+     * <p>An exception will be thrown if the interface cannot be created for
+     * any reason. However, this method returns {@code null} if the application
+     * is not prepared or is revoked by another application. This helps solve
+     * possible race conditions while handling {@link #ACTION_VPN_REVOKED}
+     * broadcasts.
+     *
+     * @return {@link ParcelFileDescriptor} of the VPN interface, or
+     *         {@code null} if the application is not prepared.
+     * @throws IllegalArgumentException if a parameter is not accepted by the
+     *         operating system.
+     * @throws IllegalStateException if a parameter cannot be applied by the
+     *         operating system.
+     * @see #prepare
+     */
+    public ParcelFileDescriptor establish() {
+        mConfig.addresses = mAddresses.toString();
+        mConfig.routes = mRoutes.toString();
+
+        try {
+            return getService().establishVpn(mConfig);
+        } catch (RemoteException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    /**
+     * Protect a socket from VPN connections. The socket will be bound to the
+     * current default network interface, so its traffic will not be forwarded
+     * through VPN. This method is useful if some connections need to be kept
+     * outside of VPN. For example, a VPN tunnel should protect itself if its
+     * destination is covered by VPN routes. Otherwise its outgoing packets
+     * will be sent back to the VPN interface and cause an infinite loop.
+     *
+     * <p>The socket is NOT closed by this method.
+     *
+     * @return {@code true} on success.
+     */
+    public static boolean protect(int socket) {
+        ParcelFileDescriptor dup = null;
+        try {
+            dup = ParcelFileDescriptor.fromFd(socket);
+            return getService().protectVpn(dup);
+        } catch (Exception e) {
+            return false;
+        } finally {
+            try {
+                dup.close();
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Protect a {@link Socket} from VPN connections.
+     *
+     * @return {@code true} on success.
+     * @see #protect(int)
+     */
+    public static boolean protect(Socket socket) {
+        return protect(socket.getFileDescriptor$().getInt$());
+    }
+
+    /**
+     * Protect a {@link DatagramSocket} from VPN connections.
+     *
+     * @return {@code true} on success.
+     * @see #protect(int)
+     */
+    public static boolean protect(DatagramSocket socket) {
+        return protect(socket.getFileDescriptor$().getInt$());
+    }
+}
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index cd39d5c..bc37244 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -361,7 +361,8 @@
 
     /**
      * Remove any pending posts of Runnable <var>r</var> with Object
-     * <var>token</var> that are in the message queue.
+     * <var>token</var> that are in the message queue.  If <var>token</var> is null,
+     * all callbacks will be removed.
      */
     public final void removeCallbacks(Runnable r, Object token)
     {
@@ -517,7 +518,8 @@
 
     /**
      * Remove any pending posts of messages with code 'what' and whose obj is
-     * 'object' that are in the message queue.
+     * 'object' that are in the message queue.  If <var>token</var> is null,
+     * all messages will be removed.
      */
     public final void removeMessages(int what, Object object) {
         mQueue.removeMessages(this, what, object, true);
@@ -525,7 +527,8 @@
 
     /**
      * Remove any pending posts of callbacks and sent messages whose
-     * <var>obj</var> is <var>token</var>.
+     * <var>obj</var> is <var>token</var>.  If <var>token</var> is null,
+     * all callbacks and messages will be removed.
      */
     public final void removeCallbacksAndMessages(Object token) {
         mQueue.removeCallbacksAndMessages(this, token);
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index c90de17..78c9010 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -563,6 +563,12 @@
             // Single pane, showing just a prefs fragment.
             findViewById(com.android.internal.R.id.headers).setVisibility(View.GONE);
             mPrefsContainer.setVisibility(View.VISIBLE);
+            if (initialTitle != 0) {
+                CharSequence initialTitleStr = getText(initialTitle);
+                CharSequence initialShortTitleStr = initialShortTitle != 0
+                        ? getText(initialShortTitle) : null;
+                showBreadCrumbs(initialTitleStr, initialShortTitleStr);
+            }
         } else if (mHeaders.size() > 0) {
             setListAdapter(new HeaderAdapter(this, mHeaders));
             if (!mSinglePane) {
@@ -1093,6 +1099,10 @@
         } else {
             getListView().clearChoices();
         }
+        showBreadCrumbs(header);
+    }
+
+    void showBreadCrumbs(Header header) {
         if (header != null) {
             CharSequence title = header.getBreadCrumbTitle(getResources());
             if (title == null) title = header.getTitle(getResources());
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index cb87e94..1cd46de 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -16,8 +16,6 @@
 
 package android.provider;
 
-
-
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.SearchManager;
@@ -48,7 +46,6 @@
 import java.util.HashMap;
 import java.util.HashSet;
 
-
 /**
  * The Settings provider contains global system-level device preferences.
  */
@@ -3737,6 +3734,15 @@
          */
         public static final String VOICE_RECOGNITION_SERVICE = "voice_recognition_service";
 
+
+        /**
+         * The {@link ComponentName} string of the service to be used as the spell checker
+         * service which is one of the services managed by the text service manager.
+         *
+         * @hide
+         */
+        public static final String SPELL_CHECKER_SERVICE = "spell_checker_service";
+
         /**
          * What happens when the user presses the Power button while in-call
          * and the screen is on.<br/>
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index ab569a1..d68d8ba 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -527,10 +527,19 @@
                 break;
             case MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY:
                 address = (String)msg.obj;
-                if (address != null) {
+                if (address == null) return;
+                int attempt = mBondState.getAttempt(address);
+
+                // Try only if attemps are in progress and cap it 2 attempts
+                // The 2 attempts cap is a fail safe if the stack returns
+                // an incorrect error code for bonding failures and if the pin
+                // is entered wrongly twice we should abort.
+                if (attempt > 0 && attempt <= 2) {
+                    mBondState.attempt(address);
                     createBond(address);
                     return;
                 }
+                if (attempt > 0) mBondState.clearPinAttempts(address);
                 break;
             }
         }
@@ -741,7 +750,6 @@
                     BluetoothDevice.BOND_NONE, result);
             return;
         }
-        mBondState.attempt(address);
     }
 
     /*package*/ BluetoothDevice getRemoteDevice(String address) {
diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java
new file mode 100644
index 0000000..6ac99ca
--- /dev/null
+++ b/core/java/android/service/textservice/SpellCheckerService.java
@@ -0,0 +1,140 @@
+/*
+ * 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.service.textservice;
+
+import com.android.internal.textservice.ISpellCheckerService;
+import com.android.internal.textservice.ISpellCheckerSession;
+import com.android.internal.textservice.ISpellCheckerSessionListener;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.view.textservice.SuggestionsInfo;
+import android.view.textservice.TextInfo;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * SpellCheckerService provides an abstract base class for a spell checker.
+ * This class combines a service to the system with the spell checker service interface that
+ * spell checker must implement.
+ */
+public abstract class SpellCheckerService extends Service {
+    private static final String TAG = SpellCheckerService.class.getSimpleName();
+    public static final String SERVICE_INTERFACE = SpellCheckerService.class.getName();
+
+    private final SpellCheckerServiceBinder mBinder = new SpellCheckerServiceBinder(this);
+
+    /**
+     * Get suggestions for specified text in TextInfo.
+     * This function will run on the incoming IPC thread. So, this is not called on the main thread,
+     * but will be called in series on another thread.
+     * @param textInfo the text metadata
+     * @param suggestionsLimit the number of limit of suggestions returned
+     * @param locale the locale for getting suggestions
+     * @return SuggestionInfo which contains suggestions for textInfo
+     */
+    public abstract SuggestionsInfo getSuggestions(
+            TextInfo textInfo, int suggestionsLimit, String locale);
+
+    /**
+     * A batch process of onGetSuggestions.
+     * This function will run on the incoming IPC thread. So, this is not called on the main thread,
+     * but will be called in series on another thread.
+     * @param textInfos an array of the text metadata
+     * @param locale the locale for getting suggestions
+     * @param suggestionsLimit the number of limit of suggestions returned
+     * @param sequentialWords true if textInfos can be treated as sequential words.
+     * @return an array of SuggestionInfo of onGetSuggestions
+     */
+    public SuggestionsInfo[] getSuggestionsMultiple(
+            TextInfo[] textInfos, String locale, int suggestionsLimit, boolean sequentialWords) {
+        final int length = textInfos.length;
+        final SuggestionsInfo[] retval = new SuggestionsInfo[length];
+        for (int i = 0; i < length; ++i) {
+            retval[i] = getSuggestions(textInfos[i], suggestionsLimit, locale);
+            retval[i].setCookieAndSequence(textInfos[i].getCookie(), textInfos[i].getSequence());
+        }
+        return retval;
+    }
+
+    /**
+     * Request to abort all tasks executed in SpellChecker.
+     * This function will run on the incoming IPC thread. So, this is not called on the main thread,
+     * but will be called in series on another thread.
+     */
+    public void cancel() {}
+
+    /**
+     * Implement to return the implementation of the internal spell checker
+     * service interface. Subclasses should not override.
+     */
+    @Override
+    public final IBinder onBind(final Intent intent) {
+        return mBinder;
+    }
+
+    private static class SpellCheckerSessionImpl extends ISpellCheckerSession.Stub {
+        private final WeakReference<SpellCheckerService> mInternalServiceRef;
+        private final String mLocale;
+        private final ISpellCheckerSessionListener mListener;
+
+        public SpellCheckerSessionImpl(
+                SpellCheckerService service, String locale, ISpellCheckerSessionListener listener) {
+            mInternalServiceRef = new WeakReference<SpellCheckerService>(service);
+            mLocale = locale;
+            mListener = listener;
+        }
+
+        @Override
+        public void getSuggestionsMultiple(
+                TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) {
+            final SpellCheckerService service = mInternalServiceRef.get();
+            if (service == null) return;
+            try {
+                mListener.onGetSuggestions(
+                        service.getSuggestionsMultiple(textInfos, mLocale,
+                                suggestionsLimit, sequentialWords));
+            } catch (RemoteException e) {
+            }
+        }
+
+        @Override
+        public void cancel() {
+            final SpellCheckerService service = mInternalServiceRef.get();
+            if (service == null) return;
+            service.cancel();
+        }
+    }
+
+    private static class SpellCheckerServiceBinder extends ISpellCheckerService.Stub {
+        private final WeakReference<SpellCheckerService> mInternalServiceRef;
+
+        public SpellCheckerServiceBinder(SpellCheckerService service) {
+            mInternalServiceRef = new WeakReference<SpellCheckerService>(service);
+        }
+
+        @Override
+        public ISpellCheckerSession getISpellCheckerSession(
+                String locale, ISpellCheckerSessionListener listener) {
+            final SpellCheckerService service = mInternalServiceRef.get();
+            if (service == null) return null;
+            return new SpellCheckerSessionImpl(service, locale, listener);
+        }
+    }
+}
diff --git a/core/java/android/service/textservice/SpellCheckerSession.java b/core/java/android/service/textservice/SpellCheckerSession.java
new file mode 100644
index 0000000..a575220
--- /dev/null
+++ b/core/java/android/service/textservice/SpellCheckerSession.java
@@ -0,0 +1,271 @@
+/*
+ * 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.service.textservice;
+
+import com.android.internal.textservice.ISpellCheckerSession;
+import com.android.internal.textservice.ISpellCheckerSessionListener;
+import com.android.internal.textservice.ITextServicesManager;
+import com.android.internal.textservice.ITextServicesSessionListener;
+
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.textservice.SuggestionsInfo;
+import android.view.textservice.TextInfo;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+/**
+ * The SpellCheckerSession interface provides the per client functionality of SpellCheckerService.
+ */
+public class SpellCheckerSession {
+    private static final String TAG = SpellCheckerSession.class.getSimpleName();
+    private static final boolean DBG = false;
+
+    private static final int MSG_ON_GET_SUGGESTION_MULTIPLE = 1;
+
+    private final InternalListener mInternalListener;
+    private final ITextServicesManager mTextServicesManager;
+    private final SpellCheckerSessionListenerImpl mSpellCheckerSessionListenerImpl;
+
+    private boolean mIsUsed;
+    private SpellCheckerSessionListener mSpellCheckerSessionListener;
+
+    /** Handler that will execute the main tasks */
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_ON_GET_SUGGESTION_MULTIPLE:
+                    handleOnGetSuggestionsMultiple((SuggestionsInfo[]) msg.obj);
+                    break;
+            }
+        }
+    };
+
+    /**
+     * Constructor
+     * @hide
+     */
+    public SpellCheckerSession(ITextServicesManager tsm, SpellCheckerSessionListener listener) {
+        if (listener == null || tsm == null) {
+            throw new NullPointerException();
+        }
+        mSpellCheckerSessionListenerImpl = new SpellCheckerSessionListenerImpl(mHandler);
+        mInternalListener = new InternalListener();
+        mTextServicesManager = tsm;
+        mIsUsed = true;
+        mSpellCheckerSessionListener = listener;
+    }
+
+    /**
+     * @return true if the connection to a text service of this session is disconnected and not
+     * alive.
+     */
+    public boolean isSessionDisconnected() {
+        return mSpellCheckerSessionListenerImpl.isDisconnected();
+    }
+
+    /**
+     * Finish this session and allow TextServicesManagerService to disconnect the bound spell
+     * checker.
+     */
+    public void close() {
+        mIsUsed = false;
+        try {
+            mTextServicesManager.finishSpellCheckerService(mSpellCheckerSessionListenerImpl);
+        } catch (RemoteException e) {
+            // do nothing
+        }
+    }
+
+    /**
+     * Get candidate strings for a substring of the specified text.
+     * @param textInfo text metadata for a spell checker
+     * @param suggestionsLimit the number of limit of suggestions returned
+     */
+    public void getSuggestions(TextInfo textInfo, int suggestionsLimit) {
+        getSuggestions(new TextInfo[] {textInfo}, suggestionsLimit, false);
+    }
+
+    /**
+     * A batch process of getSuggestions
+     * @param textInfos an array of text metadata for a spell checker
+     * @param suggestionsLimit the number of limit of suggestions returned
+     * @param sequentialWords true if textInfos can be treated as sequential words.
+     */
+    public void getSuggestions(
+            TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) {
+        // TODO: Handle multiple words suggestions by using WordBreakIterator
+        mSpellCheckerSessionListenerImpl.getSuggestionsMultiple(
+                textInfos, suggestionsLimit, sequentialWords);
+    }
+
+    private void handleOnGetSuggestionsMultiple(SuggestionsInfo[] suggestionInfos) {
+        mSpellCheckerSessionListener.onGetSuggestions(suggestionInfos);
+    }
+
+    private static class SpellCheckerSessionListenerImpl extends ISpellCheckerSessionListener.Stub {
+        private static final int TASK_CANCEL = 1;
+        private static final int TASK_GET_SUGGESTIONS_MULTIPLE = 2;
+        private final Queue<SpellCheckerParams> mPendingTasks =
+                new LinkedList<SpellCheckerParams>();
+        private final Handler mHandler;
+
+        private boolean mOpened;
+        private ISpellCheckerSession mISpellCheckerSession;
+
+        public SpellCheckerSessionListenerImpl(Handler handler) {
+            mOpened = false;
+            mHandler = handler;
+        }
+
+        private static class SpellCheckerParams {
+            public final int mWhat;
+            public final TextInfo[] mTextInfos;
+            public final int mSuggestionsLimit;
+            public final boolean mSequentialWords;
+            public SpellCheckerParams(int what, TextInfo[] textInfos, int suggestionsLimit,
+                    boolean sequentialWords) {
+                mWhat = what;
+                mTextInfos = textInfos;
+                mSuggestionsLimit = suggestionsLimit;
+                mSequentialWords = sequentialWords;
+            }
+        }
+
+        private void processTask(SpellCheckerParams scp) {
+            switch (scp.mWhat) {
+                case TASK_CANCEL:
+                    processCancel();
+                    break;
+                case TASK_GET_SUGGESTIONS_MULTIPLE:
+                    processGetSuggestionsMultiple(scp);
+                    break;
+            }
+        }
+
+        public synchronized void onServiceConnected(ISpellCheckerSession session) {
+            mISpellCheckerSession = session;
+            mOpened = true;
+            if (DBG)
+                Log.d(TAG, "onServiceConnected - Success");
+            while (!mPendingTasks.isEmpty()) {
+                processTask(mPendingTasks.poll());
+            }
+        }
+
+        public void getSuggestionsMultiple(
+                TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) {
+            processOrEnqueueTask(
+                    new SpellCheckerParams(TASK_GET_SUGGESTIONS_MULTIPLE, textInfos,
+                            suggestionsLimit, sequentialWords));
+        }
+
+        public boolean isDisconnected() {
+            return mOpened && mISpellCheckerSession == null;
+        }
+
+        public boolean checkOpenConnection() {
+            if (mISpellCheckerSession != null) {
+                return true;
+            }
+            Log.e(TAG, "not connected to the spellchecker service.");
+            return false;
+        }
+
+        private void processOrEnqueueTask(SpellCheckerParams scp) {
+            if (mISpellCheckerSession == null) {
+                mPendingTasks.offer(scp);
+            } else {
+                processTask(scp);
+            }
+        }
+
+        private void processCancel() {
+            if (!checkOpenConnection()) {
+                return;
+            }
+            try {
+                mISpellCheckerSession.cancel();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to cancel " + e);
+            }
+        }
+
+        private void processGetSuggestionsMultiple(SpellCheckerParams scp) {
+            if (!checkOpenConnection()) {
+                return;
+            }
+            try {
+                mISpellCheckerSession.getSuggestionsMultiple(
+                        scp.mTextInfos, scp.mSuggestionsLimit, scp.mSequentialWords);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to get suggestions " + e);
+            }
+        }
+
+        @Override
+        public void onGetSuggestions(SuggestionsInfo[] results) {
+            mHandler.sendMessage(Message.obtain(mHandler, MSG_ON_GET_SUGGESTION_MULTIPLE, results));
+        }
+    }
+
+    /**
+     * Callback for getting results from text services
+     */
+    public interface SpellCheckerSessionListener {
+        /**
+         * Callback for "getSuggestions"
+         * @param results an array of results of getSuggestions
+         */
+        public void onGetSuggestions(SuggestionsInfo[] results);
+    }
+
+    private class InternalListener extends ITextServicesSessionListener.Stub {
+        @Override
+        public void onServiceConnected(ISpellCheckerSession session) {
+            mSpellCheckerSessionListenerImpl.onServiceConnected(session);
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        super.finalize();
+        if (mIsUsed) {
+            Log.e(TAG, "SpellCheckerSession was not finished properly." +
+                    "You should call finishShession() when you finished to use a spell checker.");
+            close();
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public ITextServicesSessionListener getTextServicesSessionListener() {
+        return mInternalListener;
+    }
+
+    /**
+     * @hide
+     */
+    public ISpellCheckerSessionListener getSpellCheckerSessionListener() {
+        return mSpellCheckerSessionListenerImpl;
+    }
+}
diff --git a/core/java/android/view/CollapsibleActionView.java b/core/java/android/view/CollapsibleActionView.java
new file mode 100644
index 0000000..ab2365e
--- /dev/null
+++ b/core/java/android/view/CollapsibleActionView.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.view;
+
+import android.view.MenuItem.OnActionExpandListener;
+
+/**
+ * When a {@link View} implements this interface it will receive callbacks
+ * when expanded or collapsed as an action view alongside the optional,
+ * app-specified callbacks to {@link OnActionExpandListener}.
+ *
+ * <p>See {@link MenuItem} for more information about action views.
+ * See {@link android.app.ActionBar} for more information about the action bar.
+ */
+public interface CollapsibleActionView {
+    /**
+     * Called when this view is expanded as an action view.
+     * See {@link MenuItem#expandActionView()}.
+     */
+    public void onActionViewExpanded();
+
+    /**
+     * Called when this view is collapsed as an action view.
+     * See {@link MenuItem#collapseActionView()}.
+     */
+    public void onActionViewCollapsed();
+}
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index 4484d59..f4c0249 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -41,15 +41,6 @@
     abstract void end();
 
     /**
-     * Indicates whether this display list can be replayed or not.
-     * 
-     * @return True if the display list can be replayed, false otherwise.
-     * 
-     * @see android.view.HardwareCanvas#drawDisplayList(DisplayList) 
-     */
-    abstract boolean isReady();
-
-    /**
      * Invalidates the display list, indicating that it should be repopulated
      * with new drawing commands prior to being used again. Calling this method
      * causes calls to {@link #isValid()} to return <code>false</code>.
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 80244bb..d22fa6e 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -51,6 +51,7 @@
 
     // The native renderer will be destroyed when this object dies.
     // DO NOT overwrite this reference once it is set.
+    @SuppressWarnings("unused")
     private CanvasFinalizer mFinalizer;
 
     private int mWidth;
@@ -97,12 +98,8 @@
     protected GLES20Canvas(boolean record, boolean translucent) {
         mOpaque = !translucent;
 
-        setupRenderer(record);
-    }
-
-    protected void setupRenderer(boolean record) {
         if (record) {
-            mRenderer = nGetDisplayListRenderer(mRenderer);
+            mRenderer = nCreateDisplayListRenderer();
         } else {
             mRenderer = nCreateRenderer();
         }
@@ -114,43 +111,31 @@
         if (mRenderer == 0) {
             throw new IllegalStateException("Could not create GLES20Canvas renderer");
         } else {
-            mFinalizer = CanvasFinalizer.getFinalizer(mFinalizer, mRenderer);
+            mFinalizer = new CanvasFinalizer(mRenderer);
         }
     }
 
+    protected void resetDisplayListRenderer() {
+        nResetDisplayListRenderer(mRenderer);
+    }
+
     private static native int nCreateRenderer();
     private static native int nCreateLayerRenderer(int layer);
-    private static native int nGetDisplayListRenderer(int renderer);
+    private static native int nCreateDisplayListRenderer();
+    private static native void nResetDisplayListRenderer(int renderer);
     private static native void nDestroyRenderer(int renderer);
 
-    private static class CanvasFinalizer {
-        int mRenderer;
+    private static final class CanvasFinalizer {
+        private final int mRenderer;
 
-        // Factory method returns new instance if old one is null, or old instance
-        // otherwise, destroying native renderer along the way as necessary
-        static CanvasFinalizer getFinalizer(CanvasFinalizer oldFinalizer, int renderer) {
-            if (oldFinalizer == null) {
-                return new CanvasFinalizer(renderer);
-            }
-            oldFinalizer.replaceNativeObject(renderer);
-            return oldFinalizer;
-        }
-
-        private CanvasFinalizer(int renderer) {
+        public CanvasFinalizer(int renderer) {
             mRenderer = renderer;
         }
 
-        private void replaceNativeObject(int newRenderer) {
-            if (mRenderer != 0 && newRenderer != mRenderer) {
-                nDestroyRenderer(mRenderer);
-            }
-            mRenderer = newRenderer;
-        }
-
         @Override
         protected void finalize() throws Throwable {
             try {
-                replaceNativeObject(0);
+                nDestroyRenderer(mRenderer);
             } finally {
                 super.finalize();
             }
@@ -322,11 +307,11 @@
     // Display list
     ///////////////////////////////////////////////////////////////////////////
 
-    int getDisplayList() {
-        return nGetDisplayList(mRenderer);
+    int getDisplayList(int displayList) {
+        return nGetDisplayList(mRenderer, displayList);
     }
 
-    private static native int nGetDisplayList(int renderer);
+    private static native int nGetDisplayList(int renderer, int displayList);
     
     static void destroyDisplayList(int displayList) {
         nDestroyDisplayList(displayList);
@@ -337,7 +322,7 @@
     @Override
     public boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty) {
         return nDrawDisplayList(mRenderer,
-                ((GLES20DisplayList) displayList).mNativeDisplayList, width, height, dirty);
+                ((GLES20DisplayList) displayList).getNativeDisplayList(), width, height, dirty);
     }
 
     private static native boolean nDrawDisplayList(int renderer, int displayList,
@@ -345,7 +330,7 @@
 
     @Override
     void outputDisplayList(DisplayList displayList) {
-        nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList);
+        nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList());
     }
 
     private static native void nOutputDisplayList(int renderer, int displayList);
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index aeff31f..9e649cea 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -16,52 +16,50 @@
 
 package android.view;
 
-import java.lang.ref.WeakReference;
+import android.graphics.Bitmap;
+
+import java.util.ArrayList;
 
 /**
  * An implementation of display list for OpenGL ES 2.0.
  */
 class GLES20DisplayList extends DisplayList {
-    private GLES20Canvas mCanvas;
+    // These lists ensure that any Bitmaps recorded by a DisplayList are kept alive as long
+    // as the DisplayList is alive.  The Bitmaps are populated by the GLES20RecordingCanvas.
+    final ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(5);
 
-    private boolean mStarted = false;
-    private boolean mRecorded = false;
-    private boolean mValid = false;
-
-    int mNativeDisplayList;
-    WeakReference<View> hostView;
+    private GLES20RecordingCanvas mCanvas;
+    private boolean mValid;
 
     // The native display list will be destroyed when this object dies.
     // DO NOT overwrite this reference once it is set.
-    @SuppressWarnings("unused")
     private DisplayListFinalizer mFinalizer;
 
-    public GLES20DisplayList(View view) {
-        hostView = new WeakReference<View>(view);
+    int getNativeDisplayList() {
+        if (!mValid || mFinalizer == null) {
+            throw new IllegalStateException("The display list is not valid.");
+        }
+        return mFinalizer.mNativeDisplayList;
     }
 
     @Override
     HardwareCanvas start() {
-        if (mStarted) {
+        if (mCanvas != null) {
             throw new IllegalStateException("Recording has already started");
         }
 
-        if (mCanvas != null) {
-            ((GLES20RecordingCanvas) mCanvas).reset();
-        } else {
-            mCanvas = new GLES20RecordingCanvas(true);
-        }
-        mStarted = true;
-        mRecorded = false;
-        mValid = true;
-
+        mValid = false;
+        mCanvas = GLES20RecordingCanvas.obtain(this);
+        mCanvas.start();
         return mCanvas;
     }
 
     @Override
     void invalidate() {
-        mStarted = false;
-        mRecorded = false;
+        if (mCanvas != null) {
+            mCanvas.recycle();
+            mCanvas = null;
+        }
         mValid = false;
     }
 
@@ -73,48 +71,28 @@
     @Override
     void end() {
         if (mCanvas != null) {
-            mStarted = false;
-            mRecorded = true;
-
-            mNativeDisplayList = mCanvas.getDisplayList();
-            mFinalizer = DisplayListFinalizer.getFinalizer(mFinalizer, mNativeDisplayList);
+            if (mFinalizer != null) {
+                mCanvas.end(mFinalizer.mNativeDisplayList);
+            } else {
+                mFinalizer = new DisplayListFinalizer(mCanvas.end(0));
+            }
+            mCanvas.recycle();
+            mCanvas = null;
+            mValid = true;
         }
     }
 
-    @Override
-    boolean isReady() {
-        return !mStarted && mRecorded;
-    }
-
     private static class DisplayListFinalizer {
-        int mNativeDisplayList;
+        final int mNativeDisplayList;
 
-        // Factory method returns new instance if old one is null, or old instance
-        // otherwise, destroying native display list along the way as necessary
-        static DisplayListFinalizer getFinalizer(DisplayListFinalizer oldFinalizer,
-                int nativeDisplayList) {
-            if (oldFinalizer == null) {
-                return new DisplayListFinalizer(nativeDisplayList);
-            }
-            oldFinalizer.replaceNativeObject(nativeDisplayList);
-            return oldFinalizer;
-        }
-
-        private DisplayListFinalizer(int nativeDisplayList) {
+        public DisplayListFinalizer(int nativeDisplayList) {
             mNativeDisplayList = nativeDisplayList;
         }
 
-        private void replaceNativeObject(int newNativeDisplayList) {
-            if (mNativeDisplayList != 0 && mNativeDisplayList != newNativeDisplayList) {
-                GLES20Canvas.destroyDisplayList(mNativeDisplayList);
-            }
-            mNativeDisplayList = newNativeDisplayList;
-        }
-
         @Override
         protected void finalize() throws Throwable {
             try {
-                replaceNativeObject(0);
+                GLES20Canvas.destroyDisplayList(mNativeDisplayList);
             } finally {
                 super.finalize();
             }
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index ec94fe7..078222b 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -24,8 +24,10 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Shader;
-
-import java.util.ArrayList;
+import android.util.Pool;
+import android.util.Poolable;
+import android.util.PoolableManager;
+import android.util.Pools;
 
 /**
  * An implementation of a GL canvas that records drawing operations.
@@ -33,62 +35,94 @@
  * Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while
  * the DisplayList is still holding a native reference to the memory.
  */
-class GLES20RecordingCanvas extends GLES20Canvas {
-    // These lists ensure that any Bitmaps recorded by a DisplayList are kept alive as long
-    // as the DisplayList is alive.
-    @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
-    private final ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(5);
+class GLES20RecordingCanvas extends GLES20Canvas implements Poolable<GLES20RecordingCanvas> {
+    // The recording canvas pool should be large enough to handle a deeply nested
+    // view hierarchy because display lists are generated recursively.
+    private static final int POOL_LIMIT = 50;
 
-    GLES20RecordingCanvas(boolean translucent) {
-        super(true, translucent);
+    private static final Pool<GLES20RecordingCanvas> sPool = Pools.synchronizedPool(
+            Pools.finitePool(new PoolableManager<GLES20RecordingCanvas>() {
+                public GLES20RecordingCanvas newInstance() {
+                    return new GLES20RecordingCanvas();
+                }
+                @Override
+                public void onAcquired(GLES20RecordingCanvas element) {
+                }
+                @Override
+                public void onReleased(GLES20RecordingCanvas element) {
+                }
+            }, POOL_LIMIT));
+
+    private GLES20RecordingCanvas mNextPoolable;
+    private boolean mIsPooled;
+
+    private GLES20DisplayList mDisplayList;
+
+    private GLES20RecordingCanvas() {
+        super(true /*record*/, true /*translucent*/);
+    }
+
+    static GLES20RecordingCanvas obtain(GLES20DisplayList displayList) {
+        GLES20RecordingCanvas canvas = sPool.acquire();
+        canvas.mDisplayList = displayList;
+        return canvas;
+    }
+
+    void recycle() {
+        mDisplayList = null;
+        resetDisplayListRenderer();
+        sPool.release(this);
+    }
+
+    void start() {
+        mDisplayList.mBitmaps.clear();
+    }
+
+    int end(int nativeDisplayList) {
+        return getDisplayList(nativeDisplayList);
     }
 
     private void recordShaderBitmap(Paint paint) {
         if (paint != null) {
             final Shader shader = paint.getShader();
             if (shader instanceof BitmapShader) {
-                mBitmaps.add(((BitmapShader) shader).mBitmap);
+                mDisplayList.mBitmaps.add(((BitmapShader) shader).mBitmap);
             }
         }
     }
 
-    void reset() {
-        mBitmaps.clear();
-        setupRenderer(true);
-    }
-
     @Override
     public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) {
         super.drawPatch(bitmap, chunks, dst, paint);
-        mBitmaps.add(bitmap);
+        mDisplayList.mBitmaps.add(bitmap);
         // Shaders in the Paint are ignored when drawing a Bitmap
     }
 
     @Override
     public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
         super.drawBitmap(bitmap, left, top, paint);
-        mBitmaps.add(bitmap);
+        mDisplayList.mBitmaps.add(bitmap);
         // Shaders in the Paint are ignored when drawing a Bitmap
     }
 
     @Override
     public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
         super.drawBitmap(bitmap, matrix, paint);
-        mBitmaps.add(bitmap);
+        mDisplayList.mBitmaps.add(bitmap);
         // Shaders in the Paint are ignored when drawing a Bitmap
     }
 
     @Override
     public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
         super.drawBitmap(bitmap, src, dst, paint);
-        mBitmaps.add(bitmap);
+        mDisplayList.mBitmaps.add(bitmap);
         // Shaders in the Paint are ignored when drawing a Bitmap
     }
 
     @Override
     public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
         super.drawBitmap(bitmap, src, dst, paint);
-        mBitmaps.add(bitmap);
+        mDisplayList.mBitmaps.add(bitmap);
         // Shaders in the Paint are ignored when drawing a Bitmap
     }
 
@@ -111,7 +145,7 @@
             int vertOffset, int[] colors, int colorOffset, Paint paint) {
         super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset,
                 paint);
-        mBitmaps.add(bitmap);
+        mDisplayList.mBitmaps.add(bitmap);
         // Shaders in the Paint are ignored when drawing a Bitmap
     }
 
@@ -270,4 +304,24 @@
                 colorOffset, indices, indexOffset, indexCount, paint);
         recordShaderBitmap(paint);
     }
+
+    @Override
+    public GLES20RecordingCanvas getNextPoolable() {
+        return mNextPoolable;
+    }
+
+    @Override
+    public void setNextPoolable(GLES20RecordingCanvas element) {
+        mNextPoolable = element;
+    }
+
+    @Override
+    public boolean isPooled() {
+        return mIsPooled;
+    }
+
+    @Override
+    public void setPooled(boolean isPooled) {
+        mIsPooled = isPooled;
+    }
 }
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index b865b50..503b54b 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -189,7 +189,7 @@
      * 
      * @return A new display list.
      */
-    abstract DisplayList createDisplayList(View v);
+    abstract DisplayList createDisplayList();
 
     /**
      * Creates a new hardware layer. A hardware layer built by calling this
@@ -852,8 +852,8 @@
         }
 
         @Override
-        DisplayList createDisplayList(View v) {
-            return new GLES20DisplayList(v);
+        DisplayList createDisplayList() {
+            return new GLES20DisplayList();
         }
 
         @Override
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0108ecf..ecb391d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9099,7 +9099,10 @@
         mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
     }
 
-    private void resolvePadding() {
+    /**
+     * @hide
+     */
+    protected void resolvePadding() {
         // If the user specified the absolute padding (either with android:padding or
         // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
         // use the default padding or the padding from the background drawable
@@ -9830,7 +9833,7 @@
             // we copy in child display lists into ours in drawChild()
             mRecreateDisplayList = true;
             if (mDisplayList == null) {
-                mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList(this);
+                mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList();
                 // If we're creating a new display list, make sure our parent gets invalidated
                 // since they will need to recreate their display list to account for this
                 // new child display list.
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 3798c9d..4acf48c 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -25,6 +25,7 @@
 import android.os.Environment;
 import android.os.Looper;
 import android.os.Message;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.util.DisplayMetrics;
@@ -36,7 +37,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.io.File;
-import java.io.FileNotFoundException;
+import java.io.FileDescriptor;
 import java.io.FileOutputStream;
 import java.io.FileWriter;
 import java.io.IOException;
@@ -50,6 +51,9 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -426,22 +430,22 @@
      * and obtain the traces. Both methods must be invoked on the
      * same thread.
      * 
-     * @param traceFile The path where to write the looper traces
-     * 
-     * @see #stopLooperProfiling() 
+     * @hide
      */
-    public static void startLooperProfiling(File traceFile) {
+    public static void startLooperProfiling(String path, FileDescriptor fileDescriptor) {
         if (sLooperProfilerStorage.get() == null) {
-            LooperProfiler profiler = new LooperProfiler(traceFile);
+            LooperProfiler profiler = new LooperProfiler(path, fileDescriptor);
             sLooperProfilerStorage.set(profiler);
             Looper.myLooper().setMessageLogging(profiler);
         }
-    }
+    }    
 
     /**
      * Stops profiling the looper associated with the current thread.
      * 
-     * @see #startLooperProfiling(java.io.File) 
+     * @see #startLooperProfiling(String, java.io.FileDescriptor) 
+     * 
+     * @hide
      */
     public static void stopLooperProfiling() {
         LooperProfiler profiler = sLooperProfilerStorage.get();
@@ -453,21 +457,33 @@
     }
 
     private static class LooperProfiler implements Looper.Profiler, Printer {
-        private static final int LOOPER_PROFILER_VERSION = 1;
-
         private static final String LOG_TAG = "LooperProfiler";
 
+        private static final int TRACE_VERSION_NUMBER = 3;
+        private static final int ACTION_EXIT_METHOD = 0x1;
+        private static final int HEADER_SIZE = 32;
+        private static final String HEADER_MAGIC = "SLOW";
+        private static final short HEADER_RECORD_SIZE = (short) 14;
+
         private final long mTraceWallStart;
         private final long mTraceThreadStart;
         
         private final ArrayList<Entry> mTraces = new ArrayList<Entry>(512);
-        private final File mTraceFile;
 
-        private final HashMap<String, Short> mTraceNames = new HashMap<String, Short>(32);
-        private short mTraceId = 0;
+        private final HashMap<String, Integer> mTraceNames = new HashMap<String, Integer>(32);
+        private int mTraceId = 0;
 
-        LooperProfiler(File traceFile) {
-            mTraceFile = traceFile;
+        private final String mPath;
+        private ParcelFileDescriptor mFileDescriptor;
+
+        LooperProfiler(String path, FileDescriptor fileDescriptor) {
+            mPath = path;
+            try {
+                mFileDescriptor = ParcelFileDescriptor.dup(fileDescriptor);
+            } catch (IOException e) {
+                Log.e(LOG_TAG, "Could not write trace file " + mPath, e);
+                throw new RuntimeException(e);
+            }
             mTraceWallStart = SystemClock.currentTimeMicro();
             mTraceThreadStart = SystemClock.currentThreadTimeMicro();            
         }
@@ -490,11 +506,11 @@
             mTraces.add(entry);
         }
 
-        private short getTraceId(Message message) {
+        private int getTraceId(Message message) {
             String name = message.getTarget().getMessageName(message);
-            Short traceId = mTraceNames.get(name);
+            Integer traceId = mTraceNames.get(name);
             if (traceId == null) {
-                traceId = mTraceId++;
+                traceId = mTraceId++ << 4;
                 mTraceNames.put(name, traceId);
             }
             return traceId;
@@ -507,62 +523,135 @@
                 public void run() {
                     saveTraces();
                 }
-            }, "LooperProfiler[" + mTraceFile + "]").start();
+            }, "LooperProfiler[" + mPath + "]").start();
         }
 
         private void saveTraces() {
-            FileOutputStream fos;
-            try {
-                fos = new FileOutputStream(mTraceFile);
-            } catch (FileNotFoundException e) {
-                Log.e(LOG_TAG, "Could not open trace file: " + mTraceFile);
-                return;
-            }
-
+            FileOutputStream fos = new FileOutputStream(mFileDescriptor.getFileDescriptor());
             DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos));
 
             try {
-                out.writeInt(LOOPER_PROFILER_VERSION);
-                out.writeLong(mTraceWallStart);
-                out.writeLong(mTraceThreadStart);
+                writeHeader(out, mTraceWallStart, mTraceNames, mTraces);
+                out.flush();
 
-                out.writeInt(mTraceNames.size());
-                for (Map.Entry<String, Short> entry : mTraceNames.entrySet()) {
-                    saveTraceName(entry.getKey(), entry.getValue(), out);
-                }
+                writeTraces(fos, out.size(), mTraceWallStart, mTraceThreadStart, mTraces);
 
-                out.writeInt(mTraces.size());
-                for (Entry entry : mTraces) {
-                    saveTrace(entry, out);
-                }
-
-                Log.d(LOG_TAG, "Looper traces ready: " + mTraceFile);
+                Log.d(LOG_TAG, "Looper traces ready: " + mPath);
             } catch (IOException e) {
-                Log.e(LOG_TAG, "Could not write trace file: ", e);
+                Log.e(LOG_TAG, "Could not write trace file " + mPath, e);
             } finally {
                 try {
                     out.close();
                 } catch (IOException e) {
-                    // Ignore
+                    Log.e(LOG_TAG, "Could not write trace file " + mPath, e);
+                }
+                try {
+                    mFileDescriptor.close();
+                } catch (IOException e) {
+                    Log.e(LOG_TAG, "Could not write trace file " + mPath, e);
                 }
             }
         }
-
-        private void saveTraceName(String name, short id, DataOutputStream out) throws IOException {
-            out.writeShort(id);
-            out.writeUTF(name);
+        
+        private static void writeTraces(FileOutputStream out, long offset, long wallStart,
+                long threadStart, ArrayList<Entry> entries) throws IOException {
+    
+            FileChannel channel = out.getChannel();
+    
+            // Header
+            ByteBuffer buffer = ByteBuffer.allocateDirect(HEADER_SIZE);
+            buffer.put(HEADER_MAGIC.getBytes());
+            buffer = buffer.order(ByteOrder.LITTLE_ENDIAN);
+            buffer.putShort((short) TRACE_VERSION_NUMBER);    // version
+            buffer.putShort((short) HEADER_SIZE);             // offset to data
+            buffer.putLong(wallStart);                        // start time in usec
+            buffer.putShort(HEADER_RECORD_SIZE);              // size of a record in bytes
+            // padding to 32 bytes
+            for (int i = 0; i < HEADER_SIZE - 18; i++) {
+                buffer.put((byte) 0);
+            }
+    
+            buffer.flip();
+            channel.position(offset).write(buffer);
+            
+            buffer = ByteBuffer.allocateDirect(14).order(ByteOrder.LITTLE_ENDIAN);
+            for (Entry entry : entries) {
+                buffer.putShort((short) 1);   // we simulate only one thread
+                buffer.putInt(entry.traceId); // entering method
+                buffer.putInt((int) (entry.threadStart - threadStart));
+                buffer.putInt((int) (entry.wallStart - wallStart));
+    
+                buffer.flip();
+                channel.write(buffer);
+                buffer.clear();
+    
+                buffer.putShort((short) 1);
+                buffer.putInt(entry.traceId | ACTION_EXIT_METHOD); // exiting method
+                buffer.putInt((int) (entry.threadStart + entry.threadTime - threadStart));
+                buffer.putInt((int) (entry.wallStart + entry.wallTime - wallStart));
+    
+                buffer.flip();
+                channel.write(buffer);
+                buffer.clear();
+            }
+    
+            channel.close();
         }
+    
+        private static void writeHeader(DataOutputStream out, long start,
+                HashMap<String, Integer> names, ArrayList<Entry> entries) throws IOException {
+    
+            Entry last = entries.get(entries.size() - 1);
+            long wallTotal = (last.wallStart + last.wallTime) - start;
+    
+            startSection("version", out);
+            addValue(null, Integer.toString(TRACE_VERSION_NUMBER), out);
+            addValue("data-file-overflow", "false", out);
+            addValue("clock", "dual", out);
+            addValue("elapsed-time-usec", Long.toString(wallTotal), out);
+            addValue("num-method-calls", Integer.toString(entries.size()), out);
+            addValue("clock-call-overhead-nsec", "1", out);
+            addValue("vm", "dalvik", out);
+    
+            startSection("threads", out);
+            addThreadId(1, "main", out);
+    
+            startSection("methods", out);
+            addMethods(names, out);
+    
+            startSection("end", out);
+        }
+    
+        private static void addMethods(HashMap<String, Integer> names, DataOutputStream out)
+                throws IOException {
+    
+            for (Map.Entry<String, Integer> name : names.entrySet()) {
+                out.writeBytes(String.format("0x%08x\tEventQueue\t%s\t()V\tLooper\t-2\n",
+                        name.getValue(), name.getKey()));
+            }
+        }
+    
+        private static void addThreadId(int id, String name, DataOutputStream out)
+                throws IOException {
 
-        private void saveTrace(Entry entry, DataOutputStream out) throws IOException {
-            out.writeShort(entry.traceId);
-            out.writeLong(entry.wallStart);
-            out.writeLong(entry.wallTime);
-            out.writeLong(entry.threadStart);
-            out.writeLong(entry.threadTime);
+            out.writeBytes(Integer.toString(id) + '\t' + name + '\n');
+        }
+    
+        private static void addValue(String name, String value, DataOutputStream out)
+                throws IOException {
+    
+            if (name != null) {
+                out.writeBytes(name + "=");
+            }
+            out.writeBytes(value + '\n');
+        }
+    
+        private static void startSection(String name, DataOutputStream out) throws IOException {
+            out.writeBytes("*" + name + '\n');
         }
 
         static class Entry {
-            short traceId;
+            int traceId;
             long wallStart;
             long wallTime;
             long threadStart;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 54fee3c..92a8ce7 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2148,9 +2148,12 @@
         onPopulateAccessibilityEvent(event);
         // Let our children have a shot in populating the event.
         for (int i = 0, count = getChildCount(); i < count; i++) {
-            boolean handled = getChildAt(i).dispatchPopulateAccessibilityEvent(event);
-            if (handled) {
-                return handled;
+            View child = getChildAt(i);
+            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
+                boolean handled = getChildAt(i).dispatchPopulateAccessibilityEvent(event);
+                if (handled) {
+                    return handled;
+                }
             }
         }
         return false;
diff --git a/core/java/android/view/textservice/SpellCheckerInfo.aidl b/core/java/android/view/textservice/SpellCheckerInfo.aidl
new file mode 100644
index 0000000..eb5dfcc
--- /dev/null
+++ b/core/java/android/view/textservice/SpellCheckerInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.textservice;
+
+parcelable SpellCheckerInfo;
diff --git a/core/java/android/view/textservice/SpellCheckerInfo.java b/core/java/android/view/textservice/SpellCheckerInfo.java
new file mode 100644
index 0000000..1205adf
--- /dev/null
+++ b/core/java/android/view/textservice/SpellCheckerInfo.java
@@ -0,0 +1,112 @@
+/*
+ * 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.textservice;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class is used to specify meta information of an spell checker.
+ */
+public final class SpellCheckerInfo implements Parcelable {
+    private final ResolveInfo mService;
+    private final String mId;
+
+    /**
+     * Constructor.
+     * @hide
+     */
+    public SpellCheckerInfo(Context context, ResolveInfo service) {
+        mService = service;
+        ServiceInfo si = service.serviceInfo;
+        mId = new ComponentName(si.packageName, si.name).flattenToShortString();
+    }
+
+    /**
+     * Constructor.
+     * @hide
+     */
+    public SpellCheckerInfo(Parcel source) {
+        mId = source.readString();
+        mService = ResolveInfo.CREATOR.createFromParcel(source);
+    }
+
+    /**
+     * Return a unique ID for this spell checker.  The ID is generated from
+     * the package and class name implementing the method.
+     */
+    public String getId() {
+        return mId;
+    }
+
+
+    /**
+     * Return the component of the service that implements.
+     */
+    public ComponentName getComponent() {
+        return new ComponentName(
+                mService.serviceInfo.packageName, mService.serviceInfo.name);
+    }
+
+    /**
+     * Return the .apk package that implements this input method.
+     */
+    public String getPackageName() {
+        return mService.serviceInfo.packageName;
+    }
+
+    /**
+     * Used to package this object into a {@link Parcel}.
+     *
+     * @param dest The {@link Parcel} to be written.
+     * @param flags The flags used for parceling.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mId);
+        mService.writeToParcel(dest, flags);
+    }
+
+
+    /**
+     * Used to make this class parcelable.
+     */
+    public static final Parcelable.Creator<SpellCheckerInfo> CREATOR
+            = new Parcelable.Creator<SpellCheckerInfo>() {
+        @Override
+        public SpellCheckerInfo createFromParcel(Parcel source) {
+            return new SpellCheckerInfo(source);
+        }
+
+        @Override
+        public SpellCheckerInfo[] newArray(int size) {
+            return new SpellCheckerInfo[size];
+        }
+    };
+
+    /**
+     * Used to make this class parcelable.
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/view/textservice/SuggestionsInfo.aidl b/core/java/android/view/textservice/SuggestionsInfo.aidl
new file mode 100644
index 0000000..66e20d2
--- /dev/null
+++ b/core/java/android/view/textservice/SuggestionsInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.textservice;
+
+parcelable SuggestionsInfo;
diff --git a/core/java/android/view/textservice/SuggestionsInfo.java b/core/java/android/view/textservice/SuggestionsInfo.java
new file mode 100644
index 0000000..b0ccbea
--- /dev/null
+++ b/core/java/android/view/textservice/SuggestionsInfo.java
@@ -0,0 +1,176 @@
+/*
+ * 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.textservice;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class contains a metadata of suggestions from the text service
+ */
+public final class SuggestionsInfo implements Parcelable {
+    /**
+     * Flag of the attributes of the suggestions that can be obtained by
+     * {@link #getSuggestionsAttributes}: this tells that the requested word was found
+     * in the dictionary in the text service.
+     */
+    public static final int RESULT_ATTR_IN_THE_DICTIONARY = 0x0001;
+    /** Flag of the attributes of the suggestions that can be obtained by
+     * {@link #getSuggestionsAttributes}: this tells that there are one or more suggestions
+     * available for the requested word.  This doesn't necessarily mean that the suggestions
+     * are actually in this SuggestionsInfo.  For instance, the caller could have been asked to
+     * limit the maximum number of suggestions returned.
+     */
+    public static final int RESULT_ATTR_SUGGESTIONS_AVAILABLE = 0x0002;
+    /**
+     * Flag of the attributes of the suggestions that can be obtained by
+     * {@link #getSuggestionsAttributes}: this tells that the text service thinks the requested
+     * word looks a typo.
+     */
+    public static final int RESULT_ATTR_LOOKS_TYPO = 0x0004;
+    private final int mSuggestionsAttributes;
+    private final String[] mSuggestions;
+    private int mCookie;
+    private int mSequence;
+
+    /**
+     * Constructor.
+     * @param suggestionsAttributes from the text service
+     * @param suggestions from the text service
+     */
+    public SuggestionsInfo(int suggestionsAttributes, String[] suggestions) {
+        if (suggestions == null) {
+            throw new NullPointerException();
+        }
+        mSuggestionsAttributes = suggestionsAttributes;
+        mSuggestions = suggestions;
+        mCookie = 0;
+        mSequence = 0;
+    }
+
+    /**
+     * Constructor.
+     * @param suggestionsAttributes from the text service
+     * @param suggestions from the text service
+     * @param cookie the cookie of the input TextInfo
+     * @param sequence the cookie of the input TextInfo
+     */
+    public SuggestionsInfo(
+            int suggestionsAttributes, String[] suggestions, int cookie, int sequence) {
+        if (suggestions == null) {
+            throw new NullPointerException();
+        }
+        mSuggestionsAttributes = suggestionsAttributes;
+        mSuggestions = suggestions;
+        mCookie = cookie;
+        mSequence = sequence;
+    }
+
+    public SuggestionsInfo(Parcel source) {
+        mSuggestionsAttributes = source.readInt();
+        mSuggestions = source.readStringArray();
+        mCookie = source.readInt();
+        mSequence = source.readInt();
+    }
+
+    /**
+     * Used to package this object into a {@link Parcel}.
+     *
+     * @param dest The {@link Parcel} to be written.
+     * @param flags The flags used for parceling.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mSuggestionsAttributes);
+        dest.writeStringArray(mSuggestions);
+        dest.writeInt(mCookie);
+        dest.writeInt(mSequence);
+    }
+
+    /**
+     * Set the cookie and the sequence of SuggestionsInfo which are set to TextInfo from a client
+     * application
+     * @param cookie the cookie of an input TextInfo
+     * @param sequence the cookie of an input TextInfo
+     */
+    public void setCookieAndSequence(int cookie, int sequence) {
+        mCookie = cookie;
+        mSequence = sequence;
+    }
+
+    /**
+     * @return the cookie which may be set by a client application
+     */
+    public int getCookie() {
+        return mCookie;
+    }
+
+    /**
+     * @return the sequence which may be set by a client application
+     */
+    public int getSequence() {
+        return mSequence;
+    }
+
+    /**
+     * @return the attributes of suggestions. This includes whether the spell checker has the word
+     * in its dictionary or not and whether the spell checker has confident suggestions for the
+     * word or not.
+     */
+    public int getSuggestionsAttributes() {
+        return mSuggestionsAttributes;
+    }
+
+    /**
+     * @return the count of suggestions
+     */
+    public int getSuggestionsCount() {
+        return mSuggestions.length;
+    }
+
+    /**
+     * @param i the id of suggestions
+     * @return the suggestion at the specified id
+     */
+    public String getSuggestionAt(int i) {
+        return mSuggestions[i];
+    }
+
+    /**
+     * Used to make this class parcelable.
+     */
+    public static final Parcelable.Creator<SuggestionsInfo> CREATOR
+            = new Parcelable.Creator<SuggestionsInfo>() {
+        @Override
+        public SuggestionsInfo createFromParcel(Parcel source) {
+            return new SuggestionsInfo(source);
+        }
+
+        @Override
+        public SuggestionsInfo[] newArray(int size) {
+            return new SuggestionsInfo[size];
+        }
+    };
+
+    /**
+     * Used to make this class parcelable.
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/view/textservice/TextInfo.aidl b/core/java/android/view/textservice/TextInfo.aidl
new file mode 100644
index 0000000..d231d76
--- /dev/null
+++ b/core/java/android/view/textservice/TextInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.textservice;
+
+parcelable TextInfo;
diff --git a/core/java/android/view/textservice/TextInfo.java b/core/java/android/view/textservice/TextInfo.java
new file mode 100644
index 0000000..b534eb0
--- /dev/null
+++ b/core/java/android/view/textservice/TextInfo.java
@@ -0,0 +1,117 @@
+/*
+ * 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.textservice;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+/**
+ * This class contains a metadata of the input of TextService
+ */
+public final class TextInfo implements Parcelable {
+    private final String mText;
+    private final int mCookie;
+    private final int mSequence;
+
+    /**
+     * Constructor.
+     * @param text the text which will be input to TextService
+     */
+    public TextInfo(String text) {
+        this(text, 0, 0);
+    }
+
+    /**
+     * Constructor.
+     * @param text the text which will be input to TextService
+     * @param cookie the cookie for this TextInfo
+     * @param sequence the sequence number for this TextInfo
+     */
+    public TextInfo(String text, int cookie, int sequence) {
+        if (TextUtils.isEmpty(text)) {
+            throw new IllegalArgumentException(text);
+        }
+        mText = text;
+        mCookie = cookie;
+        mSequence = sequence;
+    }
+
+    public TextInfo(Parcel source) {
+        mText = source.readString();
+        mCookie = source.readInt();
+        mSequence = source.readInt();
+    }
+
+    /**
+     * Used to package this object into a {@link Parcel}.
+     *
+     * @param dest The {@link Parcel} to be written.
+     * @param flags The flags used for parceling.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mText);
+        dest.writeInt(mCookie);
+        dest.writeInt(mSequence);
+    }
+
+    /**
+     * @return the text which is an input of a text service
+     */
+    public String getText() {
+        return mText;
+    }
+
+    /**
+     * @return the cookie of TextInfo
+     */
+    public int getCookie() {
+        return mCookie;
+    }
+
+    /**
+     * @return the sequence of TextInfo
+     */
+    public int getSequence() {
+        return mSequence;
+    }
+
+    /**
+     * Used to make this class parcelable.
+     */
+    public static final Parcelable.Creator<TextInfo> CREATOR
+            = new Parcelable.Creator<TextInfo>() {
+        @Override
+        public TextInfo createFromParcel(Parcel source) {
+            return new TextInfo(source);
+        }
+
+        @Override
+        public TextInfo[] newArray(int size) {
+            return new TextInfo[size];
+        }
+    };
+
+    /**
+     * Used to make this class parcelable.
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
new file mode 100644
index 0000000..6fa7e4d
--- /dev/null
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -0,0 +1,106 @@
+/*
+ * 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.textservice;
+
+import com.android.internal.textservice.ITextServicesManager;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.view.textservice.SpellCheckerInfo;
+import android.service.textservice.SpellCheckerSession;
+import android.service.textservice.SpellCheckerSession.SpellCheckerSessionListener;
+
+import java.util.Locale;
+
+/**
+ * System API to the overall text services, which arbitrates interaction between applications
+ * and text services. You can retrieve an instance of this interface with
+ * {@link Context#getSystemService(String) Context.getSystemService()}.
+ *
+ * The user can change the current text services in Settings. And also applications can specify
+ * the target text services.
+ */
+public final class TextServicesManager {
+    private static final String TAG = TextServicesManager.class.getSimpleName();
+
+    private static TextServicesManager sInstance;
+    private static ITextServicesManager sService;
+
+    private TextServicesManager() {
+        if (sService == null) {
+            IBinder b = ServiceManager.getService(Context.TEXT_SERVICES_MANAGER_SERVICE);
+            sService = ITextServicesManager.Stub.asInterface(b);
+        }
+    }
+
+    /**
+     * Retrieve the global TextServicesManager instance, creating it if it doesn't already exist.
+     * @hide
+     */
+    public static TextServicesManager getInstance() {
+        synchronized (TextServicesManager.class) {
+            if (sInstance != null) {
+                return sInstance;
+            }
+            sInstance = new TextServicesManager();
+        }
+        return sInstance;
+    }
+
+
+    /**
+     * Get the current spell checker service info for the specified locale.
+     * @param locale locale of a spell checker
+     * @return SpellCheckerInfo for the specified locale.
+     */
+    // TODO: Add a method to get enabled spell checkers.
+    public SpellCheckerInfo getCurrentSpellChecker(Locale locale) {
+        if (locale == null) {
+            throw new NullPointerException("locale is null");
+        }
+        try {
+            return sService.getCurrentSpellChecker(locale.toString());
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Get a spell checker session for a specified spell checker
+     * @param info SpellCheckerInfo of the spell checker
+     * @param locale the locale for the spell checker
+     * @param listener a spell checker session lister for getting results from a spell checker.
+     * @return the spell checker session of the spell checker
+     */
+    public SpellCheckerSession newSpellCheckerSession(
+            SpellCheckerInfo info, Locale locale, SpellCheckerSessionListener listener) {
+        if (info == null || locale == null || listener == null) {
+            throw new NullPointerException();
+        }
+        final SpellCheckerSession session = new SpellCheckerSession(sService, listener);
+        try {
+            sService.getSpellCheckerService(
+                    info, locale.toString(), session.getTextServicesSessionListener(),
+                    session.getSpellCheckerSessionListener());
+        } catch (RemoteException e) {
+            return null;
+        }
+        return session;
+    }
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 73db03e..6a3b2ff 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -9119,20 +9119,12 @@
         return nativeTileProfilingNumTilesInFrame(frame);
     }
     /** @hide only used by profiling tests */
-    public int tileProfilingGetX(int frame, int tile) {
-        return nativeTileProfilingGetX(frame, tile);
+    public int tileProfilingGetInt(int frame, int tile, String key) {
+        return nativeTileProfilingGetInt(frame, tile, key);
     }
     /** @hide only used by profiling tests */
-    public int tileProfilingGetY(int frame, int tile) {
-        return nativeTileProfilingGetY(frame, tile);
-    }
-    /** @hide only used by profiling tests */
-    public boolean tileProfilingGetReady(int frame, int tile) {
-        return nativeTileProfilingGetReady(frame, tile);
-    }
-    /** @hide only used by profiling tests */
-    public int tileProfilingGetLevel(int frame, int tile) {
-        return nativeTileProfilingGetLevel(frame, tile);
+    public float tileProfilingGetFloat(int frame, int tile, String key) {
+        return nativeTileProfilingGetFloat(frame, tile, key);
     }
 
     private native int nativeCacheHitFramePointer();
@@ -9262,10 +9254,8 @@
     private native void     nativeTileProfilingClear();
     private native int      nativeTileProfilingNumFrames();
     private native int      nativeTileProfilingNumTilesInFrame(int frame);
-    private native int      nativeTileProfilingGetX(int frame, int tile);
-    private native int      nativeTileProfilingGetY(int frame, int tile);
-    private native boolean  nativeTileProfilingGetReady(int frame, int tile);
-    private native int      nativeTileProfilingGetLevel(int frame, int tile);
+    private native int      nativeTileProfilingGetInt(int frame, int tile, String key);
+    private native float    nativeTileProfilingGetFloat(int frame, int tile, String key);
     // Never call this version except by updateCachedTextfield(String) -
     // we always want to pass in our generation number.
     private native void     nativeUpdateCachedTextfield(String updatedText,
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index d7a2526..8d8023b 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1069,6 +1069,15 @@
                                 + " arg1=" + msg.arg1 + " arg2=" + msg.arg2
                                 + " obj=" + msg.obj);
                     }
+                    if (mWebView == null
+                            && msg.what != EventHub.RESUME_TIMERS
+                            && msg.what != EventHub.PAUSE_TIMERS) {
+                        if (DebugFlags.WEB_VIEW_CORE) {
+                            Log.v(LOGTAG, "Rejecting message " + msg.what
+                                    + " because we are destroyed");
+                        }
+                        return;
+                    }
                     switch (msg.what) {
                         case WEBKIT_DRAW:
                             webkitDraw();
@@ -1757,30 +1766,17 @@
     }
 
     /**
-     * Removes pending messages and trigger a DESTROY message to send to
-     * WebCore.
+     * Sends a DESTROY message to WebCore.
      * Called from UI thread.
      */
     void destroy() {
-        // We don't want anyone to post a message between removing pending
-        // messages and sending the destroy message.
         synchronized (mEventHub) {
-            // RESUME_TIMERS and PAUSE_TIMERS are per process base. They need to
-            // be preserved even the WebView is destroyed.
-            // Note: we should not have more than one RESUME_TIMERS/PAUSE_TIMERS
-            boolean hasResume = mEventHub.hasMessages(EventHub.RESUME_TIMERS);
-            boolean hasPause = mEventHub.hasMessages(EventHub.PAUSE_TIMERS);
-            mEventHub.removeMessages();
+            // Do not call removeMessages as then we risk removing PAUSE_TIMERS
+            // or RESUME_TIMERS messages, which we must still handle as they
+            // are per process. DESTROY will instead trigger a white list in
+            // mEventHub, skipping any remaining messages in the queue
             mEventHub.sendMessageAtFrontOfQueue(
                     Message.obtain(null, EventHub.DESTROY));
-            if (hasPause) {
-                mEventHub.sendMessageAtFrontOfQueue(
-                        Message.obtain(null, EventHub.PAUSE_TIMERS));
-            }
-            if (hasResume) {
-                mEventHub.sendMessageAtFrontOfQueue(
-                        Message.obtain(null, EventHub.RESUME_TIMERS));
-            }
             mEventHub.blockMessages();
         }
     }
@@ -2113,13 +2109,17 @@
 
     // called from JNI or WebView thread
     /* package */ void contentDraw() {
-        // don't update the Picture until we have an initial width and finish
-        // the first layout
-        if (mCurrentViewWidth == 0 || !mBrowserFrame.firstLayoutDone()) {
-            return;
-        }
-        // only fire an event if this is our first request
         synchronized (this) {
+            if (mWebView == null || mBrowserFrame == null) {
+                // We were destroyed
+                return;
+            }
+            // don't update the Picture until we have an initial width and finish
+            // the first layout
+            if (mCurrentViewWidth == 0 || !mBrowserFrame.firstLayoutDone()) {
+                return;
+            }
+            // only fire an event if this is our first request
             if (mDrawIsScheduled) return;
             mDrawIsScheduled = true;
             if (mDrawIsPaused) return;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 8f8c1d0..b7c1687 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -4638,9 +4638,6 @@
                             childrenTop += getVerticalFadingEdgeLength();
                         }
                     }
-                    // Don't ever focus a disabled item.
-                    if (!mAdapter.isEnabled(i)) continue;
-
                     if (top >= childrenTop) {
                         // Found a view whose top is fully visisble
                         selectedPos = firstPosition + i;
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 755d4e0..00c75a9 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -902,15 +902,16 @@
 
     @Override
     public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
-        // Add a record for ourselves as well.
-        AccessibilityEvent record = AccessibilityEvent.obtain();
-        record.setSource(this);
-        // Set the class since it is not populated in #dispatchPopulateAccessibilityEvent
-        record.setClassName(getClass().getName());
-        child.onInitializeAccessibilityEvent(record);
-        child.dispatchPopulateAccessibilityEvent(record);
-        event.appendRecord(record);
-        return true;
+        if (super.onRequestSendAccessibilityEvent(child, event)) {
+            // Add a record for ourselves as well.
+            AccessibilityEvent record = AccessibilityEvent.obtain();
+            onInitializeAccessibilityEvent(record);
+            // Populate with the text of the requesting child.
+            child.dispatchPopulateAccessibilityEvent(record);
+            event.appendRecord(record);
+            return true;
+        }
+        return false;
     }
 
     @Override
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 49616cc..f3a6da7 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -39,8 +39,9 @@
     private boolean mChecked;
     private int mCheckMarkResource;
     private Drawable mCheckMarkDrawable;
-    private int mBasePaddingRight;
+    private int mBasePadding;
     private int mCheckMarkWidth;
+    private boolean mNeedRequestlayout;
 
     private static final int[] CHECKED_STATE_SET = {
         R.attr.state_checked
@@ -123,6 +124,7 @@
             mCheckMarkDrawable.setCallback(null);
             unscheduleDrawable(mCheckMarkDrawable);
         }
+        mNeedRequestlayout = (d != mCheckMarkDrawable);
         if (d != null) {
             d.setCallback(this);
             d.setVisible(getVisibility() == VISIBLE, false);
@@ -130,19 +132,35 @@
             setMinHeight(d.getIntrinsicHeight());
             
             mCheckMarkWidth = d.getIntrinsicWidth();
-            mUserPaddingRight = mCheckMarkWidth + mBasePaddingRight;
             d.setState(getDrawableState());
         } else {
-            mUserPaddingRight = mBasePaddingRight;
+            mCheckMarkWidth = 0;
         }
         mCheckMarkDrawable = d;
-        requestLayout();
+        // Do padding resolution. This will call setPadding() and do a requestLayout() if needed.
+        resolvePadding();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    protected void resolvePadding() {
+        super.resolvePadding();
+        int newPadding = (mCheckMarkDrawable != null) ?
+                mCheckMarkWidth + mBasePadding : mBasePadding;
+        mNeedRequestlayout |= (mPaddingRight != newPadding);
+        mPaddingRight = newPadding;
+        if (mNeedRequestlayout) {
+            requestLayout();
+            mNeedRequestlayout = false;
+        }
     }
     
     @Override
     public void setPadding(int left, int top, int right, int bottom) {
         super.setPadding(left, top, right, bottom);
-        mBasePaddingRight = mUserPaddingRight;
+        mBasePadding = mPaddingRight;
     }
 
     @Override
@@ -167,9 +185,9 @@
             
             int right = getWidth();
             checkMarkDrawable.setBounds(
-                    right - mUserPaddingRight,
+                    right - mPaddingRight,
                     y, 
-                    right - mUserPaddingRight + mCheckMarkWidth,
+                    right - mPaddingRight + mCheckMarkWidth,
                     y + height);
             checkMarkDrawable.draw(canvas);
         }
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 161b404..299e1ff 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -30,14 +30,15 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.RemotableViewMethod;
 import android.view.View;
 import android.view.ViewDebug;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.RemoteViews.RemoteView;
 
-
 /**
  * Displays an arbitrary image, such as an icon.  The ImageView class
  * can load images from various sources (such as resources or content
@@ -208,7 +209,15 @@
         }
         return false;
     }
-    
+
+    @Override
+    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+        CharSequence contentDescription = getContentDescription();
+        if (!TextUtils.isEmpty(contentDescription)) {
+            event.getText().add(contentDescription);
+        }
+    }
+
     /**
      * Set this to true if you want the ImageView to adjust its bounds
      * to preserve the aspect ratio of its drawable.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 108ac33..a7324b0 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -329,7 +329,7 @@
     private int mTextEditPasteWindowLayout, mTextEditSidePasteWindowLayout;
     private int mTextEditNoPasteWindowLayout, mTextEditSideNoPasteWindowLayout;
 
-    private int mTextEditSuggestionsBottomWindowLayout, mTextEditSuggestionsTopWindowLayout;
+    private int mTextEditSuggestionsWindowLayout;
     private int mTextEditSuggestionItemLayout;
     private SuggestionsPopupWindow mSuggestionsPopupWindow;
     private SuggestionRangeSpan mSuggestionRangeSpan;
@@ -830,12 +830,8 @@
                 mTextEditSideNoPasteWindowLayout = a.getResourceId(attr, 0);
                 break;
 
-            case com.android.internal.R.styleable.TextView_textEditSuggestionsBottomWindowLayout:
-                mTextEditSuggestionsBottomWindowLayout = a.getResourceId(attr, 0);
-                break;
-
-            case com.android.internal.R.styleable.TextView_textEditSuggestionsTopWindowLayout:
-                mTextEditSuggestionsTopWindowLayout = a.getResourceId(attr, 0);
+            case com.android.internal.R.styleable.TextView_textEditSuggestionsWindowLayout:
+                mTextEditSuggestionsWindowLayout = a.getResourceId(attr, 0);
                 break;
 
             case com.android.internal.R.styleable.TextView_textEditSuggestionItemLayout:
@@ -8785,9 +8781,7 @@
         private static final int MAX_NUMBER_SUGGESTIONS = 5;
         private static final int NO_SUGGESTIONS = -1;
         private final PopupWindow mContainer;
-        private final ViewGroup[] mSuggestionViews = new ViewGroup[2];
-        private final int[] mSuggestionViewLayouts = new int[] {
-                mTextEditSuggestionsBottomWindowLayout, mTextEditSuggestionsTopWindowLayout};
+        private ViewGroup mSuggestionViewGroup;
         private WordIterator mSuggestionWordIterator;
         private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan[0];
 
@@ -8809,12 +8803,8 @@
             int suggestionIndex; // the index of the suggestion inside suggestionSpan
         }
 
-        private ViewGroup getViewGroup(boolean under) {
-            final int viewIndex = under ? 0 : 1;
-            ViewGroup viewGroup = mSuggestionViews[viewIndex];
-
-            if (viewGroup == null) {
-                final int layout = mSuggestionViewLayouts[viewIndex];
+        private void initSuggestionViewGroup() {
+            if (mSuggestionViewGroup == null) {
                 LayoutInflater inflater = (LayoutInflater) TextView.this.mContext.
                         getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
@@ -8823,19 +8813,19 @@
                             "Unable to create TextEdit suggestion window inflater");
                 }
 
-                View view = inflater.inflate(layout, null);
+                View view = inflater.inflate(mTextEditSuggestionsWindowLayout, null);
 
                 if (! (view instanceof ViewGroup)) {
                     throw new IllegalArgumentException(
                             "Inflated TextEdit suggestion window is not a ViewGroup: " + view);
                 }
 
-                viewGroup = (ViewGroup) view;
+                mSuggestionViewGroup = (ViewGroup) view;
 
                 // Inflate the suggestion items once and for all.
                 for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) {
-                    View childView = inflater.inflate(mTextEditSuggestionItemLayout, viewGroup,
-                            false);
+                    View childView = inflater.inflate(mTextEditSuggestionItemLayout,
+                            mSuggestionViewGroup, false);
 
                     if (! (childView instanceof TextView)) {
                         throw new IllegalArgumentException(
@@ -8843,14 +8833,12 @@
                     }
 
                     childView.setTag(new SuggestionInfo());
-                    viewGroup.addView(childView);
+                    mSuggestionViewGroup.addView(childView);
                     childView.setOnClickListener(this);
                 }
 
-                mSuggestionViews[viewIndex] = viewGroup;
+                mContainer.setContentView(mSuggestionViewGroup);
             }
-
-            return viewGroup;
         }
 
         public void show() {
@@ -8861,8 +8849,7 @@
             SuggestionSpan[] suggestionSpans = spannable.getSpans(pos, pos, SuggestionSpan.class);
             final int nbSpans = suggestionSpans.length;
 
-            ViewGroup viewGroup = getViewGroup(true);
-            mContainer.setContentView(viewGroup);
+            initSuggestionViewGroup();
 
             int totalNbSuggestions = 0;
             int spanUnionStart = mText.length();
@@ -8878,7 +8865,8 @@
                 String[] suggestions = suggestionSpan.getSuggestions();
                 int nbSuggestions = suggestions.length;
                 for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) {
-                    TextView textView = (TextView) viewGroup.getChildAt(totalNbSuggestions);
+                    TextView textView = (TextView) mSuggestionViewGroup.getChildAt(
+                            totalNbSuggestions);
                     textView.setText(suggestions[suggestionIndex]);
                     SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
                     suggestionInfo.spanStart = spanStart;
@@ -8897,7 +8885,7 @@
 
             if (totalNbSuggestions == 0) {
                 // TODO Replace by final text, use a dedicated layout, add a fade out timer...
-                TextView textView = (TextView) viewGroup.getChildAt(0);
+                TextView textView = (TextView) mSuggestionViewGroup.getChildAt(0);
                 textView.setText("No suggestions available");
                 SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
                 suggestionInfo.spanStart = NO_SUGGESTIONS;
@@ -8908,17 +8896,24 @@
                         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
 
                 for (int i = 0; i < totalNbSuggestions; i++) {
-                    final TextView textView = (TextView) viewGroup.getChildAt(i);
+                    final TextView textView = (TextView) mSuggestionViewGroup.getChildAt(i);
                     highlightTextDifferences(textView, spanUnionStart, spanUnionEnd);
                 }
             }
 
-            for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) {
-                viewGroup.getChildAt(i).setVisibility(i < totalNbSuggestions ? VISIBLE : GONE);
+            for (int i = 0; i < totalNbSuggestions; i++) {
+                mSuggestionViewGroup.getChildAt(i).setVisibility(VISIBLE);
+            }
+            for (int i = totalNbSuggestions; i < MAX_NUMBER_SUGGESTIONS; i++) {
+                mSuggestionViewGroup.getChildAt(i).setVisibility(GONE);
             }
 
-            final int size = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
-            viewGroup.measure(size, size);
+            final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
+            final int screenWidth = displayMetrics.widthPixels;
+            final int screenHeight = displayMetrics.heightPixels;
+            mSuggestionViewGroup.measure(
+                    View.MeasureSpec.makeMeasureSpec(screenWidth, View.MeasureSpec.AT_MOST),
+                    View.MeasureSpec.makeMeasureSpec(screenHeight, View.MeasureSpec.AT_MOST));
 
             positionAtCursor();
         }
@@ -9171,23 +9166,12 @@
 
             // Vertical clipping
             if (coords[1] + height > screenHeight) {
-                // Try to position above current line instead
-                // TODO use top layout instead, reverse suggestion order,
-                // try full screen vertical down if it still does not fit. TBD with designers.
-
-                // Update dimensions from new view
-                contentView = mContainer.getContentView();
-                width = contentView.getMeasuredWidth();
-                height = contentView.getMeasuredHeight();
-
-                final int lineTop = mLayout.getLineTop(line);
-                final int lineHeight = lineBottom - lineTop;
-                coords[1] -= height + lineHeight;
+                coords[1] = screenHeight - height;
             }
 
             // Horizontal clipping
-            coords[0] = Math.max(0, coords[0]);
             coords[0] = Math.min(displayMetrics.widthPixels - width, coords[0]);
+            coords[0] = Math.max(0, coords[0]);
 
             mContainer.showAtLocation(TextView.this, Gravity.NO_GRAVITY, coords[0], coords[1]);
         }
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 8d6caa1..2061c90 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -438,7 +438,7 @@
             LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                     LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
             
-            topPanel.addView(mCustomTitleView, lp);
+            topPanel.addView(mCustomTitleView, 0, lp);
             
             // Hide the title template
             View titleTemplate = mWindow.findViewById(R.id.title_template);
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index a9e5057..07430e7 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -27,7 +27,7 @@
     void expand();
     void collapse();
     void disable(int what, IBinder token, String pkg);
-    void setIcon(String slot, String iconPackage, int iconId, int iconLevel);
+    void setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription);
     void setIconVisibility(String slot, boolean visible);
     void removeIcon(String slot);
     void topAppWindowChanged(boolean menuVisible);
diff --git a/core/java/com/android/internal/statusbar/StatusBarIcon.java b/core/java/com/android/internal/statusbar/StatusBarIcon.java
index ae2cac2..3333c82 100644
--- a/core/java/com/android/internal/statusbar/StatusBarIcon.java
+++ b/core/java/com/android/internal/statusbar/StatusBarIcon.java
@@ -19,42 +19,35 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
-/**
- * @hide
- */
 public class StatusBarIcon implements Parcelable {
     public String iconPackage;
     public int iconId;
     public int iconLevel;
     public boolean visible = true;
     public int number;
+    public CharSequence contentDescription;
 
-    private StatusBarIcon() {
-    }
-
-    public StatusBarIcon(String iconPackage, int iconId, int iconLevel) {
-        this.iconPackage = iconPackage;
-        this.iconId = iconId;
-        this.iconLevel = iconLevel;
-    }
-
-    public StatusBarIcon(String iconPackage, int iconId, int iconLevel, int number) {
+    public StatusBarIcon(String iconPackage, int iconId, int iconLevel, int number,
+            CharSequence contentDescription) {
         this.iconPackage = iconPackage;
         this.iconId = iconId;
         this.iconLevel = iconLevel;
         this.number = number;
+        this.contentDescription = contentDescription;
     }
 
+    @Override
     public String toString() {
         return "StatusBarIcon(pkg=" + this.iconPackage + " id=0x" + Integer.toHexString(this.iconId)
                 + " level=" + this.iconLevel + " visible=" + visible
                 + " num=" + this.number + " )";
     }
 
+    @Override
     public StatusBarIcon clone() {
-        StatusBarIcon that = new StatusBarIcon(this.iconPackage, this.iconId, this.iconLevel);
+        StatusBarIcon that = new StatusBarIcon(this.iconPackage, this.iconId, this.iconLevel,
+                this.number, this.contentDescription);
         that.visible = this.visible;
-        that.number = this.number;
         return that;
     }
 
@@ -71,6 +64,7 @@
         this.iconLevel = in.readInt();
         this.visible = in.readInt() != 0;
         this.number = in.readInt();
+        this.contentDescription = in.readCharSequence();
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -79,6 +73,7 @@
         out.writeInt(this.iconLevel);
         out.writeInt(this.visible ? 1 : 0);
         out.writeInt(this.number);
+        out.writeCharSequence(this.contentDescription);
     }
 
     public int describeContents() {
diff --git a/core/java/com/android/internal/textservice/ISpellCheckerService.aidl b/core/java/com/android/internal/textservice/ISpellCheckerService.aidl
new file mode 100644
index 0000000..ff00492
--- /dev/null
+++ b/core/java/com/android/internal/textservice/ISpellCheckerService.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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 com.android.internal.textservice;
+
+import com.android.internal.textservice.ISpellCheckerSession;
+import com.android.internal.textservice.ISpellCheckerSessionListener;
+
+/**
+ * Public interface to the global spell checker.
+ * @hide
+ */
+interface ISpellCheckerService {
+    ISpellCheckerSession getISpellCheckerSession(
+            String locale, ISpellCheckerSessionListener listener);
+}
diff --git a/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl b/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl
new file mode 100644
index 0000000..79e43510c0
--- /dev/null
+++ b/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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 com.android.internal.textservice;
+
+import android.view.textservice.TextInfo;
+
+/**
+ * @hide
+ */
+oneway interface ISpellCheckerSession {
+    void getSuggestionsMultiple(
+            in TextInfo[] textInfos, int suggestionsLimit, boolean multipleWords);
+    void cancel();
+}
diff --git a/core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl b/core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl
new file mode 100644
index 0000000..796b06e
--- /dev/null
+++ b/core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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 com.android.internal.textservice;
+
+import android.view.textservice.SuggestionsInfo;
+
+/**
+ * @hide
+ */
+oneway interface ISpellCheckerSessionListener {
+    void onGetSuggestions(in SuggestionsInfo[] results);
+}
diff --git a/core/java/com/android/internal/textservice/ITextServicesManager.aidl b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
new file mode 100644
index 0000000..ad0c1ff
--- /dev/null
+++ b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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 com.android.internal.textservice;
+
+import com.android.internal.textservice.ISpellCheckerSessionListener;
+import com.android.internal.textservice.ITextServicesSessionListener;
+
+import android.content.ComponentName;
+import android.view.textservice.SpellCheckerInfo;
+
+/**
+ * Interface to the text service manager.
+ * @hide
+ */
+interface ITextServicesManager {
+    SpellCheckerInfo getCurrentSpellChecker(String locale);
+    oneway void getSpellCheckerService(in SpellCheckerInfo info, in String locale,
+            in ITextServicesSessionListener tsListener,
+            in ISpellCheckerSessionListener scListener);
+    oneway void finishSpellCheckerService(in ISpellCheckerSessionListener listener);
+}
diff --git a/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl b/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl
new file mode 100644
index 0000000..ecb6cd0
--- /dev/null
+++ b/core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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 com.android.internal.textservice;
+
+import com.android.internal.textservice.ISpellCheckerSession;
+
+import android.view.textservice.SpellCheckerInfo;
+
+/**
+ * Interface to the text service session.
+ * @hide
+ */
+interface ITextServicesSessionListener {
+    oneway void onServiceConnected(in ISpellCheckerSession spellCheckerSession);
+}
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index 164d581..159b3da 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -50,6 +50,8 @@
     private static final String LOGTAG = "MenuBuilder";
 
     private static final String PRESENTER_KEY = "android:menu:presenters";
+    private static final String ACTION_VIEW_STATES_KEY = "android:menu:actionviewstates";
+    private static final String EXPANDED_ACTION_VIEW_ID = "android:menu:expandedactionview";
 
     private static final int[]  sCategoryToOrder = new int[] {
         1, /* No category */
@@ -308,6 +310,67 @@
         dispatchRestoreInstanceState(state);
     }
 
+    public void saveActionViewStates(Bundle outStates) {
+        SparseArray<Parcelable> viewStates = null;
+
+        final int itemCount = size();
+        for (int i = 0; i < itemCount; i++) {
+            final MenuItem item = getItem(i);
+            final View v = item.getActionView();
+            if (v != null && v.getId() != View.NO_ID) {
+                if (viewStates == null) {
+                    viewStates = new SparseArray<Parcelable>();
+                }
+                v.saveHierarchyState(viewStates);
+                if (item.isActionViewExpanded()) {
+                    outStates.putInt(EXPANDED_ACTION_VIEW_ID, item.getItemId());
+                }
+            }
+            if (item.hasSubMenu()) {
+                final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
+                subMenu.saveActionViewStates(outStates);
+            }
+        }
+
+        if (viewStates != null) {
+            outStates.putSparseParcelableArray(getActionViewStatesKey(), viewStates);
+        }
+    }
+
+    public void restoreActionViewStates(Bundle states) {
+        if (states == null) {
+            return;
+        }
+
+        SparseArray<Parcelable> viewStates = states.getSparseParcelableArray(
+                getActionViewStatesKey());
+
+        final int itemCount = size();
+        for (int i = 0; i < itemCount; i++) {
+            final MenuItem item = getItem(i);
+            final View v = item.getActionView();
+            if (v != null && v.getId() != View.NO_ID) {
+                v.restoreHierarchyState(viewStates);
+            }
+            if (item.hasSubMenu()) {
+                final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
+                subMenu.restoreActionViewStates(states);
+            }
+        }
+
+        final int expandedId = states.getInt(EXPANDED_ACTION_VIEW_ID);
+        if (expandedId > 0) {
+            MenuItem itemToExpand = findItem(expandedId);
+            if (itemToExpand != null) {
+                itemToExpand.expandActionView();
+            }
+        }
+    }
+
+    protected String getActionViewStatesKey() {
+        return ACTION_VIEW_STATES_KEY;
+    }
+
     public void setCallback(Callback cb) {
         mCallback = cb;
     }
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 541d101..b0a002d 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -553,6 +553,9 @@
     public MenuItem setActionView(View view) {
         mActionView = view;
         mActionProvider = null;
+        if (view != null && view.getId() == View.NO_ID && mId > 0) {
+            view.setId(mId);
+        }
         mMenu.onItemActionRequestChanged(this);
         return this;
     }
diff --git a/core/java/com/android/internal/view/menu/SubMenuBuilder.java b/core/java/com/android/internal/view/menu/SubMenuBuilder.java
index fb1cd5e..92acf8c 100644
--- a/core/java/com/android/internal/view/menu/SubMenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/SubMenuBuilder.java
@@ -121,4 +121,13 @@
     public boolean collapseItemActionView(MenuItemImpl item) {
         return mParentMenu.collapseItemActionView(item);
     }
+
+    @Override
+    public String getActionViewStatesKey() {
+        final int itemId = mItem != null ? mItem.getItemId() : 0;
+        if (itemId == 0) {
+            return null;
+        }
+        return super.getActionViewStatesKey() + ":" + itemId;
+    }
 }
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index e03858b..8b74f3d 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -42,6 +42,7 @@
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.view.CollapsibleActionView;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -1304,6 +1305,10 @@
             if (mCustomNavView != null) mCustomNavView.setVisibility(GONE);
             requestLayout();
             item.setActionViewExpanded(true);
+
+            if (mExpandedActionView instanceof CollapsibleActionView) {
+                ((CollapsibleActionView) mExpandedActionView).onActionViewExpanded();
+            }
             return true;
         }
 
@@ -1330,11 +1335,16 @@
             if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
                 mCustomNavView.setVisibility(VISIBLE);
             }
+            View collapsedView = mExpandedActionView;
             mExpandedActionView = null;
             mExpandedHomeLayout.setIcon(null);
             mCurrentExpandedItem = null;
             requestLayout();
             item.setActionViewExpanded(false);
+
+            if (collapsedView instanceof CollapsibleActionView) {
+                ((CollapsibleActionView) collapsedView).onActionViewCollapsed();
+            }
             return true;
         }
 
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index e930c5c..0c81634 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -315,26 +315,56 @@
     return doBooleanCommand("OK", "DRIVER STOP");
 }
 
-static jboolean android_net_wifi_startPacketFiltering(JNIEnv* env, jobject)
+/*
+    Multicast filtering rules work as follows:
+
+    The driver can filter multicast (v4 and/or v6) and broadcast packets when in
+    a power optimized mode (typically when screen goes off).
+
+    In order to prevent the driver from filtering the multicast/broadcast packets, we have to
+    add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective
+
+    DRIVER RXFILTER-ADD Num
+        where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6
+
+    and DRIVER RXFILTER-START
+
+    In order to stop the usage of these rules, we do
+
+    DRIVER RXFILTER-STOP
+    DRIVER RXFILTER-REMOVE Num
+        where Num is as described for RXFILTER-ADD
+
+    The  SETSUSPENDOPT driver command overrides the filtering rules
+*/
+
+static jboolean android_net_wifi_startMultiV4Filtering(JNIEnv* env, jobject)
 {
-    return doBooleanCommand("OK", "DRIVER RXFILTER-ADD 0")
-            && doBooleanCommand("OK", "DRIVER RXFILTER-ADD 1")
-            && doBooleanCommand("OK", "DRIVER RXFILTER-ADD 3")
+    return doBooleanCommand("OK", "DRIVER RXFILTER-STOP")
+            && doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 2")
             && doBooleanCommand("OK", "DRIVER RXFILTER-START");
 }
 
-static jboolean android_net_wifi_stopPacketFiltering(JNIEnv* env, jobject)
+static jboolean android_net_wifi_stopMultiV4Filtering(JNIEnv* env, jobject)
 {
-    jboolean result = doBooleanCommand("OK", "DRIVER RXFILTER-STOP");
-    if (result) {
-        (void)doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 3");
-        (void)doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 1");
-        (void)doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 0");
-    }
-
-    return result;
+    return doBooleanCommand("OK", "DRIVER RXFILTER-ADD 2")
+            && doBooleanCommand("OK", "DRIVER RXFILTER-START");
 }
 
+static jboolean android_net_wifi_startMultiV6Filtering(JNIEnv* env, jobject)
+{
+    return doBooleanCommand("OK", "DRIVER RXFILTER-STOP")
+            && doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 3")
+            && doBooleanCommand("OK", "DRIVER RXFILTER-START");
+}
+
+static jboolean android_net_wifi_stopMultiV6Filtering(JNIEnv* env, jobject)
+{
+    return doBooleanCommand("OK", "DRIVER RXFILTER-ADD 3")
+        && doBooleanCommand("OK", "DRIVER RXFILTER-START");
+}
+
+
 static jint android_net_wifi_getRssiHelper(const char *cmd)
 {
     char reply[BUF_SIZE];
@@ -545,8 +575,10 @@
     { "setScanModeCommand", "(Z)Z", (void*) android_net_wifi_setScanModeCommand },
     { "startDriverCommand", "()Z", (void*) android_net_wifi_startDriverCommand },
     { "stopDriverCommand", "()Z", (void*) android_net_wifi_stopDriverCommand },
-    { "startPacketFiltering", "()Z", (void*) android_net_wifi_startPacketFiltering },
-    { "stopPacketFiltering", "()Z", (void*) android_net_wifi_stopPacketFiltering },
+    { "startFilteringMulticastV4Packets", "()Z", (void*) android_net_wifi_startMultiV4Filtering},
+    { "stopFilteringMulticastV4Packets", "()Z", (void*) android_net_wifi_stopMultiV4Filtering},
+    { "startFilteringMulticastV6Packets", "()Z", (void*) android_net_wifi_startMultiV6Filtering},
+    { "stopFilteringMulticastV6Packets", "()Z", (void*) android_net_wifi_stopMultiV6Filtering},
     { "setPowerModeCommand", "(I)Z", (void*) android_net_wifi_setPowerModeCommand },
     { "getPowerModeCommand", "()I", (void*) android_net_wifi_getPowerModeCommand },
     { "setBandCommand", "(I)Z", (void*) android_net_wifi_setBandCommand},
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index b0c2f2c..b06de9d 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -576,18 +576,18 @@
 // ----------------------------------------------------------------------------
 
 static DisplayList* android_view_GLES20Canvas_getDisplayList(JNIEnv* env,
-        jobject clazz, DisplayListRenderer* renderer) {
-    return renderer->getDisplayList();
+        jobject clazz, DisplayListRenderer* renderer, DisplayList* displayList) {
+    return renderer->getDisplayList(displayList);
 }
 
-static OpenGLRenderer* android_view_GLES20Canvas_getDisplayListRenderer(JNIEnv* env,
+static OpenGLRenderer* android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env,
+        jobject clazz) {
+    return new DisplayListRenderer;
+}
+
+static void android_view_GLES20Canvas_resetDisplayListRenderer(JNIEnv* env,
         jobject clazz, DisplayListRenderer* renderer) {
-    if (renderer == NULL) {
-        renderer = new DisplayListRenderer;
-    } else {
-        renderer->reset();
-    }
-    return renderer;
+    renderer->reset();
 }
 
 static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env,
@@ -812,9 +812,10 @@
     { "nGetClipBounds",     "(ILandroid/graphics/Rect;)Z",
             (void*) android_view_GLES20Canvas_getClipBounds },
 
-    { "nGetDisplayList",         "(I)I",       (void*) android_view_GLES20Canvas_getDisplayList },
+    { "nGetDisplayList",         "(II)I",      (void*) android_view_GLES20Canvas_getDisplayList },
     { "nDestroyDisplayList",     "(I)V",       (void*) android_view_GLES20Canvas_destroyDisplayList },
-    { "nGetDisplayListRenderer", "(I)I",       (void*) android_view_GLES20Canvas_getDisplayListRenderer },
+    { "nCreateDisplayListRenderer", "()I",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
+    { "nResetDisplayListRenderer", "(I)V",     (void*) android_view_GLES20Canvas_resetDisplayListRenderer },
     { "nDrawDisplayList",        "(IIIILandroid/graphics/Rect;)Z",
                                                (void*) android_view_GLES20Canvas_drawDisplayList },
     { "nOutputDisplayList",      "(II)V",      (void*) android_view_GLES20Canvas_outputDisplayList },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 103a326..91003d1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1120,6 +1120,13 @@
         android:description="@string/permdesc_bindInputMethod"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by a TextService (e.g. SpellCheckerService)
+         to ensure that only the system can bind to it. -->
+    <permission android:name="android.permission.BIND_TEXT_SERVICE"
+        android:label="@string/permlab_bindTextService"
+        android:description="@string/permdesc_bindTextService"
+        android:protectionLevel="signature" />
+
     <!-- Must be required by a {@link android.service.wallpaper.WallpaperService},
          to ensure that only the system can bind to it. -->
     <permission android:name="android.permission.BIND_WALLPAPER"
@@ -1197,7 +1204,7 @@
     <permission android:name="android.permission.READ_FRAME_BUFFER"
         android:label="@string/permlab_readFrameBuffer"
         android:description="@string/permdesc_readFrameBuffer"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signatureOrSystem" />
 
     <!-- Required to be able to disable the device (very dangerous!). -->
     <permission android:name="android.permission.BRICK"
diff --git a/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png b/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png
deleted file mode 100644
index ff6b34a..0000000
--- a/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_edit_suggestions_bottom_window.9.png b/core/res/res/drawable-hdpi/text_edit_suggestions_window.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/text_edit_suggestions_bottom_window.9.png
rename to core/res/res/drawable-hdpi/text_edit_suggestions_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_edit_suggestions_top_window.9.png b/core/res/res/drawable-mdpi/text_edit_suggestions_top_window.9.png
deleted file mode 100644
index 41886eb..0000000
--- a/core/res/res/drawable-mdpi/text_edit_suggestions_top_window.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_edit_suggestions_bottom_window.9.png b/core/res/res/drawable-mdpi/text_edit_suggestions_window.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/text_edit_suggestions_bottom_window.9.png
rename to core/res/res/drawable-mdpi/text_edit_suggestions_window.9.png
Binary files differ
diff --git a/core/res/res/layout/text_edit_suggestion_item.xml b/core/res/res/layout/text_edit_suggestion_item.xml
index ef537d9..082c5ec 100644
--- a/core/res/res/layout/text_edit_suggestion_item.xml
+++ b/core/res/res/layout/text_edit_suggestion_item.xml
@@ -22,6 +22,8 @@
           android:paddingTop="8dip"
           android:paddingBottom="8dip"
           android:layout_gravity="left|center_vertical"
+          android:singleLine="true"
+          android:ellipsize="marquee"
           android:textAppearance="?android:attr/textAppearanceMedium"
           android:textColor="@android:color/dim_foreground_light" />
 
diff --git a/core/res/res/layout/text_edit_suggestions_bottom_window.xml b/core/res/res/layout/text_edit_suggestions_bottom_window.xml
deleted file mode 100644
index 588bfbd..0000000
--- a/core/res/res/layout/text_edit_suggestions_bottom_window.xml
+++ /dev/null
@@ -1,23 +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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:background="@android:drawable/text_edit_suggestions_bottom_window">
-
-</LinearLayout>
diff --git a/core/res/res/layout/text_edit_suggestions_top_window.xml b/core/res/res/layout/text_edit_suggestions_window.xml
similarity index 98%
rename from core/res/res/layout/text_edit_suggestions_top_window.xml
rename to core/res/res/layout/text_edit_suggestions_window.xml
index 67faa37..824025e 100644
--- a/core/res/res/layout/text_edit_suggestions_top_window.xml
+++ b/core/res/res/layout/text_edit_suggestions_window.xml
@@ -18,6 +18,6 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:orientation="vertical"
-    android:background="@android:drawable/text_edit_suggestions_top_window">
+    android:background="@android:drawable/text_edit_suggestions_window">
 
 </LinearLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 082284a..7d7aea9 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -713,10 +713,7 @@
 
         <!-- Layout of a the view that is used to create the text suggestions popup window in an
              EditText. This window will be displayed below the text line. -->
-        <attr name="textEditSuggestionsBottomWindowLayout" format="reference" />
-        <!-- Same as textEditSuggestionsBottomWindowLayout, but used when the popup is displayed
-             above the current line of text instead of below. -->
-        <attr name="textEditSuggestionsTopWindowLayout" format="reference" />
+        <attr name="textEditSuggestionsWindowLayout" format="reference" />
         <!-- Layout of the TextView item that will populate the suggestion popup window. -->
         <attr name="textEditSuggestionItemLayout" format="reference" />
 
@@ -3082,10 +3079,7 @@
 
         <!-- Layout of a the view that is used to create the text suggestions popup window in an
              EditText. This window will be displayed below the text line. -->
-        <attr name="textEditSuggestionsBottomWindowLayout" />
-        <!-- Same as textEditSuggestionsBottomWindowLayout, but used when the popup is displayed
-             above the current line of text instead of below. -->
-        <attr name="textEditSuggestionsTopWindowLayout" />
+        <attr name="textEditSuggestionsWindowLayout" />
         <!-- Layout of the TextView item that will populate the suggestion popup window. -->
         <attr name="textEditSuggestionItemLayout" />
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 75f0c4e..b2b7025 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1715,8 +1715,7 @@
   <public type="attr" name="switchPreferenceStyle" />
 
   <public type="attr" name="textSuggestionsWindowStyle" />
-  <public type="attr" name="textEditSuggestionsBottomWindowLayout" />
-  <public type="attr" name="textEditSuggestionsTopWindowLayout" />
+  <public type="attr" name="textEditSuggestionsWindowLayout" />
   <public type="attr" name="textEditSuggestionItemLayout" />
 
   <public type="attr" name="suggestionsEnabled" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 2e870fe..feac38d 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -705,6 +705,12 @@
         interface of an input method. Should never be needed for normal applications.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_bindTextService">bind to a text service</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_bindTextService">Allows the holder to bind to the top-level
+        interface of a text service(e.g. SpellCheckerService). Should never be needed for normal applications.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_bindWallpaper">bind to a wallpaper</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_bindWallpaper">Allows the holder to bind to the top-level
@@ -2675,12 +2681,14 @@
     <!-- USB_STORAGE_ERROR dialog  ok button-->
     <string name="dlg_ok">OK</string>
 
-    <!-- USB_PREFERENCES: Notification for wehen the user connects the phone to a computer via USB in MTP mode.  This is the title -->
+    <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in MTP mode.  This is the title -->
     <string name="usb_mtp_notification_title">Connected as a media device</string>
-    <!-- USB_PREFERENCES: Notification for wehen the user connects the phone to a computer via USB in PTP mode.  This is the title -->
+    <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in PTP mode.  This is the title -->
     <string name="usb_ptp_notification_title">Connected as a camera</string>
-    <!-- USB_PREFERENCES: Notification for wehen the user connects the phone to a computer via USB in mass storage mode (for installer CD image).  This is the title -->
+    <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in mass storage mode (for installer CD image).  This is the title -->
     <string name="usb_cd_installer_notification_title">Connected as an installer</string>
+    <!-- USB_PREFERENCES: Notification for when a USB accessory is attached.  This is the title -->
+    <string name="usb_accessory_notification_title">Connected to a USB accessory</string>
     <!-- See USB_PREFERENCES. This is the message. -->
     <string name="usb_notification_message">Touch for other USB options</string>
 
@@ -3056,4 +3064,9 @@
     <!-- Title for a dialog showing possible activities for sharing in ShareActionProvider [CHAR LIMIT=25] -->
     <string name="share_action_provider_share_with">Share with...</string>
 
+    <!-- Status Bar icon descriptions -->
+
+    <!-- Description of for the status bar's icon that the device is locked for accessibility. [CHAR LIMIT=NONE] -->
+    <string name="status_bar_device_locked">Device locked.</string>
+
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index d647467..9b6c442 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -423,8 +423,7 @@
         <item name="android:textEditNoPasteWindowLayout">?android:attr/textEditNoPasteWindowLayout</item>
         <item name="android:textEditSidePasteWindowLayout">?android:attr/textEditSidePasteWindowLayout</item>
         <item name="android:textEditSideNoPasteWindowLayout">?android:attr/textEditSideNoPasteWindowLayout</item>
-        <item name="android:textEditSuggestionsBottomWindowLayout">?android:attr/textEditSuggestionsBottomWindowLayout</item>
-        <item name="android:textEditSuggestionsTopWindowLayout">?android:attr/textEditSuggestionsTopWindowLayout</item>
+        <item name="android:textEditSuggestionsWindowLayout">?android:attr/textEditSuggestionsWindowLayout</item>
         <item name="android:textEditSuggestionItemLayout">?android:attr/textEditSuggestionItemLayout</item>
         <item name="android:textCursorDrawable">?android:attr/textCursorDrawable</item>
     </style>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 90f3602..93ccfe3 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -190,8 +190,7 @@
         <item name="textEditSidePasteWindowLayout">@android:layout/text_edit_side_paste_window</item>
         <item name="textEditSideNoPasteWindowLayout">@android:layout/text_edit_side_no_paste_window</item>
         <item name="textSuggestionsWindowStyle">@android:style/Widget.TextSuggestions</item>
-        <item name="textEditSuggestionsBottomWindowLayout">@android:layout/text_edit_suggestions_bottom_window</item>
-        <item name="textEditSuggestionsTopWindowLayout">@android:layout/text_edit_suggestions_top_window</item>
+        <item name="textEditSuggestionsWindowLayout">@android:layout/text_edit_suggestions_window</item>
         <item name="textEditSuggestionItemLayout">@android:layout/text_edit_suggestion_item</item>
         <item name="textCursorDrawable">@null</item>
 
diff --git a/include/media/stagefright/openmax/OMX_IVCommon.h b/include/media/stagefright/openmax/OMX_IVCommon.h
index 7ed072b..97170d7 100644
--- a/include/media/stagefright/openmax/OMX_IVCommon.h
+++ b/include/media/stagefright/openmax/OMX_IVCommon.h
@@ -16,29 +16,29 @@
  * -------------------------------------------------------------------
  */
 /**
- * Copyright (c) 2008 The Khronos Group Inc. 
- * 
+ * Copyright (c) 2008 The Khronos Group Inc.
+ *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * without limitation the rights to use, copy, modify, merge, publish,
  * distribute, sublicense, and/or sell copies of the Software, and to
  * permit persons to whom the Software is furnished to do so, subject
- * to the following conditions: 
+ * to the following conditions:
  * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software. 
- * 
+ * in all copies or substantial portions of the Software.
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
 
-/** 
+/**
  * @file OMX_IVCommon.h - OpenMax IL version 1.1.2
  *  The structures needed by Video and Image components to exchange
  *  parameters and configuration data with the components.
@@ -53,7 +53,7 @@
 /**
  * Each OMX header must include all required header files to allow the header
  * to compile without errors.  The includes below are required for this header
- * file to compile successfully 
+ * file to compile successfully
  */
 
 #include <OMX_Core.h>
@@ -64,8 +64,8 @@
  */
 
 
-/** 
- * Enumeration defining possible uncompressed image/video formats. 
+/**
+ * Enumeration defining possible uncompressed image/video formats.
  *
  * ENUMS:
  *  Unused                 : Placeholder value when format is N/A
@@ -113,7 +113,7 @@
     OMX_COLOR_Format16bitBGR565,
     OMX_COLOR_Format18bitRGB666,
     OMX_COLOR_Format18bitARGB1665,
-    OMX_COLOR_Format19bitARGB1666, 
+    OMX_COLOR_Format19bitARGB1666,
     OMX_COLOR_Format24bitRGB888,
     OMX_COLOR_Format24bitBGR888,
     OMX_COLOR_Format24bitARGB1887,
@@ -136,55 +136,62 @@
     OMX_COLOR_FormatRawBayer8bit,
     OMX_COLOR_FormatRawBayer10bit,
     OMX_COLOR_FormatRawBayer8bitcompressed,
-    OMX_COLOR_FormatL2, 
-    OMX_COLOR_FormatL4, 
-    OMX_COLOR_FormatL8, 
-    OMX_COLOR_FormatL16, 
-    OMX_COLOR_FormatL24, 
+    OMX_COLOR_FormatL2,
+    OMX_COLOR_FormatL4,
+    OMX_COLOR_FormatL8,
+    OMX_COLOR_FormatL16,
+    OMX_COLOR_FormatL24,
     OMX_COLOR_FormatL32,
     OMX_COLOR_FormatYUV420PackedSemiPlanar,
     OMX_COLOR_FormatYUV422PackedSemiPlanar,
     OMX_COLOR_Format18BitBGR666,
     OMX_COLOR_Format24BitARGB6666,
     OMX_COLOR_Format24BitABGR6666,
-    OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_COLOR_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+    /**<Reserved android opaque colorformat. Tells the encoder that
+     * the actual colorformat will be  relayed by the
+     * 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.*/
+    OMX_COLOR_FormatAndroidOpaque = 0x7F000001,
     OMX_TI_COLOR_FormatYUV420PackedSemiPlanar = 0x7F000100,
     OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00,
     OMX_COLOR_FormatMax = 0x7FFFFFFF
 } OMX_COLOR_FORMATTYPE;
 
 
-/** 
+/**
  * Defines the matrix for conversion from RGB to YUV or vice versa.
- * iColorMatrix should be initialized with the fixed point values 
+ * iColorMatrix should be initialized with the fixed point values
  * used in converting between formats.
  */
 typedef struct OMX_CONFIG_COLORCONVERSIONTYPE {
     OMX_U32 nSize;              /**< Size of the structure in bytes */
-    OMX_VERSIONTYPE nVersion;   /**< OMX specification version info */ 
+    OMX_VERSIONTYPE nVersion;   /**< OMX specification version info */
     OMX_U32 nPortIndex;         /**< Port that this struct applies to */
     OMX_S32 xColorMatrix[3][3]; /**< Stored in signed Q16 format */
     OMX_S32 xColorOffset[4];    /**< Stored in signed Q16 format */
 }OMX_CONFIG_COLORCONVERSIONTYPE;
 
 
-/** 
- * Structure defining percent to scale each frame dimension.  For example:  
+/**
+ * Structure defining percent to scale each frame dimension.  For example:
  * To make the width 50% larger, use fWidth = 1.5 and to make the width
  * 1/2 the original size, use fWidth = 0.5
  */
 typedef struct OMX_CONFIG_SCALEFACTORTYPE {
     OMX_U32 nSize;            /**< Size of the structure in bytes */
-    OMX_VERSIONTYPE nVersion; /**< OMX specification version info */ 
+    OMX_VERSIONTYPE nVersion; /**< OMX specification version info */
     OMX_U32 nPortIndex;       /**< Port that this struct applies to */
     OMX_S32 xWidth;           /**< Fixed point value stored as Q16 */
     OMX_S32 xHeight;          /**< Fixed point value stored as Q16 */
 }OMX_CONFIG_SCALEFACTORTYPE;
 
 
-/** 
- * Enumeration of possible image filter types 
+/**
+ * Enumeration of possible image filter types
  */
 typedef enum OMX_IMAGEFILTERTYPE {
     OMX_ImageFilterNone,
@@ -195,23 +202,23 @@
     OMX_ImageFilterOilPaint,
     OMX_ImageFilterHatch,
     OMX_ImageFilterGpen,
-    OMX_ImageFilterAntialias, 
-    OMX_ImageFilterDeRing,       
+    OMX_ImageFilterAntialias,
+    OMX_ImageFilterDeRing,
     OMX_ImageFilterSolarize,
-    OMX_ImageFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_ImageFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_ImageFilterVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_ImageFilterMax = 0x7FFFFFFF
 } OMX_IMAGEFILTERTYPE;
 
 
-/** 
- * Image filter configuration 
+/**
+ * Image filter configuration
  *
  * STRUCT MEMBERS:
- *  nSize        : Size of the structure in bytes       
+ *  nSize        : Size of the structure in bytes
  *  nVersion     : OMX specification version information
- *  nPortIndex   : Port that this structure applies to 
- *  eImageFilter : Image filter type enumeration      
+ *  nPortIndex   : Port that this structure applies to
+ *  eImageFilter : Image filter type enumeration
  */
 typedef struct OMX_CONFIG_IMAGEFILTERTYPE {
     OMX_U32 nSize;
@@ -221,22 +228,22 @@
 } OMX_CONFIG_IMAGEFILTERTYPE;
 
 
-/** 
- * Customized U and V for color enhancement 
+/**
+ * Customized U and V for color enhancement
  *
  * STRUCT MEMBERS:
  *  nSize             : Size of the structure in bytes
- *  nVersion          : OMX specification version information 
+ *  nVersion          : OMX specification version information
  *  nPortIndex        : Port that this structure applies to
  *  bColorEnhancement : Enable/disable color enhancement
- *  nCustomizedU      : Practical values: 16-240, range: 0-255, value set for 
+ *  nCustomizedU      : Practical values: 16-240, range: 0-255, value set for
  *                      U component
- *  nCustomizedV      : Practical values: 16-240, range: 0-255, value set for 
+ *  nCustomizedV      : Practical values: 16-240, range: 0-255, value set for
  *                      V component
  */
 typedef struct OMX_CONFIG_COLORENHANCEMENTTYPE {
     OMX_U32 nSize;
-    OMX_VERSIONTYPE nVersion; 
+    OMX_VERSIONTYPE nVersion;
     OMX_U32 nPortIndex;
     OMX_BOOL bColorEnhancement;
     OMX_U8 nCustomizedU;
@@ -244,12 +251,12 @@
 } OMX_CONFIG_COLORENHANCEMENTTYPE;
 
 
-/** 
- * Define color key and color key mask 
+/**
+ * Define color key and color key mask
  *
  * STRUCT MEMBERS:
  *  nSize      : Size of the structure in bytes
- *  nVersion   : OMX specification version information 
+ *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
  *  nARGBColor : 32bit Alpha, Red, Green, Blue Color
  *  nARGBMask  : 32bit Mask for Alpha, Red, Green, Blue channels
@@ -263,12 +270,12 @@
 } OMX_CONFIG_COLORKEYTYPE;
 
 
-/** 
- * List of color blend types for pre/post processing 
+/**
+ * List of color blend types for pre/post processing
  *
  * ENUMS:
  *  None          : No color blending present
- *  AlphaConstant : Function is (alpha_constant * src) + 
+ *  AlphaConstant : Function is (alpha_constant * src) +
  *                  (1 - alpha_constant) * dst)
  *  AlphaPerPixel : Function is (alpha * src) + (1 - alpha) * dst)
  *  Alternate     : Function is alternating pixels from src and dst
@@ -284,21 +291,21 @@
     OMX_ColorBlendAnd,
     OMX_ColorBlendOr,
     OMX_ColorBlendInvert,
-    OMX_ColorBlendKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_ColorBlendKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_ColorBlendVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_ColorBlendMax = 0x7FFFFFFF
 } OMX_COLORBLENDTYPE;
 
 
-/** 
- * Color blend configuration 
+/**
+ * Color blend configuration
  *
  * STRUCT MEMBERS:
- *  nSize             : Size of the structure in bytes                        
- *  nVersion          : OMX specification version information                
- *  nPortIndex        : Port that this structure applies to                   
+ *  nSize             : Size of the structure in bytes
+ *  nVersion          : OMX specification version information
+ *  nPortIndex        : Port that this structure applies to
  *  nRGBAlphaConstant : Constant global alpha values when global alpha is used
- *  eColorBlend       : Color blend type enumeration                         
+ *  eColorBlend       : Color blend type enumeration
  */
 typedef struct OMX_CONFIG_COLORBLENDTYPE {
     OMX_U32 nSize;
@@ -309,15 +316,15 @@
 } OMX_CONFIG_COLORBLENDTYPE;
 
 
-/** 
+/**
  * Hold frame dimension
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes      
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
- *  nPortIndex : Port that this structure applies to     
- *  nWidth     : Frame width in pixels                 
- *  nHeight    : Frame height in pixels                
+ *  nPortIndex : Port that this structure applies to
+ *  nWidth     : Frame width in pixels
+ *  nHeight    : Frame height in pixels
  */
 typedef struct OMX_FRAMESIZETYPE {
     OMX_U32 nSize;
@@ -329,69 +336,69 @@
 
 
 /**
- * Rotation configuration 
+ * Rotation configuration
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes             
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
- *  nRotation  : +/- integer rotation value               
+ *  nRotation  : +/- integer rotation value
  */
 typedef struct OMX_CONFIG_ROTATIONTYPE {
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
     OMX_U32 nPortIndex;
-    OMX_S32 nRotation; 
+    OMX_S32 nRotation;
 } OMX_CONFIG_ROTATIONTYPE;
 
 
-/** 
- * Possible mirroring directions for pre/post processing 
+/**
+ * Possible mirroring directions for pre/post processing
  *
  * ENUMS:
- *  None       : No mirroring                         
- *  Vertical   : Vertical mirroring, flip on X axis   
- *  Horizontal : Horizontal mirroring, flip on Y axis  
+ *  None       : No mirroring
+ *  Vertical   : Vertical mirroring, flip on X axis
+ *  Horizontal : Horizontal mirroring, flip on Y axis
  *  Both       : Both vertical and horizontal mirroring
  */
 typedef enum OMX_MIRRORTYPE {
     OMX_MirrorNone = 0,
     OMX_MirrorVertical,
     OMX_MirrorHorizontal,
-    OMX_MirrorBoth, 
-    OMX_MirrorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_MirrorBoth,
+    OMX_MirrorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_MirrorVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
-    OMX_MirrorMax = 0x7FFFFFFF   
+    OMX_MirrorMax = 0x7FFFFFFF
 } OMX_MIRRORTYPE;
 
 
-/** 
- * Mirroring configuration 
+/**
+ * Mirroring configuration
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes      
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
- *  nPortIndex : Port that this structure applies to  
- *  eMirror    : Mirror type enumeration              
+ *  nPortIndex : Port that this structure applies to
+ *  eMirror    : Mirror type enumeration
  */
 typedef struct OMX_CONFIG_MIRRORTYPE {
     OMX_U32 nSize;
-    OMX_VERSIONTYPE nVersion; 
+    OMX_VERSIONTYPE nVersion;
     OMX_U32 nPortIndex;
     OMX_MIRRORTYPE  eMirror;
 } OMX_CONFIG_MIRRORTYPE;
 
 
-/** 
- * Position information only 
+/**
+ * Position information only
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes               
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
- *  nX         : X coordinate for the point                     
- *  nY         : Y coordinate for the point 
- */                      
+ *  nX         : X coordinate for the point
+ *  nY         : Y coordinate for the point
+ */
 typedef struct OMX_CONFIG_POINTTYPE {
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
@@ -401,37 +408,37 @@
 } OMX_CONFIG_POINTTYPE;
 
 
-/** 
- * Frame size plus position 
+/**
+ * Frame size plus position
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes                    
- *  nVersion   : OMX specification version information      
- *  nPortIndex : Port that this structure applies to    
+ *  nSize      : Size of the structure in bytes
+ *  nVersion   : OMX specification version information
+ *  nPortIndex : Port that this structure applies to
  *  nLeft      : X Coordinate of the top left corner of the rectangle
  *  nTop       : Y Coordinate of the top left corner of the rectangle
- *  nWidth     : Width of the rectangle                              
- *  nHeight    : Height of the rectangle                             
+ *  nWidth     : Width of the rectangle
+ *  nHeight    : Height of the rectangle
  */
 typedef struct OMX_CONFIG_RECTTYPE {
     OMX_U32 nSize;
-    OMX_VERSIONTYPE nVersion;  
-    OMX_U32 nPortIndex; 
-    OMX_S32 nLeft; 
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_S32 nLeft;
     OMX_S32 nTop;
     OMX_U32 nWidth;
     OMX_U32 nHeight;
 } OMX_CONFIG_RECTTYPE;
 
 
-/** 
- * Deblocking state; it is required to be set up before starting the codec 
+/**
+ * Deblocking state; it is required to be set up before starting the codec
  *
  * STRUCT MEMBERS:
- *  nSize       : Size of the structure in bytes      
- *  nVersion    : OMX specification version information 
+ *  nSize       : Size of the structure in bytes
+ *  nVersion    : OMX specification version information
  *  nPortIndex  : Port that this structure applies to
- *  bDeblocking : Enable/disable deblocking mode    
+ *  bDeblocking : Enable/disable deblocking mode
  */
 typedef struct OMX_PARAM_DEBLOCKINGTYPE {
     OMX_U32 nSize;
@@ -441,13 +448,13 @@
 } OMX_PARAM_DEBLOCKINGTYPE;
 
 
-/** 
- * Stabilization state 
+/**
+ * Stabilization state
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes          
- *  nVersion   : OMX specification version information    
- *  nPortIndex : Port that this structure applies to   
+ *  nSize      : Size of the structure in bytes
+ *  nVersion   : OMX specification version information
+ *  nPortIndex : Port that this structure applies to
  *  bStab      : Enable/disable frame stabilization state
  */
 typedef struct OMX_CONFIG_FRAMESTABTYPE {
@@ -458,8 +465,8 @@
 } OMX_CONFIG_FRAMESTABTYPE;
 
 
-/** 
- * White Balance control type 
+/**
+ * White Balance control type
  *
  * STRUCT MEMBERS:
  *  SunLight : Referenced in JSR-234
@@ -476,20 +483,20 @@
     OMX_WhiteBalControlIncandescent,
     OMX_WhiteBalControlFlash,
     OMX_WhiteBalControlHorizon,
-    OMX_WhiteBalControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_WhiteBalControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_WhiteBalControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_WhiteBalControlMax = 0x7FFFFFFF
 } OMX_WHITEBALCONTROLTYPE;
 
 
-/** 
- * White Balance control configuration 
+/**
+ * White Balance control configuration
  *
  * STRUCT MEMBERS:
- *  nSize            : Size of the structure in bytes       
+ *  nSize            : Size of the structure in bytes
  *  nVersion         : OMX specification version information
- *  nPortIndex       : Port that this structure applies to                 
- *  eWhiteBalControl : White balance enumeration            
+ *  nPortIndex       : Port that this structure applies to
+ *  eWhiteBalControl : White balance enumeration
  */
 typedef struct OMX_CONFIG_WHITEBALCONTROLTYPE {
     OMX_U32 nSize;
@@ -499,8 +506,8 @@
 } OMX_CONFIG_WHITEBALCONTROLTYPE;
 
 
-/** 
- * Exposure control type 
+/**
+ * Exposure control type
  */
 typedef enum OMX_EXPOSURECONTROLTYPE {
     OMX_ExposureControlOff = 0,
@@ -513,20 +520,20 @@
     OMX_ExposureControlBeach,
     OMX_ExposureControlLargeAperture,
     OMX_ExposureControlSmallApperture,
-    OMX_ExposureControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_ExposureControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_ExposureControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_ExposureControlMax = 0x7FFFFFFF
 } OMX_EXPOSURECONTROLTYPE;
 
 
-/** 
- * White Balance control configuration 
+/**
+ * White Balance control configuration
  *
  * STRUCT MEMBERS:
- *  nSize            : Size of the structure in bytes      
+ *  nSize            : Size of the structure in bytes
  *  nVersion         : OMX specification version information
- *  nPortIndex       : Port that this structure applies to                
- *  eExposureControl : Exposure control enumeration         
+ *  nPortIndex       : Port that this structure applies to
+ *  eExposureControl : Exposure control enumeration
  */
 typedef struct OMX_CONFIG_EXPOSURECONTROLTYPE {
     OMX_U32 nSize;
@@ -536,16 +543,16 @@
 } OMX_CONFIG_EXPOSURECONTROLTYPE;
 
 
-/** 
- * Defines sensor supported mode. 
+/**
+ * Defines sensor supported mode.
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes           
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
- *  nPortIndex : Port that this structure applies to 
- *  nFrameRate : Single shot mode is indicated by a 0     
+ *  nPortIndex : Port that this structure applies to
+ *  nFrameRate : Single shot mode is indicated by a 0
  *  bOneShot   : Enable for single shot, disable for streaming
- *  sFrameSize : Framesize                                          
+ *  sFrameSize : Framesize
  */
 typedef struct OMX_PARAM_SENSORMODETYPE {
     OMX_U32 nSize;
@@ -557,13 +564,13 @@
 } OMX_PARAM_SENSORMODETYPE;
 
 
-/** 
- * Defines contrast level 
+/**
+ * Defines contrast level
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes                              
- *  nVersion   : OMX specification version information                
- *  nPortIndex : Port that this structure applies to                 
+ *  nSize      : Size of the structure in bytes
+ *  nVersion   : OMX specification version information
+ *  nPortIndex : Port that this structure applies to
  *  nContrast  : Values allowed for contrast -100 to 100, zero means no change
  */
 typedef struct OMX_CONFIG_CONTRASTTYPE {
@@ -574,14 +581,14 @@
 } OMX_CONFIG_CONTRASTTYPE;
 
 
-/** 
- * Defines brightness level 
+/**
+ * Defines brightness level
  *
  * STRUCT MEMBERS:
- *  nSize       : Size of the structure in bytes          
- *  nVersion    : OMX specification version information 
- *  nPortIndex  : Port that this structure applies to 
- *  nBrightness : 0-100%        
+ *  nSize       : Size of the structure in bytes
+ *  nVersion    : OMX specification version information
+ *  nPortIndex  : Port that this structure applies to
+ *  nBrightness : 0-100%
  */
 typedef struct OMX_CONFIG_BRIGHTNESSTYPE {
     OMX_U32 nSize;
@@ -591,16 +598,16 @@
 } OMX_CONFIG_BRIGHTNESSTYPE;
 
 
-/** 
- * Defines backlight level configuration for a video sink, e.g. LCD panel 
+/**
+ * Defines backlight level configuration for a video sink, e.g. LCD panel
  *
  * STRUCT MEMBERS:
  *  nSize      : Size of the structure in bytes
- *  nVersion   : OMX specification version information 
+ *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
  *  nBacklight : Values allowed for backlight 0-100%
- *  nTimeout   : Number of milliseconds before backlight automatically turns 
- *               off.  A value of 0x0 disables backight timeout 
+ *  nTimeout   : Number of milliseconds before backlight automatically turns
+ *               off.  A value of 0x0 disables backight timeout
  */
 typedef struct OMX_CONFIG_BACKLIGHTTYPE {
     OMX_U32 nSize;
@@ -611,12 +618,12 @@
 } OMX_CONFIG_BACKLIGHTTYPE;
 
 
-/** 
- * Defines setting for Gamma 
+/**
+ * Defines setting for Gamma
  *
  * STRUCT MEMBERS:
  *  nSize      : Size of the structure in bytes
- *  nVersion   : OMX specification version information 
+ *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
  *  nGamma     : Values allowed for gamma -100 to 100, zero means no change
  */
@@ -628,14 +635,14 @@
 } OMX_CONFIG_GAMMATYPE;
 
 
-/** 
- * Define for setting saturation 
- * 
+/**
+ * Define for setting saturation
+ *
  * STRUCT MEMBERS:
  *  nSize       : Size of the structure in bytes
  *  nVersion    : OMX specification version information
  *  nPortIndex  : Port that this structure applies to
- *  nSaturation : Values allowed for saturation -100 to 100, zero means 
+ *  nSaturation : Values allowed for saturation -100 to 100, zero means
  *                no change
  */
 typedef struct OMX_CONFIG_SATURATIONTYPE {
@@ -646,14 +653,14 @@
 } OMX_CONFIG_SATURATIONTYPE;
 
 
-/** 
- * Define for setting Lightness 
+/**
+ * Define for setting Lightness
  *
  * STRUCT MEMBERS:
  *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
  *  nPortIndex : Port that this structure applies to
- *  nLightness : Values allowed for lightness -100 to 100, zero means no 
+ *  nLightness : Values allowed for lightness -100 to 100, zero means no
  *               change
  */
 typedef struct OMX_CONFIG_LIGHTNESSTYPE {
@@ -664,17 +671,17 @@
 } OMX_CONFIG_LIGHTNESSTYPE;
 
 
-/** 
- * Plane blend configuration 
+/**
+ * Plane blend configuration
  *
  * STRUCT MEMBERS:
- *  nSize      : Size of the structure in bytes 
+ *  nSize      : Size of the structure in bytes
  *  nVersion   : OMX specification version information
  *  nPortIndex : Index of input port associated with the plane.
- *  nDepth     : Depth of the plane in relation to the screen. Higher 
- *               numbered depths are "behind" lower number depths.  
+ *  nDepth     : Depth of the plane in relation to the screen. Higher
+ *               numbered depths are "behind" lower number depths.
  *               This number defaults to the Port Index number.
- *  nAlpha     : Transparency blending component for the entire plane.  
+ *  nAlpha     : Transparency blending component for the entire plane.
  *               See blending modes for more detail.
  */
 typedef struct OMX_CONFIG_PLANEBLENDTYPE {
@@ -686,17 +693,17 @@
 } OMX_CONFIG_PLANEBLENDTYPE;
 
 
-/** 
+/**
  * Define interlace type
  *
  * STRUCT MEMBERS:
- *  nSize                 : Size of the structure in bytes 
- *  nVersion              : OMX specification version information 
+ *  nSize                 : Size of the structure in bytes
+ *  nVersion              : OMX specification version information
  *  nPortIndex            : Port that this structure applies to
- *  bEnable               : Enable control variable for this functionality 
+ *  bEnable               : Enable control variable for this functionality
  *                          (see below)
- *  nInterleavePortIndex  : Index of input or output port associated with  
- *                          the interleaved plane. 
+ *  nInterleavePortIndex  : Index of input or output port associated with
+ *                          the interleaved plane.
  *  pPlanarPortIndexes[4] : Index of input or output planar ports.
  */
 typedef struct OMX_PARAM_INTERLEAVETYPE {
@@ -708,8 +715,8 @@
 } OMX_PARAM_INTERLEAVETYPE;
 
 
-/** 
- * Defines the picture effect used for an input picture 
+/**
+ * Defines the picture effect used for an input picture
  */
 typedef enum OMX_TRANSITIONEFFECTTYPE {
     OMX_EffectNone,
@@ -719,18 +726,18 @@
     OMX_EffectDissolve,
     OMX_EffectWipe,
     OMX_EffectUnspecifiedMixOfTwoScenes,
-    OMX_EffectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_EffectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_EffectVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_EffectMax = 0x7FFFFFFF
 } OMX_TRANSITIONEFFECTTYPE;
 
 
-/** 
- * Structure used to configure current transition effect 
+/**
+ * Structure used to configure current transition effect
  *
  * STRUCT MEMBERS:
  * nSize      : Size of the structure in bytes
- * nVersion   : OMX specification version information 
+ * nVersion   : OMX specification version information
  * nPortIndex : Port that this structure applies to
  * eEffect    : Effect to enable
  */
@@ -742,43 +749,43 @@
 } OMX_CONFIG_TRANSITIONEFFECTTYPE;
 
 
-/** 
- * Defines possible data unit types for encoded video data. The data unit 
+/**
+ * Defines possible data unit types for encoded video data. The data unit
  * types are used both for encoded video input for playback as well as
- * encoded video output from recording. 
+ * encoded video output from recording.
  */
 typedef enum OMX_DATAUNITTYPE {
     OMX_DataUnitCodedPicture,
     OMX_DataUnitVideoSegment,
     OMX_DataUnitSeveralSegments,
     OMX_DataUnitArbitraryStreamSection,
-    OMX_DataUnitKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_DataUnitKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_DataUnitVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_DataUnitMax = 0x7FFFFFFF
 } OMX_DATAUNITTYPE;
 
 
-/** 
- * Defines possible encapsulation types for coded video data unit. The 
- * encapsulation information is used both for encoded video input for 
- * playback as well as encoded video output from recording. 
+/**
+ * Defines possible encapsulation types for coded video data unit. The
+ * encapsulation information is used both for encoded video input for
+ * playback as well as encoded video output from recording.
  */
 typedef enum OMX_DATAUNITENCAPSULATIONTYPE {
     OMX_DataEncapsulationElementaryStream,
     OMX_DataEncapsulationGenericPayload,
     OMX_DataEncapsulationRtpPayload,
-    OMX_DataEncapsulationKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_DataEncapsulationKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_DataEncapsulationVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_DataEncapsulationMax = 0x7FFFFFFF
 } OMX_DATAUNITENCAPSULATIONTYPE;
 
 
-/** 
- * Structure used to configure the type of being decoded/encoded 
+/**
+ * Structure used to configure the type of being decoded/encoded
  */
 typedef struct OMX_PARAM_DATAUNITTYPE {
     OMX_U32 nSize;            /**< Size of the structure in bytes */
-    OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ 
+    OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
     OMX_U32 nPortIndex;       /**< Port that this structure applies to */
     OMX_DATAUNITTYPE eUnitType;
     OMX_DATAUNITENCAPSULATIONTYPE eEncapsulationType;
@@ -786,25 +793,25 @@
 
 
 /**
- * Defines dither types 
+ * Defines dither types
  */
 typedef enum OMX_DITHERTYPE {
     OMX_DitherNone,
     OMX_DitherOrdered,
     OMX_DitherErrorDiffusion,
     OMX_DitherOther,
-    OMX_DitherKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_DitherKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_DitherVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_DitherMax = 0x7FFFFFFF
 } OMX_DITHERTYPE;
 
 
-/** 
- * Structure used to configure current type of dithering 
+/**
+ * Structure used to configure current type of dithering
  */
 typedef struct OMX_CONFIG_DITHERTYPE {
     OMX_U32 nSize;            /**< Size of the structure in bytes */
-    OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ 
+    OMX_VERSIONTYPE nVersion; /**< OMX specification version information */
     OMX_U32 nPortIndex;       /**< Port that this structure applies to */
     OMX_DITHERTYPE eDither;   /**< Type of dithering to use */
 } OMX_CONFIG_DITHERTYPE;
@@ -813,28 +820,28 @@
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
     OMX_U32 nPortIndex;     /**< Port that this structure applies to */
-    OMX_BOOL bContinuous;   /**< If true then ignore frame rate and emit capture 
+    OMX_BOOL bContinuous;   /**< If true then ignore frame rate and emit capture
                              *   data as fast as possible (otherwise obey port's frame rate). */
-    OMX_BOOL bFrameLimited; /**< If true then terminate capture after the port emits the 
-                             *   specified number of frames (otherwise the port does not 
-                             *   terminate the capture until instructed to do so by the client). 
-                             *   Even if set, the client may manually terminate the capture prior 
+    OMX_BOOL bFrameLimited; /**< If true then terminate capture after the port emits the
+                             *   specified number of frames (otherwise the port does not
+                             *   terminate the capture until instructed to do so by the client).
+                             *   Even if set, the client may manually terminate the capture prior
                              *   to reaching the limit. */
     OMX_U32 nFrameLimit;      /**< Limit on number of frames emitted during a capture (only
                                *   valid if bFrameLimited is set). */
 } OMX_CONFIG_CAPTUREMODETYPE;
 
 typedef enum OMX_METERINGTYPE {
- 
+
     OMX_MeteringModeAverage,     /**< Center-weighted average metering. */
     OMX_MeteringModeSpot,  	      /**< Spot (partial) metering. */
     OMX_MeteringModeMatrix,      /**< Matrix or evaluative metering. */
- 
-    OMX_MeteringKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+
+    OMX_MeteringKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_MeteringVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_EVModeMax = 0x7fffffff
 } OMX_METERINGTYPE;
- 
+
 typedef struct OMX_CONFIG_EXPOSUREVALUETYPE {
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
@@ -843,14 +850,14 @@
     OMX_S32 xEVCompensation;      /**< Fixed point value stored as Q16 */
     OMX_U32 nApertureFNumber;     /**< e.g. nApertureFNumber = 2 implies "f/2" - Q16 format */
     OMX_BOOL bAutoAperture;		/**< Whether aperture number is defined automatically */
-    OMX_U32 nShutterSpeedMsec;    /**< Shutterspeed in milliseconds */ 
-    OMX_BOOL bAutoShutterSpeed;	/**< Whether shutter speed is defined automatically */ 
+    OMX_U32 nShutterSpeedMsec;    /**< Shutterspeed in milliseconds */
+    OMX_BOOL bAutoShutterSpeed;	/**< Whether shutter speed is defined automatically */
     OMX_U32 nSensitivity;         /**< e.g. nSensitivity = 100 implies "ISO 100" */
     OMX_BOOL bAutoSensitivity;	/**< Whether sensitivity is defined automatically */
 } OMX_CONFIG_EXPOSUREVALUETYPE;
 
-/** 
- * Focus region configuration 
+/**
+ * Focus region configuration
  *
  * STRUCT MEMBERS:
  *  nSize           : Size of the structure in bytes
@@ -881,8 +888,8 @@
     OMX_BOOL bBottomRight;
 } OMX_CONFIG_FOCUSREGIONTYPE;
 
-/** 
- * Focus Status type 
+/**
+ * Focus Status type
  */
 typedef enum OMX_FOCUSSTATUSTYPE {
     OMX_FocusStatusOff = 0,
@@ -890,13 +897,13 @@
     OMX_FocusStatusReached,
     OMX_FocusStatusUnableToReach,
     OMX_FocusStatusLost,
-    OMX_FocusStatusKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
+    OMX_FocusStatusKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_FocusStatusVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_FocusStatusMax = 0x7FFFFFFF
 } OMX_FOCUSSTATUSTYPE;
 
-/** 
- * Focus status configuration 
+/**
+ * Focus status configuration
  *
  * STRUCT MEMBERS:
  *  nSize               : Size of the structure in bytes
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 1dc6cd2..986fc7e 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -55,6 +55,9 @@
     mQueryWidth = 0;
     mQueryHeight = 0;
     mQueryFormat = 0;
+    mDefaultWidth = 0;
+    mDefaultHeight = 0;
+    mTransformHint = 0;
     mConnectedToCpu = false;
 }
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 8b1caeee..886c05c 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -883,7 +883,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 DisplayListRenderer::DisplayListRenderer(): mWriter(MIN_WRITER_SIZE) {
-    mDisplayList = NULL;
 }
 
 DisplayListRenderer::~DisplayListRenderer() {
@@ -923,13 +922,13 @@
 // Operations
 ///////////////////////////////////////////////////////////////////////////////
 
-DisplayList* DisplayListRenderer::getDisplayList() {
-    if (mDisplayList == NULL) {
-        mDisplayList = new DisplayList(*this);
+DisplayList* DisplayListRenderer::getDisplayList(DisplayList* displayList) {
+    if (!displayList) {
+        displayList = new DisplayList(*this);
     } else {
-        mDisplayList->initFromDisplayListRenderer(*this, true);
+        displayList->initFromDisplayListRenderer(*this, true);
     }
-    return mDisplayList;
+    return displayList;
 }
 
 void DisplayListRenderer::setViewport(int width, int height) {
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index b83259f..8157631 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -217,7 +217,7 @@
     DisplayListRenderer();
     ~DisplayListRenderer();
 
-    DisplayList* getDisplayList();
+    DisplayList* getDisplayList(DisplayList* displayList);
 
     void setViewport(int width, int height);
     void prepareDirty(float left, float top, float right, float bottom, bool opaque);
@@ -474,8 +474,6 @@
 
     SkWriter32 mWriter;
 
-    DisplayList *mDisplayList;
-
     int mRestoreSaveCount;
 
     friend class DisplayList;
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index 412552e..0e8ae61 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -310,35 +310,21 @@
         int operation, ...)
 {
     switch (operation) {
-        case NATIVE_WINDOW_SET_USAGE:
-            // TODO: we should implement this
-            return NO_ERROR;
         case NATIVE_WINDOW_CONNECT:
-            // TODO: we should implement this
-            return NO_ERROR;
         case NATIVE_WINDOW_DISCONNECT:
-            // TODO: we should implement this
-            return NO_ERROR;
-        case NATIVE_WINDOW_LOCK:
-            return INVALID_OPERATION;
-        case NATIVE_WINDOW_UNLOCK_AND_POST:
-            return INVALID_OPERATION;
-        case NATIVE_WINDOW_SET_CROP:
-            return INVALID_OPERATION;
-        case NATIVE_WINDOW_SET_BUFFER_COUNT:
-            // TODO: we should implement this
-            return INVALID_OPERATION;
+        case NATIVE_WINDOW_SET_USAGE:
         case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
-            return INVALID_OPERATION;
-        case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
-            return INVALID_OPERATION;
-        case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
-            return INVALID_OPERATION;
         case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
-            return INVALID_OPERATION;
         case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
-            // TODO: we should implement this
+        case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
+            // TODO: we should implement these
             return NO_ERROR;
+
+        case NATIVE_WINDOW_LOCK:
+        case NATIVE_WINDOW_UNLOCK_AND_POST:
+        case NATIVE_WINDOW_SET_CROP:
+        case NATIVE_WINDOW_SET_BUFFER_COUNT:
+        case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
         case NATIVE_WINDOW_SET_SCALING_MODE:
             return INVALID_OPERATION;
     }
diff --git a/packages/SystemUI/res/layout-sw600dp/compat_mode_help.xml b/packages/SystemUI/res/layout-sw600dp/compat_mode_help.xml
index d29e495..a354336 100644
--- a/packages/SystemUI/res/layout-sw600dp/compat_mode_help.xml
+++ b/packages/SystemUI/res/layout-sw600dp/compat_mode_help.xml
@@ -43,6 +43,7 @@
         android:layout_height="wrap_content"
         android:layout_centerInParent="true"
         android:src="@drawable/compat_mode_help_diagram"
+        android:contentDescription="@string/accessibility_compatibility_zoom_example"
         />
     <RelativeLayout
         android:orientation="horizontal"
@@ -61,6 +62,7 @@
             android:layout_alignParentRight="true"
             android:layout_centerVertical="true"
             android:src="@drawable/compat_mode_help_icon"
+            android:contentDescription="@string/accessibility_compatibility_zoom_button"
             />
         <TextView
             android:id="@+id/explanation"
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar.xml b/packages/SystemUI/res/layout-sw600dp/status_bar.xml
index d9f3f23..a2a6473 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar.xml
@@ -49,6 +49,7 @@
                 android:src="@drawable/ic_sysbar_back"
                 android:layout_alignParentLeft="true"
                 systemui:keyCode="4"
+                android:contentDescription="@string/accessibility_back"
                 />
             <LinearLayout
                 android:id="@+id/navigationArea"
@@ -62,11 +63,13 @@
                     android:layout_height="match_parent"
                     android:src="@drawable/ic_sysbar_home"
                     systemui:keyCode="3"
+                    android:contentDescription="@string/accessibility_home"
                     />
                 <ImageView android:id="@+id/recent_apps"
                     android:layout_width="80dip"
                     android:layout_height="match_parent"
                     android:src="@drawable/ic_sysbar_recent"
+                    android:contentDescription="@string/accessibility_menu"
                     />
                 <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
                     android:layout_width="80dip"
@@ -74,6 +77,7 @@
                     android:src="@drawable/ic_sysbar_menu"
                     systemui:keyCode="82"
                     android:visibility="invisible"
+                    android:contentDescription="@string/accessibility_menu"
                     />
             </LinearLayout>
 
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_item.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_item.xml
index 3fef7e0..41a20fb 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_item.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_item.xml
@@ -53,7 +53,8 @@
                 android:id="@+id/item_icon"
                 android:layout_width="@android:dimen/app_icon_size"
                 android:layout_height="wrap_content"
-                android:scaleType="fitCenter" />
+                android:scaleType="fitCenter"
+                android:contentDescription="@null" />
             <LinearLayout
                 android:orientation="vertical"
                 android:layout_width="0px"
@@ -94,7 +95,8 @@
             android:visibility="visible"
             android:clickable="true"
             android:focusable="true"
-            android:background="?android:attr/selectableItemBackground" />
+            android:background="?android:attr/selectableItemBackground"
+            android:contentDescription="@string/accessibility_settings_button" />
     </LinearLayout>
     <View
         android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml
index fecfe7f..1e3099dc 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml
@@ -16,7 +16,7 @@
 -->
 
 <!-- notification icons & panel access -->
-<LinearLayout
+<com.android.systemui.statusbar.tablet.NotificationArea
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:id="@+id/notificationArea"
@@ -40,6 +40,7 @@
             android:layout_marginLeft="8dip"
             android:src="@drawable/ic_sysbar_ime_default"
             android:visibility="gone"
+            android:contentDescription="@string/accessibility_ime_switch_button"
             />
 
         <com.android.systemui.statusbar.policy.CompatModeButton
@@ -49,6 +50,7 @@
             android:layout_marginLeft="8dip"
             android:src="@drawable/ic_sysbar_zoom"
             android:visibility="gone"
+            android:contentDescription="@string/accessibility_compatibility_zoom_button"
             />
 
         <com.android.systemui.statusbar.tablet.NotificationIconArea
@@ -152,4 +154,4 @@
                 />
         </LinearLayout>
     </LinearLayout>
-</LinearLayout>
+</com.android.systemui.statusbar.tablet.NotificationArea>
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml
index 543f4ed..bbb2bc6 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel_title.xml
@@ -14,15 +14,17 @@
   limitations under the License.
 -->
 
-<RelativeLayout
+<com.android.systemui.statusbar.tablet.NotificationPanelTitle
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:id="@+id/title_area"
-    android:layout_width="0dp"
-    android:layout_height="0dp"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:clickable="true"
     android:orientation="vertical"
     android:background="@drawable/notify_panel_clock_bg"
     >
+
     <LinearLayout
         android:id="@+id/icons"
         android:layout_width="wrap_content"
@@ -34,6 +36,7 @@
         android:layout_marginTop="16dp"
         android:layout_marginBottom="16dp"
         >
+
         <ImageView
             android:id="@+id/bluetooth"
             android:layout_height="32dp"
@@ -41,6 +44,7 @@
             android:scaleType="centerInside"
             android:baseline="22dp"
             android:visibility="gone"
+            android:contentDescription="@null"
             />
 
         <FrameLayout
@@ -49,21 +53,28 @@
             android:layout_width="32dp"
             android:layout_marginRight="4dp"
             >
+
             <ImageView
                 android:id="@+id/network_signal"
                 android:layout_height="match_parent"
                 android:layout_width="match_parent"
+                android:contentDescription="@null"
                 />
+
             <ImageView
                 android:id="@+id/network_type"
                 android:layout_height="match_parent"
                 android:layout_width="match_parent"
+                android:contentDescription="@null"
                 />
+
             <ImageView
                 android:id="@+id/network_direction"
                 android:layout_height="match_parent"
                 android:layout_width="match_parent"
+                android:contentDescription="@null"
                 />
+
         </FrameLayout>
             
         <TextView
@@ -86,6 +97,7 @@
             android:layout_toRightOf="@id/network_text"
             android:layout_alignBaseline="@id/network_signal"
             android:baseline="22dp"
+            android:contentDescription="@null"
             />
 
         <TextView
@@ -110,6 +122,7 @@
         android:paddingRight="16dp"
         android:src="@drawable/ic_sysbar_quicksettings"
         android:baseline="21dp"
+        android:contentDescription="@string/accessibility_settings_button"
         />
 
     <ImageView
@@ -122,6 +135,7 @@
         android:src="@drawable/ic_notification_open"
         android:baseline="21dp"
         android:visibility="invisible"
+        android:contentDescription="@string/accessibility_notifications_button"
         />
 
     <View
@@ -138,7 +152,7 @@
     <com.android.systemui.statusbar.tablet.HoloClock
         android:id="@+id/clock"
         android:layout_height="wrap_content"
-        android:layout_width="match_parent"
+        android:layout_width="wrap_content"
         android:layout_alignParentRight="true"
         android:layout_above="@id/title_divider"
         android:layout_marginRight="6dip"
@@ -164,19 +178,11 @@
         android:id="@+id/date"
         style="@style/StatusBarNotificationText"
         android:layout_height="wrap_content"
-        android:layout_width="120dp"
+        android:layout_width="wrap_content"
         android:layout_alignBottom="@id/clock"
         android:layout_alignParentLeft="true"
         android:gravity="left"
         android:layout_marginLeft="32dp"
         />
 
-    <view
-        class="com.android.systemui.statusbar.tablet.NotificationPanel$ModeToggle"
-        android:id="@+id/mode_toggle"
-        android:background="@null"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:clickable="true"
-        />
-</RelativeLayout>
+</com.android.systemui.statusbar.tablet.NotificationPanelTitle>
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index 51e7d97..5d7e8de 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -54,6 +54,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_weight="1"
+                android:contentDescription="@string/accessibility_back"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
                 android:layout_width="80dp"
@@ -66,6 +67,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_weight="1"
+                android:contentDescription="@string/accessibility_home"
                 />
             <ImageView android:id="@+id/recent_apps"
                 android:layout_width="80dp"
@@ -80,6 +82,7 @@
                 systemui:keyCode="82"
                 android:layout_weight="0"
                 android:visibility="invisible"
+                android:contentDescription="@string/accessibility_menu"
                 />
         </LinearLayout>
 
@@ -124,6 +127,7 @@
                 android:layout_height="match_parent"
                 android:layout_width="match_parent"
                 android:layout_weight="1"
+                android:contentDescription="@string/accessibility_menu"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
                 android:layout_height="80dp"
@@ -131,11 +135,13 @@
                 android:src="@drawable/ic_sysbar_home_default_land"
                 systemui:keyCode="3"
                 android:layout_weight="0"
+                android:contentDescription="@string/accessibility_home"
                 />
             <View 
                 android:layout_height="match_parent"
                 android:layout_width="match_parent"
                 android:layout_weight="1"
+                android:contentDescription="@string/accessibility_back"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
                 android:layout_height="80dp"
@@ -148,6 +154,7 @@
                 android:layout_height="40dp"
                 android:layout_width="match_parent"
                 android:layout_weight="0"
+                android:contentDescription="@string/accessibility_menu"
                 />
         </LinearLayout>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 01cf2dc..082dab3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -169,4 +169,135 @@
     <string name="screenshot_saving_toast">Screenshot saved to Gallery</string>
     <!-- toast message displayed when we fail to take a screenshot. -->
     <string name="screenshot_failed_toast">Could not save screenshot</string>
+
+    <!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] -->
+    <string name="usb_preference_title">USB file transfer options</string>
+    <!-- Label for the MTP USB function in UsbPreferenceActivity. [CHAR LIMIT=50] -->
+    <string name="use_mtp_button_title">Mount as a media player (MTP)</string>
+    <!-- Label for the PTP USB function in UsbPreferenceActivity. [CHAR LIMIT=50] -->
+    <string name="use_ptp_button_title">Mount as a camera (PTP)</string>
+    <!-- Label for the installer CD image option in UsbPreferenceActivity. [CHAR LIMIT=50] -->
+    <string name="installer_cd_button_title">Install Android File Transfer application for Mac</string>
+
+    <!-- Content description of the back button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_back">Back</string>
+    <!-- Content description of the home button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_home">Home</string>
+    <!-- Content description of the menu button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_menu">Menu</string>
+
+    <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_ime_switch_button">Switch input method button.</string>
+    <!-- Content description of the compatibility zoom button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_compatibility_zoom_button">Compatibility zoom button.</string>
+
+    <!-- Content description of picture of the compatibility zoom example for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_compatibility_zoom_example">Zoom smaller to larger screen.</string>
+
+    <!-- Content description of the bluetooth icon when connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_bluetooth_connected">Bluetooth connected.</string>
+    <!-- Content description of the bluetooth icon when connecting for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_bluetooth_disconnected">Bluetooth disconnected.</string>
+
+    <!-- Content description of the battery when no battery for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_no_battery">No battery.</string>
+    <!-- Content description of the battery when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_battery_one_bar">Battery one bar.</string>
+    <!-- Content description of the battery when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_battery_two_bars">Battery two bars.</string>
+     <!-- Content description of the battery when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_battery_three_bars">Battery three bars.</string>
+    <!-- Content description of the battery when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_battery_full">Battery full.</string>
+
+    <!-- Content description of the phone signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_no_phone">No phone.</string>
+    <!-- Content description of the phone signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_phone_one_bar">Phone one bar.</string>
+    <!-- Content description of the phone signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_phone_two_bars">Phone two bars.</string>
+    <!-- Content description of the phone signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_phone_three_bars">Phone three bars.</string>
+    <!-- Content description of the phone signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_phone_signal_full">Phone signal full.</string>
+
+    <!-- Content description of the data signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_no_data">No data.</string>
+    <!-- Content description of the data signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_one_bar">Data one bar.</string>
+    <!-- Content description of the data signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_two_bars">Data two bars.</string>
+    <!-- Content description of the data signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_three_bars">Data three bars.</string>
+    <!-- Content description of the data signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_signal_full">Data signal full.</string>
+
+    <!-- Content description of the WIFI signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_no_wifi">No WiFi.</string>
+    <!-- Content description of the WIFI signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_wifi_one_bar">WiFi one bar.</string>
+    <!-- Content description of the WIFI signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_wifi_two_bars">WiFi two bars.</string>
+    <!-- Content description of the WIFI signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_wifi_three_bars">WiFi three bars.</string>
+    <!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_wifi_signal_full">WiFi signal full.</string>
+
+    <!-- Content description of the data connection type GPRS for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_gprs">GPRS</string>
+
+    <!-- Content description of the data connection type 3G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_3g">3G</string>
+
+    <!-- Content description of the data connection type 3.5G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_3.5g">3.5G</string>
+
+    <!-- Content description of the data connection type 4G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_4g">4G</string>
+
+    <!-- Content description of the data connection type CDMA for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_cdma">CDMA</string>
+
+    <!-- Content description of the data connection type Edge for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_edge">Edge</string>
+
+    <!-- Content description of the data connection type WiFi for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_wifi">WiFi</string>
+
+    <!-- Content description of the data connection with no SIM for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_no_sim">No SIM.</string>
+
+    <!-- Content description of the bluetooth tethering icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_bluetooth_tether">Bluetooth tethering.</string>
+
+    <!-- Content description of the airplane mode icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_airplane_mode">Airplane mode.</string>
+
+    <!-- Content description of the battery level icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_battery_level">Battery <xliff:g id="number">%d</xliff:g> percent.</string>
+
+    <!-- Content description of the button for showing a settings panel in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_settings_button">Settings button.</string>
+
+    <!-- Content description of the button for showing a notifications panel in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_notifications_button">Notifications button.</string>
+
+    <!-- Content description of the button for removing a notification in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_remove_notification">Remove notification.</string>
+
+    <!-- Content description of the enabled GPS icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_gps_enabled">GPS enabled.</string>
+
+    <!-- Content description of the acquiring GPS icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_gps_acquiring">GPS acquiring.</string>
+
+    <!-- Content description of the TeleTypewriter(TTY) enabled icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_tty_enabled">TeleTypewriter enabled.</string>
+
+    <!-- Content description of the ringer vibrate icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_ringer_vibrate">Ringer vibrate.</string>
+
+    <!-- Content description of the ringer silent icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_ringer_silent">Ringer silent.</string>
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index bc0a508..ea54445 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -22,7 +22,6 @@
 import android.animation.Animator;
 import android.animation.LayoutTransition;
 import android.app.ActivityManager;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -48,6 +47,7 @@
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
@@ -112,7 +112,7 @@
             position = _pos;
             packageName = _packageName;
         }
-    };
+    }
 
     private final class OnLongClickDelegate implements View.OnLongClickListener {
         View mOtherView;
@@ -252,6 +252,19 @@
         mChoreo.setPanelHeight(mRecentsContainer.getHeight());
     }
 
+    @Override
+    public boolean dispatchHoverEvent(MotionEvent event) {
+        // Ignore hover events outside of this panel bounds since such events
+        // generate spurious accessibility events with the panel content when
+        // tapping outside of it, thus confusing the user.
+        final int x = (int) event.getX();
+        final int y = (int) event.getY();
+        if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
+            return super.dispatchHoverEvent(event);
+        }
+        return true;
+    }
+
     /**
      * Whether the panel is showing, or, if it's animating, whether it will be
      * when the animation is done.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
index 64ec063..6419777 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
@@ -18,8 +18,8 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
-import android.util.Slog;
-import android.view.MotionEvent;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.FrameLayout;
 
 public class LatestItemView extends FrameLayout {
@@ -27,7 +27,22 @@
         super(context, attrs);
     }
 
+    @Override
     public void setOnClickListener(OnClickListener l) {
         super.setOnClickListener(l);
     }
+
+    @Override
+    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+        if (super.onRequestSendAccessibilityEvent(child, event)) {
+            // Add a record for the entire layout since its content is somehow small.
+            // The event comes from a leaf view that is interacted with.
+            AccessibilityEvent record = AccessibilityEvent.obtain();
+            onInitializeAccessibilityEvent(record);
+            dispatchPopulateAccessibilityEvent(record);
+            event.appendRecord(record);
+            return true;
+        }
+        return false;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index d9d9c06..be4b395 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar;
 
+import android.app.Notification;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
@@ -23,11 +24,11 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.text.TextUtils;
 import android.util.Slog;
 import android.util.Log;
-import android.view.View;
 import android.view.ViewDebug;
-import android.widget.FrameLayout;
+import android.view.accessibility.AccessibilityEvent;
 
 import java.text.NumberFormat;
 
@@ -45,8 +46,9 @@
     private int mNumberX;
     private int mNumberY;
     private String mNumberText;
+    private Notification mNotification;
 
-    public StatusBarIconView(Context context, String slot) {
+    public StatusBarIconView(Context context, String slot, Notification notification) {
         super(context);
         final Resources res = context.getResources();
         mSlot = slot;
@@ -54,6 +56,8 @@
         mNumberPain.setTextAlign(Paint.Align.CENTER);
         mNumberPain.setColor(res.getColor(R.drawable.notification_number_text_color));
         mNumberPain.setAntiAlias(true);
+        mNotification = notification;
+        setContentDescription(notification);
     }
 
     private static boolean streq(String a, String b) {
@@ -83,6 +87,7 @@
         final boolean numberEquals = mIcon != null
                 && mIcon.number == icon.number;
         mIcon = icon.clone();
+        setContentDescription(icon.contentDescription);
         if (!iconEquals) {
             Drawable drawable = getIcon(icon);
             if (drawable == null) {
@@ -159,6 +164,15 @@
         return mIcon;
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        if (mNotification != null) {
+            event.setParcelableData(mNotification);
+        }
+    }
+
+    @Override
     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
         super.onSizeChanged(w, h, oldw, oldh);
         if (mNumberBackground != null) {
@@ -166,6 +180,7 @@
         }
     }
 
+    @Override
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
 
@@ -175,6 +190,7 @@
         }
     }
 
+    @Override
     protected void debug(int depth) {
         super.debug(depth);
         Log.d("View", debugIndent(depth) + "slot=" + mSlot);
@@ -213,4 +229,13 @@
         mNumberY = h-r.bottom-((dh-r.top-th-r.bottom)/2);
         mNumberBackground.setBounds(w-dw, h-dh, w, h);
     }
+
+    private void setContentDescription(Notification notification) {
+        if (notification != null) {
+            CharSequence tickerText = notification.tickerText;
+            if (!TextUtils.isEmpty(tickerText)) {
+                setContentDescription(tickerText);
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
index e1d17a8..f6aa159 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
@@ -33,7 +33,8 @@
 
     private int mIconSize;
     private StatusBarIconView mMoreView;
-    private StatusBarIcon mMoreIcon = new StatusBarIcon(null, R.drawable.stat_notify_more, 0);
+    private StatusBarIcon mMoreIcon = new StatusBarIcon(null, R.drawable.stat_notify_more, 0, 0,
+            null);
 
     public IconMerger(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -41,7 +42,7 @@
         mIconSize = context.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_icon_size);
 
-        mMoreView = new StatusBarIconView(context, "more");
+        mMoreView = new StatusBarIconView(context, "more", null);
         mMoreView.set(mMoreIcon);
         addView(mMoreView, 0, new LinearLayout.LayoutParams(mIconSize, mIconSize));
     }
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 f4c4bbc..b93ad68 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -472,7 +472,7 @@
     public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
         if (SPEW) Slog.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
                 + " icon=" + icon);
-        StatusBarIconView view = new StatusBarIconView(mContext, slot);
+        StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
         view.set(icon);
         mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize));
     }
@@ -607,7 +607,7 @@
                 // Update the icon.
                 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
                         notification.notification.icon, notification.notification.iconLevel,
-                        notification.notification.number);
+                        notification.notification.number, notification.notification.tickerText);
                 if (!oldEntry.icon.set(ic)) {
                     handleNotificationError(key, notification, "Couldn't update icon: " + ic);
                     return;
@@ -765,9 +765,11 @@
         final View expanded = views[2];
         // Construct the icon.
         final StatusBarIconView iconView = new StatusBarIconView(mContext,
-                notification.pkg + "/0x" + Integer.toHexString(notification.id));
+                notification.pkg + "/0x" + Integer.toHexString(notification.id),
+                notification.notification);
         final StatusBarIcon ic = new StatusBarIcon(notification.pkg, notification.notification.icon,
-                    notification.notification.iconLevel, notification.notification.number);
+                    notification.notification.iconLevel, notification.notification.number,
+                    notification.notification.tickerText);
         if (!iconView.set(ic)) {
             handleNotificationError(key, notification, "Coulding create icon: " + ic);
             return null;
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 af5c72d..7b50985 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -18,25 +18,17 @@
 
 import android.app.StatusBarManager;
 import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothPbap;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.res.TypedArray;
-import android.graphics.PixelFormat;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
 import android.location.LocationManager;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
-import android.net.Uri;
 import android.net.wifi.WifiManager;
 import android.os.Binder;
 import android.os.Handler;
-import android.os.Message;
 import android.os.RemoteException;
 import android.os.storage.StorageManager;
 import android.provider.Settings;
@@ -44,18 +36,7 @@
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
-import android.text.format.DateFormat;
-import android.text.style.CharacterStyle;
-import android.text.style.RelativeSizeSpan;
-import android.text.style.ForegroundColorSpan;
-import android.text.style.StyleSpan;
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
 import android.util.Slog;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
 
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.telephony.IccCard;
@@ -63,7 +44,6 @@
 import com.android.internal.telephony.cdma.EriInfo;
 import com.android.internal.telephony.cdma.TtyIntent;
 import com.android.server.am.BatteryStatsService;
-
 import com.android.systemui.R;
 
 /**
@@ -447,6 +427,32 @@
               R.drawable.stat_sys_data_fully_inandout_1x }
             };
 
+    // Accessibility;
+
+    private static final int[] sPhoneSignalStrength = {
+        R.string.accessibility_no_phone,
+        R.string.accessibility_phone_one_bar,
+        R.string.accessibility_phone_two_bars,
+        R.string.accessibility_phone_three_bars,
+        R.string.accessibility_phone_signal_full
+    };
+
+    private static final int[] sDataConnectionStrength = {
+        R.string.accessibility_no_data,
+        R.string.accessibility_data_one_bar,
+        R.string.accessibility_data_two_bars,
+        R.string.accessibility_data_three_bars,
+        R.string.accessibility_data_signal_full
+    };
+
+    private static final int[] sWifiConnectionStrength = {
+        R.string.accessibility_no_wifi,
+        R.string.accessibility_wifi_one_bar,
+        R.string.accessibility_wifi_two_bars,
+        R.string.accessibility_wifi_three_bars,
+        R.string.accessibility_wifi_signal_full
+    };
+
     // Assume it's all good unless we hear otherwise.  We don't always seem
     // to get broadcasts that it *is* there.
     IccCard.State mSimState = IccCard.State.READY;
@@ -546,12 +552,13 @@
                 new com.android.systemui.usb.StorageNotification(context));
 
         // battery
-        mService.setIcon("battery", com.android.internal.R.drawable.stat_sys_battery_unknown, 0);
+        mService.setIcon("battery", com.android.internal.R.drawable.stat_sys_battery_unknown, 0,
+                null);
 
         // phone_signal
         mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
         mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
-        mService.setIcon("phone_signal", mPhoneSignalIconId, 0);
+        mService.setIcon("phone_signal", mPhoneSignalIconId, 0, null);
 
         // register for phone state notifications.
         ((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
@@ -563,24 +570,24 @@
                         | PhoneStateListener.LISTEN_DATA_ACTIVITY);
 
         // data_connection
-        mService.setIcon("data_connection", R.drawable.stat_sys_data_connected_g, 0);
+        mService.setIcon("data_connection", R.drawable.stat_sys_data_connected_g, 0, null);
         mService.setIconVisibility("data_connection", false);
 
         // wifi
-        mService.setIcon("wifi", sWifiSignalImages[0][0], 0);
+        mService.setIcon("wifi", sWifiSignalImages[0][0], 0, null);
         mService.setIconVisibility("wifi", false);
         // wifi will get updated by the sticky intents
 
         // TTY status
-        mService.setIcon("tty",  R.drawable.stat_sys_tty_mode, 0);
+        mService.setIcon("tty",  R.drawable.stat_sys_tty_mode, 0, null);
         mService.setIconVisibility("tty", false);
 
         // Cdma Roaming Indicator, ERI
-        mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_0, 0);
+        mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_0, 0, null);
         mService.setIconVisibility("cdma_eri", false);
 
         // bluetooth status
-        mService.setIcon("bluetooth", R.drawable.stat_sys_data_bluetooth, 0);
+        mService.setIcon("bluetooth", R.drawable.stat_sys_data_bluetooth, 0, null);
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
         if (adapter != null) {
             mBluetoothEnabled = adapter.isEnabled();
@@ -590,21 +597,23 @@
         mService.setIconVisibility("bluetooth", mBluetoothEnabled);
 
         // Gps status
-        mService.setIcon("gps", R.drawable.stat_sys_gps_acquiring_anim, 0);
+        mService.setIcon("gps", R.drawable.stat_sys_gps_acquiring_anim, 0, null);
         mService.setIconVisibility("gps", false);
 
         // Alarm clock
-        mService.setIcon("alarm_clock", R.drawable.stat_notify_alarm, 0);
+        mService.setIcon("alarm_clock", R.drawable.stat_notify_alarm, 0, null);
         mService.setIconVisibility("alarm_clock", false);
 
         // Sync state
-        mService.setIcon("sync_active", com.android.internal.R.drawable.stat_notify_sync_anim0, 0);
-        mService.setIcon("sync_failing", com.android.internal.R.drawable.stat_notify_sync_error, 0);
+        mService.setIcon("sync_active", com.android.internal.R.drawable.stat_notify_sync_anim0,
+                0, null);
+        mService.setIcon("sync_failing", com.android.internal.R.drawable.stat_notify_sync_error,
+                0, null);
         mService.setIconVisibility("sync_active", false);
         mService.setIconVisibility("sync_failing", false);
 
         // volume
-        mService.setIcon("volume", R.drawable.stat_sys_ringer_silent, 0);
+        mService.setIcon("volume", R.drawable.stat_sys_ringer_silent, 0, null);
         mService.setIconVisibility("volume", false);
         updateVolume();
 
@@ -655,7 +664,8 @@
     private final void updateBattery(Intent intent) {
         final int id = intent.getIntExtra("icon-small", 0);
         int level = intent.getIntExtra("level", 0);
-        mService.setIcon("battery", id, level);
+        String contentDescription = mContext.getString(R.string.accessibility_battery_level, level);
+        mService.setIcon("battery", id, level, contentDescription);
     }
 
     private void updateConnectivity(Intent intent) {
@@ -677,12 +687,16 @@
             if (info.isConnected()) {
                 mIsWifiConnected = true;
                 int iconId;
+                String contentDescription = null;
                 if (mLastWifiSignalLevel == -1) {
                     iconId = sWifiSignalImages[mInetCondition][0];
+                    contentDescription = mContext.getString(sWifiConnectionStrength[0]);
                 } else {
                     iconId = sWifiSignalImages[mInetCondition][mLastWifiSignalLevel];
-                }
-                mService.setIcon("wifi", iconId, 0);
+                    contentDescription = mContext.getString(
+                            sWifiConnectionStrength[mLastWifiSignalLevel]);
+                } 
+                mService.setIcon("wifi", iconId, 0, contentDescription);
                 // Show the icon since wi-fi is connected
                 mService.setIconVisibility("wifi", true);
             } else {
@@ -690,7 +704,8 @@
                 mIsWifiConnected = false;
                 int iconId = sWifiSignalImages[0][0];
 
-                mService.setIcon("wifi", iconId, 0);
+                String contentDescription = mContext.getString(R.string.accessibility_no_wifi);
+                mService.setIcon("wifi", iconId, 0, contentDescription);
                 // Hide the icon since we're not connected
                 mService.setIconVisibility("wifi", false);
             }
@@ -781,6 +796,7 @@
 
     private final void updateSignalStrength() {
         int[] iconList;
+        String contentDescription = null;
 
         // Display signal strength while in "emergency calls only" mode
         if (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly())) {
@@ -788,10 +804,12 @@
             if (Settings.System.getInt(mContext.getContentResolver(),
                     Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
                 mPhoneSignalIconId = R.drawable.stat_sys_signal_flightmode;
+                contentDescription = mContext.getString(R.string.accessibility_airplane_mode);
             } else {
                 mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
+                contentDescription = mContext.getString(R.string.accessibility_no_phone);
             }
-            mService.setIcon("phone_signal", mPhoneSignalIconId, 0);
+            mService.setIcon("phone_signal", mPhoneSignalIconId, 0, contentDescription);
             return;
         }
 
@@ -805,8 +823,11 @@
         } else {
             iconList = sSignalImages[mInetCondition];
         }
-        mPhoneSignalIconId = iconList[mSignalStrength.getLevel()];
-        mService.setIcon("phone_signal", mPhoneSignalIconId, 0);
+
+        final int signalLevel = mSignalStrength.getLevel();
+        mPhoneSignalIconId = iconList[signalLevel];
+        contentDescription = mContext.getString(sPhoneSignalStrength[signalLevel]);
+        mService.setIcon("phone_signal", mPhoneSignalIconId, 0, contentDescription);
     }
 
     private final void updateDataNetType(int net) {
@@ -850,6 +871,7 @@
 
     private final void updateDataIcon() {
         int iconId;
+        String contentDescription = null;
         boolean visible = true;
 
         if (!isCdma()) {
@@ -870,13 +892,15 @@
                             iconId = mDataIconList[0];
                             break;
                     }
-                    mService.setIcon("data_connection", iconId, 0);
+                    contentDescription = mContext.getString(sDataConnectionStrength[mDataActivity]);
+                    mService.setIcon("data_connection", iconId, 0, contentDescription);
                 } else {
                     visible = false;
                 }
             } else {
                 iconId = R.drawable.stat_sys_no_sim;
-                mService.setIcon("data_connection", iconId, 0);
+                contentDescription = mContext.getString(R.string.accessibility_no_sim);
+                mService.setIcon("data_connection", iconId, 0, contentDescription);
             }
         } else {
             // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
@@ -896,7 +920,7 @@
                         iconId = mDataIconList[0];
                         break;
                 }
-                mService.setIcon("data_connection", iconId, 0);
+                mService.setIcon("data_connection", iconId, 0, null);
             } else {
                 visible = false;
             }
@@ -921,12 +945,19 @@
         final int ringerMode = audioManager.getRingerMode();
         final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
                 ringerMode == AudioManager.RINGER_MODE_VIBRATE;
-        final int iconId = audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)
-                ? R.drawable.stat_sys_ringer_vibrate
-                : R.drawable.stat_sys_ringer_silent;
+
+        final int iconId;
+        String contentDescription = null;
+        if (audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)) {
+            iconId = R.drawable.stat_sys_ringer_vibrate;
+            contentDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
+        } else {
+            iconId =  R.drawable.stat_sys_ringer_silent;
+            contentDescription = mContext.getString(R.string.accessibility_ringer_silent);
+        }
 
         if (visible) {
-            mService.setIcon("volume", iconId, 0);
+            mService.setIcon("volume", iconId, 0, contentDescription);
         }
         if (visible != mVolumeVisible) {
             mService.setIconVisibility("volume", visible);
@@ -936,6 +967,7 @@
 
     private final void updateBluetooth(Intent intent) {
         int iconId = R.drawable.stat_sys_data_bluetooth;
+        String contentDescription = null;
         String action = intent.getAction();
         if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
             int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
@@ -945,12 +977,16 @@
                 BluetoothAdapter.STATE_DISCONNECTED);
             if (state == BluetoothAdapter.STATE_CONNECTED) {
                 iconId = R.drawable.stat_sys_data_bluetooth_connected;
+                contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
+            } else {
+                contentDescription = mContext.getString(
+                        R.string.accessibility_bluetooth_disconnected);
             }
         } else {
             return;
         }
 
-        mService.setIcon("bluetooth", iconId, 0);
+        mService.setIcon("bluetooth", iconId, 0, contentDescription);
         mService.setIconVisibility("bluetooth", mBluetoothEnabled);
     }
 
@@ -974,6 +1010,7 @@
             }
         } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
             int iconId;
+            String contentDescription = null;
             final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
             int newSignalLevel = WifiManager.calculateSignalLevel(newRssi,
                                                                   sWifiSignalImages[0].length);
@@ -981,10 +1018,13 @@
                 mLastWifiSignalLevel = newSignalLevel;
                 if (mIsWifiConnected) {
                     iconId = sWifiSignalImages[mInetCondition][newSignalLevel];
+                    contentDescription = mContext.getString(
+                            sWifiConnectionStrength[newSignalLevel]);
                 } else {
                     iconId = sWifiTemporarilyNotConnectedImage;
+                    contentDescription = mContext.getString(R.string.accessibility_no_wifi);
                 }
-                mService.setIcon("wifi", iconId, 0);
+                mService.setIcon("wifi", iconId, 0, contentDescription);
             }
         }
     }
@@ -995,14 +1035,16 @@
 
         if (action.equals(LocationManager.GPS_FIX_CHANGE_ACTION) && enabled) {
             // GPS is getting fixes
-            mService.setIcon("gps", com.android.internal.R.drawable.stat_sys_gps_on, 0);
+            mService.setIcon("gps", com.android.internal.R.drawable.stat_sys_gps_on, 0,
+                    mContext.getString(R.string.accessibility_gps_enabled));
             mService.setIconVisibility("gps", true);
         } else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) && !enabled) {
             // GPS is off
             mService.setIconVisibility("gps", false);
         } else {
             // GPS is on, but not receiving fixes
-            mService.setIcon("gps", R.drawable.stat_sys_gps_acquiring_anim, 0);
+            mService.setIcon("gps", R.drawable.stat_sys_gps_acquiring_anim, 0,
+                    mContext.getString(R.string.accessibility_gps_acquiring));
             mService.setIconVisibility("gps", true);
         }
     }
@@ -1016,7 +1058,8 @@
         if (enabled) {
             // TTY is on
             if (false) Slog.v(TAG, "updateTTY: set TTY on");
-            mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0);
+            mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0,
+                    mContext.getString(R.string.accessibility_tty_enabled));
             mService.setIconVisibility("tty", true);
         } else {
             // TTY is off
@@ -1058,15 +1101,15 @@
 
         switch (iconMode) {
             case EriInfo.ROAMING_ICON_MODE_NORMAL:
-                mService.setIcon("cdma_eri", iconList[iconIndex], 0);
+                mService.setIcon("cdma_eri", iconList[iconIndex], 0, null);
                 mService.setIconVisibility("cdma_eri", true);
                 break;
             case EriInfo.ROAMING_ICON_MODE_FLASH:
-                mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_flash, 0);
+                mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_flash, 0, null);
                 mService.setIconVisibility("cdma_eri", true);
                 break;
 
         }
-        mService.setIcon("phone_signal", mPhoneSignalIconId, 0);
+        mService.setIcon("phone_signal", mPhoneSignalIconId, 0, null);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 84c524a..c2390e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -26,6 +26,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.FrameLayout;
 
 import com.android.systemui.R;
@@ -203,5 +204,19 @@
         return mService.interceptTouchEvent(event)
                 ? true : super.onInterceptTouchEvent(event);
     }
-}
 
+    @Override
+    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+        if (super.onRequestSendAccessibilityEvent(child, event)) {
+            // The status bar is very small so augment the view that the user is touching
+            // with the content of the status bar a whole. This way an accessibility service
+            // may announce the current item as well as the entire content if appropriate.
+            AccessibilityEvent record = AccessibilityEvent.obtain();
+            onInitializeAccessibilityEvent(record);
+            dispatchPopulateAccessibilityEvent(record);
+            event.appendRecord(record);
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
index 8ee12de..e76fe51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
@@ -183,7 +183,8 @@
         }
 
         final Drawable icon = StatusBarIconView.getIcon(mContext,
-                new StatusBarIcon(n.pkg, n.notification.icon, n.notification.iconLevel, 0));
+                new StatusBarIcon(n.pkg, n.notification.icon, n.notification.iconLevel, 0,
+                        n.notification.tickerText));
         final Segment newSegment = new Segment(n, icon, n.notification.tickerText);
 
         // If there's already a notification schedule for this package and id, remove it.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
new file mode 100644
index 0000000..13fb03e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
@@ -0,0 +1,37 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+package com.android.systemui.statusbar.policy;
+
+import com.android.systemui.R;
+
+/**
+ * Content descriptions for accessibility support.
+ */
+public class AccessibilityContentDescriptions {
+
+    private AccessibilityContentDescriptions() {}
+    
+    static final int[] PHONE_SIGNAL_STRENGTH = {
+        R.string.accessibility_no_phone,
+        R.string.accessibility_phone_one_bar,
+        R.string.accessibility_phone_two_bars,
+        R.string.accessibility_phone_three_bars,
+        R.string.accessibility_phone_signal_full
+    };
+
+    static final int[] DATA_CONNECTION_STRENGTH = {
+        R.string.accessibility_no_data,
+        R.string.accessibility_data_one_bar,
+        R.string.accessibility_data_two_bars,
+        R.string.accessibility_data_three_bars,
+        R.string.accessibility_data_signal_full
+    };
+
+    static final int[] WIFI_CONNECTION_STRENGTH = {
+        R.string.accessibility_no_wifi,
+        R.string.accessibility_wifi_one_bar,
+        R.string.accessibility_wifi_two_bars,
+        R.string.accessibility_wifi_three_bars,
+        R.string.accessibility_wifi_signal_full
+    };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index ae2b6b2..3957c1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -62,12 +62,15 @@
                 ImageView v = mIconViews.get(i);
                 v.setImageResource(icon);
                 v.setImageLevel(level);
+                v.setContentDescription(mContext.getString(R.string.accessibility_battery_level,
+                        level));
             }
             N = mLabelViews.size();
             for (int i=0; i<N; i++) {
                 //final boolean plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
                 TextView v = mLabelViews.get(i);
-                v.setText(mContext.getString(R.string.status_bar_settings_battery_meter_format, level));
+                v.setText(mContext.getString(R.string.status_bar_settings_battery_meter_format,
+                        level));
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
index 0525054..c6f416f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
@@ -19,12 +19,10 @@
 import java.util.ArrayList;
 
 import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.util.Slog;
 import android.view.View;
 import android.widget.ImageView;
 
@@ -54,26 +52,24 @@
 
     @Override
     public void onReceive(Context context, Intent intent) {
-        String action = intent.getAction();
-        if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
-            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
-            mEnabled = state == BluetoothAdapter.STATE_ON;
-        } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
-            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
+        int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
                 BluetoothAdapter.STATE_DISCONNECTED);
-            if (state == BluetoothAdapter.STATE_CONNECTED) {
-                mIconId = R.drawable.stat_sys_data_bluetooth_connected;
-            } else {
-                mIconId = R.drawable.stat_sys_data_bluetooth;
-            }
-        }
+        int contentDescriptionResId = 0;
 
+        if (state == BluetoothAdapter.STATE_CONNECTED) {
+            mIconId = R.drawable.stat_sys_data_bluetooth_connected;
+            contentDescriptionResId = R.string.accessibility_bluetooth_connected;
+        } else {
+            mIconId = R.drawable.stat_sys_data_bluetooth;
+            contentDescriptionResId = R.string.accessibility_bluetooth_disconnected;
+        }
 
         int N = mIconViews.size();
         for (int i=0; i<N; i++) {
             ImageView v = mIconViews.get(i);
             v.setImageResource(mIconId);
             v.setVisibility(mEnabled ? View.VISIBLE : View.GONE);
+            v.setContentDescription(mContext.getString(contentDescriptionResId));
         }
     }
 }
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 3175a99..829855b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -28,14 +28,11 @@
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
-import android.net.wifi.SupplicantState;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Binder;
 import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
@@ -87,6 +84,11 @@
     int mDataTypeIconId;
     boolean mDataActive;
 
+    String mContentDescriptionPhoneSignal;
+    String mContentDescriptionWifi;
+    String mContentDescriptionCombinedSignal;
+    String mContentDescriptionDataType;
+
     // wifi
     final WifiManager mWifiManager;
     AsyncChannel mWifiChannel;
@@ -366,6 +368,8 @@
             if (mSignalStrength == null) {
                 mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
                 mDataSignalIconId = R.drawable.stat_sys_signal_0; // note we use 0 instead of null
+                mContentDescriptionPhoneSignal = mContext.getString(
+                        AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]);
             } else {
                 int iconLevel;
                 int[] iconList;
@@ -385,6 +389,9 @@
                     }
                 }
                 mPhoneSignalIconId = iconList[iconLevel];
+                mContentDescriptionPhoneSignal = mContext.getString(
+                        AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[iconLevel]);
+
                 mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel];
             }
         }
@@ -395,14 +402,20 @@
             case TelephonyManager.NETWORK_TYPE_UNKNOWN:
                 mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
                 mDataTypeIconId = 0;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_gprs);
                 break;
             case TelephonyManager.NETWORK_TYPE_EDGE:
                 mDataIconList = TelephonyIcons.DATA_E[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_edge;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_edge);
                 break;
             case TelephonyManager.NETWORK_TYPE_UMTS:
                 mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_3g;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_3g);
                 break;
             case TelephonyManager.NETWORK_TYPE_HSDPA:
             case TelephonyManager.NETWORK_TYPE_HSUPA:
@@ -410,19 +423,27 @@
                 if (mHspaDataDistinguishable) {
                     mDataIconList = TelephonyIcons.DATA_H[mInetCondition];
                     mDataTypeIconId = R.drawable.stat_sys_signal_hsdpa;
+                    mContentDescriptionDataType = mContext.getString(
+                            R.string.accessibility_data_connection_3_5g);
                 } else {
                     mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
                     mDataTypeIconId = R.drawable.stat_sys_signal_3g;
+                    mContentDescriptionDataType = mContext.getString(
+                            R.string.accessibility_data_connection_3g);
                 }
                 break;
             case TelephonyManager.NETWORK_TYPE_CDMA:
                 // display 1xRTT for IS95A/B
                 mDataIconList = TelephonyIcons.DATA_1X[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_1x;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_cdma);
                 break;
             case TelephonyManager.NETWORK_TYPE_1xRTT:
                 mDataIconList = TelephonyIcons.DATA_1X[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_1x;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_cdma);
                 break;
             case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
             case TelephonyManager.NETWORK_TYPE_EVDO_A:
@@ -430,14 +451,20 @@
             case TelephonyManager.NETWORK_TYPE_EHRPD:
                 mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_3g;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_3g);
                 break;
             case TelephonyManager.NETWORK_TYPE_LTE:
                 mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_4g;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_4g);
                 break;
             default:
                 mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_gprs;
+                mContentDescriptionDataType = mContext.getString(
+                        R.string.accessibility_data_connection_gprs);
                 break;
         }
         if ((isCdma() && isCdmaEri()) || mPhone.isNetworkRoaming()) {
@@ -618,8 +645,11 @@
     private void updateWifiIcons() {
         if (mWifiConnected) {
             mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel];
+            mContentDescriptionWifi = mContext.getString(
+                    AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH[mWifiLevel]);
         } else {
             mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[0][0];
+            mContentDescriptionWifi = mContext.getString(R.string.accessibility_no_wifi);
         }
     }
 
@@ -704,6 +734,7 @@
                 }
             }
             combinedSignalIconId = mWifiIconId;
+            mContentDescriptionCombinedSignal = mContentDescriptionWifi;
             dataTypeIconId = 0;
         } else if (mDataConnected) {
             label = mNetworkName;
@@ -723,22 +754,29 @@
                     break;
             }
             combinedSignalIconId = mDataSignalIconId;
+            mContentDescriptionCombinedSignal = mContentDescriptionDataType;
             dataTypeIconId = mDataTypeIconId;
         } else if (mBluetoothTethered) {
             label = mContext.getString(R.string.bluetooth_tethered);
             combinedSignalIconId = mBluetoothTetherIconId;
+            mContentDescriptionCombinedSignal = mContext.getString(
+                    R.string.accessibility_bluetooth_tether);
             dataTypeIconId = 0;
         } else if (mAirplaneMode &&
                 (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly()))) {
             // Only display the flight-mode icon if not in "emergency calls only" mode.
             label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
             combinedSignalIconId = R.drawable.stat_sys_signal_flightmode;
+            mContentDescriptionCombinedSignal = mContext.getString(
+                    R.string.accessibility_airplane_mode);
             dataTypeIconId = 0;
         } else {
             label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
             // On devices without mobile radios, we want to show the wifi icon
             combinedSignalIconId =
                 hasMobileDataFeature() ? mDataSignalIconId : mWifiIconId;
+            mContentDescriptionCombinedSignal = hasMobileDataFeature()
+                ? mContentDescriptionDataType : mContentDescriptionWifi;
             dataTypeIconId = 0;
         }
 
@@ -764,6 +802,7 @@
             for (int i=0; i<N; i++) {
                 final ImageView v = mPhoneSignalIconViews.get(i);
                 v.setImageResource(mPhoneSignalIconId);
+                v.setContentDescription(mContentDescriptionPhoneSignal);
             }
         }
 
@@ -774,6 +813,7 @@
             for (int i=0; i<N; i++) {
                 final ImageView v = mDataDirectionIconViews.get(i);
                 v.setImageResource(mDataDirectionIconId);
+                v.setContentDescription(mContentDescriptionDataType);
             }
         }
 
@@ -784,6 +824,7 @@
             for (int i=0; i<N; i++) {
                 final ImageView v = mWifiIconViews.get(i);
                 v.setImageResource(mWifiIconId);
+                v.setContentDescription(mContentDescriptionWifi);
             }
         }
 
@@ -794,6 +835,7 @@
             for (int i=0; i<N; i++) {
                 final ImageView v = mCombinedSignalIconViews.get(i);
                 v.setImageResource(combinedSignalIconId);
+                v.setContentDescription(mContentDescriptionCombinedSignal);
             }
         }
 
@@ -808,6 +850,7 @@
                 } else {
                     v.setVisibility(View.VISIBLE);
                     v.setImageResource(dataTypeIconId);
+                    v.setContentDescription(mContentDescriptionDataType);
                 }
             }
         }
@@ -826,6 +869,7 @@
                 } else {
                     v.setVisibility(View.VISIBLE);
                     v.setImageResource(dataDirectionOverlayIconId);
+                    v.setContentDescription(mContentDescriptionDataType);
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
index b4d2a14..d5885bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -148,6 +148,11 @@
                                 "now sliding child %d: %s (touchY=%.1f, rowHeight=%d, count=%d)",
                                 childIdx, mSlidingChild, mInitialTouchY, mRowHeight, count));
                         }
+
+
+                        // We need to prevent the surrounding ScrollView from intercepting us now;
+                        // the scroll position will be locked while we swipe
+                        requestDisallowInterceptTouchEvent(true);
                     }
                 }
                 break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java
index c62c4ad..8c4ae19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java
@@ -22,6 +22,7 @@
 import android.os.RemoteException;
 import android.util.AttributeSet;
 import android.util.Slog;
+import android.view.MotionEvent;
 import android.view.View;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
@@ -90,6 +91,19 @@
         return false;
     }
 
+    @Override
+    public boolean dispatchHoverEvent(MotionEvent event) {
+        // Ignore hover events outside of this panel bounds since such events
+        // generate spurious accessibility events with the panel content when
+        // tapping outside of it, thus confusing the user.
+        final int x = (int) event.getX();
+        final int y = (int) event.getY();
+        if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
+            return super.dispatchHoverEvent(event);
+        }
+        return true;
+    }
+
     public void setTrigger(View v) {
         mTrigger = v;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
index 339e3f3..1e417ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
@@ -30,6 +30,7 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Pair;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
@@ -160,6 +161,19 @@
         }
     }
 
+    @Override
+    public boolean dispatchHoverEvent(MotionEvent event) {
+        // Ignore hover events outside of this panel bounds since such events
+        // generate spurious accessibility events with the panel content when
+        // tapping outside of it, thus confusing the user.
+        final int x = (int) event.getX();
+        final int y = (int) event.getY();
+        if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
+            return super.dispatchHoverEvent(event);
+        }
+        return true;
+    }
+
     private void updateHardKeyboardEnabled() {
         if (mHardKeyboardAvailable) {
             final boolean checked = mHardKeyboardSwitch.isChecked();
@@ -222,6 +236,7 @@
             itemSubtitle.setText(imiName);
         }
         subtypeIcon.setImageDrawable(icon);
+        subtypeIcon.setContentDescription(itemTitle.getText());
         final String settingsActivity = imi.getSettingsActivity();
         if (!TextUtils.isEmpty(settingsActivity)) {
             settingsIcon.setOnClickListener(new View.OnClickListener() {
@@ -463,4 +478,5 @@
     public interface OnHardKeyboardEnabledChangeListener {
         public void onHardKeyboardEnabledChange(boolean enabled);
     }
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationArea.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationArea.java
new file mode 100644
index 0000000..42bdf3d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationArea.java
@@ -0,0 +1,45 @@
+/*
+ * 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 com.android.systemui.statusbar.tablet;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.LinearLayout;
+
+public class NotificationArea extends LinearLayout {
+
+    public NotificationArea(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+        if (super.onRequestSendAccessibilityEvent(child, event)) {
+            // The event is coming from a descendant like battery but append
+            // the content of the entire notification area so accessibility
+            // services can choose how to present the content to the user.
+            AccessibilityEvent record = AccessibilityEvent.obtain();
+            onInitializeAccessibilityEvent(record);
+            dispatchPopulateAccessibilityEvent(record);
+            event.appendRecord(record);
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index 64a4f16..a316e4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -20,27 +20,15 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
 import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
 import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Slog;
-import android.view.accessibility.AccessibilityEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
-import android.view.SoundEffectConstants;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.animation.AccelerateInterpolator;
-import android.widget.FrameLayout;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
-import android.widget.TextView;
 
 import com.android.systemui.R;
 
@@ -53,8 +41,7 @@
 
     boolean mShowing;
     int mNotificationCount = 0;
-    View mTitleArea;
-    ModeToggle mModeToggle;
+    NotificationPanelTitle mTitleArea;
     View mSettingsButton;
     View mNotificationButton;
     View mNotificationScroller;
@@ -68,48 +55,6 @@
 
     Choreographer mChoreo = new Choreographer();
 
-    static class ModeToggle extends View {
-        NotificationPanel mPanel;
-        View mTitle;
-        public ModeToggle(Context context, AttributeSet attrs) {
-            super(context, attrs);
-        }
-        public void setPanel(NotificationPanel p) {
-            mPanel = p;
-        }
-        public void setTitleArea(View v) {
-            mTitle = v;
-        }
-        @Override
-        public boolean onTouchEvent(MotionEvent e) {
-            final int x = (int)e.getX();
-            final int y = (int)e.getY();
-            switch (e.getAction()) {
-                case MotionEvent.ACTION_DOWN:
-                    mTitle.setPressed(true);
-                    break;
-                case MotionEvent.ACTION_MOVE:
-                    mTitle.setPressed(x >= 0
-                            && x < getWidth()
-                            && y >= 0
-                            && y < getHeight());
-                    break;
-                case MotionEvent.ACTION_CANCEL:
-                    mTitle.setPressed(false);
-                    break;
-                case MotionEvent.ACTION_UP:
-                    if (mTitle.isPressed()) {
-                        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
-                        playSoundEffect(SoundEffectConstants.CLICK);
-                        mPanel.swapPanels();
-                        mTitle.setPressed(false);
-                    }
-                    break;
-            }
-            return true;
-        }
-    }
-
     public NotificationPanel(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
@@ -126,14 +71,11 @@
 
         mContentParent = (ViewGroup)findViewById(R.id.content_parent);
         mContentParent.bringToFront();
-        mTitleArea = findViewById(R.id.title_area);
-        mModeToggle = (ModeToggle) findViewById(R.id.mode_toggle);
-        mModeToggle.setOnClickListener(this);
-        mModeToggle.setPanel(this);
-        mModeToggle.setTitleArea(mTitleArea);
+        mTitleArea = (NotificationPanelTitle) findViewById(R.id.title_area);
+        mTitleArea.setPanel(this);
 
-        mSettingsButton = (ImageView)findViewById(R.id.settings_button);
-        mNotificationButton = (ImageView)findViewById(R.id.notification_button);
+        mSettingsButton = findViewById(R.id.settings_button);
+        mNotificationButton = findViewById(R.id.notification_button);
 
         mNotificationScroller = findViewById(R.id.notification_scroller);
         mContentFrame = (ViewGroup)findViewById(R.id.content_frame);
@@ -185,6 +127,19 @@
         }
     }
 
+    @Override
+    public boolean dispatchHoverEvent(MotionEvent event) {
+        // Ignore hover events outside of this panel bounds since such events
+        // generate spurious accessibility events with the panel content when
+        // tapping outside of it, thus confusing the user.
+        final int x = (int) event.getX();
+        final int y = (int) event.getY();
+        if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
+            return super.dispatchHoverEvent(event);
+        }
+        return true;
+    }
+
     /*
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
@@ -205,7 +160,7 @@
     */
 
     public void onClick(View v) {
-        if (v == mModeToggle) {
+        if (v == mTitleArea) {
             swapPanels();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanelTitle.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanelTitle.java
new file mode 100644
index 0000000..689bc36
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanelTitle.java
@@ -0,0 +1,82 @@
+/*
+ * 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 com.android.systemui.statusbar.tablet;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.SoundEffectConstants;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.RelativeLayout;
+
+public class NotificationPanelTitle extends RelativeLayout implements View.OnClickListener {
+    private NotificationPanel mPanel;
+
+    public NotificationPanelTitle(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setOnClickListener(this);
+    }
+
+    public void setPanel(NotificationPanel p) {
+        mPanel = p;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent e) {
+        switch (e.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                setPressed(true);
+                break;
+            case MotionEvent.ACTION_MOVE:
+                final int x = (int) e.getX();
+                final int y = (int) e.getY();
+                setPressed(x > 0 && x < getWidth() && y > 0 && y < getHeight());
+                break;
+            case MotionEvent.ACTION_UP:
+                if (isPressed()) {
+                    playSoundEffect(SoundEffectConstants.CLICK);
+                    mPanel.swapPanels();
+                    setPressed(false);
+                }
+                break;
+            case MotionEvent.ACTION_CANCEL:
+                setPressed(false);
+                break;
+        }
+        return true;
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v == this) {
+            mPanel.swapPanels();
+        }
+    }
+
+    @Override
+    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+        if (super.onRequestSendAccessibilityEvent(child, event)) {
+            AccessibilityEvent record = AccessibilityEvent.obtain();
+            onInitializeAccessibilityEvent(record);
+            dispatchPopulateAccessibilityEvent(record);
+            event.appendRecord(record);
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java
index 8b68240..ba28306 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java
@@ -18,12 +18,9 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
-import android.util.Slog;
 import android.view.MotionEvent;
 import android.widget.RelativeLayout;
 
-import com.android.systemui.R;
-
 public class NotificationPeekPanel extends RelativeLayout implements StatusBarPanel {
     TabletStatusBar mBar;
 
@@ -54,5 +51,17 @@
         mBar.resetNotificationPeekFadeTimer();
         return false;
     }
-}
 
+    @Override
+    public boolean dispatchHoverEvent(MotionEvent event) {
+        // Ignore hover events outside of this panel bounds since such events
+        // generate spurious accessibility events with the panel content when
+        // tapping outside of it, thus confusing the user.
+        final int x = (int) event.getX();
+        final int y = (int) event.getY();
+        if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
+            return super.dispatchHoverEvent(event);
+        }
+        return true;
+    }
+}
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 df09f84..13846ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -808,7 +808,8 @@
                 // Update the icon.
                 final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
                         notification.notification.icon, notification.notification.iconLevel,
-                        notification.notification.number);
+                        notification.notification.number,
+                        notification.notification.tickerText);
                 if (!oldEntry.icon.set(ic)) {
                     handleNotificationError(key, notification, "Couldn't update icon: " + ic);
                     return;
@@ -1012,10 +1013,7 @@
 
         mCompatModeButton.refresh();
         if (mCompatModeButton.getVisibility() == View.VISIBLE) {
-            if (DEBUG_COMPAT_HELP
-                    || ! Prefs.read(mContext).getBoolean(Prefs.SHOWN_COMPAT_MODE_HELP, false)) {
                 showCompatibilityHelp();
-            }
         } else {
             hideCompatibilityHelp();
             mCompatModePanel.closePanel();
@@ -1451,13 +1449,15 @@
         }
         // Construct the icon.
         final StatusBarIconView iconView = new StatusBarIconView(mContext,
-                notification.pkg + "/0x" + Integer.toHexString(notification.id));
+                notification.pkg + "/0x" + Integer.toHexString(notification.id),
+                notification.notification);
         iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
 
         final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
                     notification.notification.icon,
                     notification.notification.iconLevel,
-                    notification.notification.number);
+                    notification.notification.number,
+                    notification.notification.tickerText);
         if (!iconView.set(ic)) {
             handleNotificationError(key, notification, "Couldn't attach StatusBarIcon: " + ic);
             return null;
@@ -1501,11 +1501,6 @@
         // alternate behavior in DND mode
         if (mNotificationDNDMode) {
             if (mIconLayout.getChildCount() == 0) {
-                final StatusBarIconView iconView = new StatusBarIconView(mContext, "_dnd");
-                iconView.setImageResource(R.drawable.ic_notification_dnd);
-                iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
-                iconView.setPadding(mIconHPadding, 0, mIconHPadding, 0);
-
                 final Notification dndNotification = new Notification.Builder(mContext)
                     .setContentTitle(mContext.getText(R.string.notifications_off_title))
                     .setContentText(mContext.getText(R.string.notifications_off_text))
@@ -1513,6 +1508,12 @@
                     .setOngoing(true)
                     .getNotification();
 
+                final StatusBarIconView iconView = new StatusBarIconView(mContext, "_dnd",
+                        dndNotification);
+                iconView.setImageResource(R.drawable.ic_notification_dnd);
+                iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+                iconView.setPadding(mIconHPadding, 0, mIconHPadding, 0);
+
                 mNotificationDNDDummyEntry = new NotificationData.Entry(
                         null,
                         new StatusBarNotification("", 0, "", 0, 0, dndNotification),
@@ -1634,19 +1635,24 @@
         } else {
             if ((sbn.notification.flags & Notification.FLAG_ONGOING_EVENT) == 0) {
                 vetoButton.setVisibility(View.INVISIBLE);
+                vetoButton.setContentDescription("VETO");
             } else {
                 vetoButton.setVisibility(View.GONE);
             }
         }
+        vetoButton.setContentDescription(mContext.getString(
+                R.string.accessibility_remove_notification));
 
         // the large icon
         ImageView largeIcon = (ImageView)row.findViewById(R.id.large_icon);
         if (sbn.notification.largeIcon != null) {
             largeIcon.setImageBitmap(sbn.notification.largeIcon);
+            largeIcon.setContentDescription(sbn.notification.tickerText);
         } else {
             largeIcon.getLayoutParams().width = 0;
             largeIcon.setVisibility(View.INVISIBLE);
         }
+        largeIcon.setContentDescription(sbn.notification.tickerText);
 
         // bind the click event to the content area
         ViewGroup content = (ViewGroup)row.findViewById(R.id.content);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index a8f4262..6045e31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -284,7 +284,7 @@
         } else if (n.tickerText != null) {
             group = (ViewGroup)inflater.inflate(R.layout.status_bar_ticker_compat, mWindow, false);
             final Drawable icon = StatusBarIconView.getIcon(mContext,
-                    new StatusBarIcon(notification.pkg, n.icon, n.iconLevel, 0));
+                    new StatusBarIcon(notification.pkg, n.icon, n.iconLevel, 0, n.tickerText));
             ImageView iv = (ImageView)group.findViewById(iconId);
             iv.setImageDrawable(icon);
             iv.setVisibility(View.VISIBLE);
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 935f4ad..47d34b3 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -35,7 +35,6 @@
 import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Handler;
-import android.os.IBinder;
 import android.os.LocalPowerManager;
 import android.os.Message;
 import android.os.PowerManager;
@@ -43,7 +42,6 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
 import android.telephony.TelephonyManager;
 import android.util.EventLog;
 import android.util.Log;
@@ -1117,8 +1115,11 @@
                 // Give feedback to user when secure keyguard is active and engaged
                 if (mShowing && isSecure()) {
                     if (!mShowingLockIcon) {
+                        String contentDescription = mContext.getString(
+                                com.android.internal.R.string.status_bar_device_locked);
                         mStatusBarManager.setIcon("secure",
-                                com.android.internal.R.drawable.stat_sys_secure, 0);
+                                com.android.internal.R.drawable.stat_sys_secure, 0,
+                                contentDescription);
                         mShowingLockIcon = true;
                     }
                 } else {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index b963b13..e0debf7 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -388,6 +388,11 @@
         st.isHandled = false;
         mPreparedPanel = st;
 
+        if (st.frozenActionViewState != null) {
+            st.menu.restoreActionViewStates(st.frozenActionViewState);
+            st.frozenActionViewState = null;
+        }
+
         return true;
     }
 
@@ -652,7 +657,13 @@
     @Override
     public void invalidatePanelMenu(int featureId) {
         PanelFeatureState st = getPanelState(featureId, true);
+        Bundle savedActionViewStates = null;
         if (st.menu != null) {
+            savedActionViewStates = new Bundle();
+            st.menu.saveActionViewStates(savedActionViewStates);
+            if (savedActionViewStates.size() > 0) {
+                st.frozenActionViewState = savedActionViewStates;
+            }
             st.menu.clear();
         }
         st.refreshMenuContent = true;
@@ -3024,6 +3035,12 @@
          */
         Bundle frozenMenuState;
 
+        /**
+         * Contains the state of associated action views when told to freeze.
+         * These are saved across invalidations.
+         */
+        Bundle frozenActionViewState;
+
         PanelFeatureState(int featureId) {
             this.featureId = featureId;
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index ad6cebb..ae13ab5 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -166,22 +166,22 @@
     static final int SYSTEM_DIALOG_LAYER = 6;
     // toasts and the plugged-in battery thing
     static final int TOAST_LAYER = 7;
-    static final int STATUS_BAR_LAYER = 8;
-    static final int STATUS_BAR_PANEL_LAYER = 9;
     // SIM errors and unlock.  Not sure if this really should be in a high layer.
-    static final int PRIORITY_PHONE_LAYER = 10;
+    static final int PRIORITY_PHONE_LAYER = 8;
     // like the ANR / app crashed dialogs
-    static final int SYSTEM_ALERT_LAYER = 11;
+    static final int SYSTEM_ALERT_LAYER = 9;
     // system-level error dialogs
-    static final int SYSTEM_ERROR_LAYER = 12;
+    static final int SYSTEM_ERROR_LAYER = 10;
     // on-screen keyboards and other such input method user interfaces go here.
-    static final int INPUT_METHOD_LAYER = 13;
+    static final int INPUT_METHOD_LAYER = 11;
     // on-screen keyboards and other such input method user interfaces go here.
-    static final int INPUT_METHOD_DIALOG_LAYER = 14;
+    static final int INPUT_METHOD_DIALOG_LAYER = 12;
     // the keyguard; nothing on top of these can take focus, since they are
     // responsible for power management when displayed.
-    static final int KEYGUARD_LAYER = 15;
-    static final int KEYGUARD_DIALOG_LAYER = 16;
+    static final int KEYGUARD_LAYER = 13;
+    static final int KEYGUARD_DIALOG_LAYER = 14;
+    static final int STATUS_BAR_LAYER = 15;
+    static final int STATUS_BAR_PANEL_LAYER = 16;
     // the navigation bar, if available, shows atop most things
     static final int NAVIGATION_BAR_LAYER = 17;
     // the drag layer: input for drag-and-drop is associated with this window,
@@ -1703,7 +1703,11 @@
                     }
                 }
             }
-            if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + navr);
+            if (DEBUG_LAYOUT) {
+                Log.i(TAG, "mNavigationBar frame: " + navr);
+                Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
+                            mDockLeft, mDockTop, mDockRight, mDockBottom));
+            }
 
             // apply navigation bar insets
             pf.left = df.left = vf.left = mDockLeft;
@@ -1713,6 +1717,25 @@
 
             mStatusBar.computeFrameLw(pf, df, vf, vf);
 
+            // now, let's consider the navigation bar; if it exists, it must be removed from the
+            // available screen real estate (like an un-hideable status bar)
+            if (navr != null) {
+                if (navr.top == 0) {
+                    // Navigation bar is vertical
+                    if (mRestrictedScreenLeft == navr.left) {
+                        mRestrictedScreenLeft = navr.right;
+                        mRestrictedScreenWidth -= (navr.right - navr.left);
+                    } else if ((mRestrictedScreenLeft+mRestrictedScreenWidth) == navr.right) {
+                        mRestrictedScreenWidth -= (navr.right - navr.left);
+                    }
+                } else {
+                    // Navigation bar horizontal, at bottom
+                    if ((mRestrictedScreenHeight+mRestrictedScreenTop) == navr.bottom) {
+                        mRestrictedScreenHeight -= (navr.bottom-navr.top);
+                    }
+                }
+            }
+
             if (mStatusBar.isVisibleLw()) {
                 // If the status bar is hidden, we don't want to cause
                 // windows behind it to scroll.
@@ -1745,23 +1768,6 @@
                         mRestrictedScreenHeight -= (r.bottom-r.top);
                     }
 
-                    if (navr != null) {
-                        if (navr.top == 0) {
-                            // Navigation bar is vertical
-                            if (mRestrictedScreenLeft == navr.left) {
-                                mRestrictedScreenLeft = navr.right;
-                                mRestrictedScreenWidth -= (navr.right - navr.left);
-                            } else if ((mRestrictedScreenLeft+mRestrictedScreenWidth) == navr.right) {
-                                mRestrictedScreenWidth -= (navr.right - navr.left);
-                            }
-                        } else {
-                            // Navigation bar horizontal, at bottom
-                            if ((mRestrictedScreenHeight-mRestrictedScreenTop) == r.bottom) {
-                                mRestrictedScreenHeight -= (navr.bottom-navr.top);
-                            }
-                        }
-                    }
-
                     mContentTop = mCurTop = mDockTop = mRestrictedScreenTop;
                     mContentBottom = mCurBottom = mDockBottom
                             = mRestrictedScreenTop + mRestrictedScreenHeight;
@@ -1873,19 +1879,22 @@
                         // permission, so they have the same privileges as the status
                         // bar itself.
                         //
-                        // However, they should still dodge the navigation bar if it exists. A
-                        // straightforward way to do this is to only allow the status bar panels to
-                        // extend to the extrema of the allowable region for the IME dock.
+                        // However, they should still dodge the navigation bar if it exists.
 
                         pf.left = df.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
                         pf.top = df.top = mUnrestrictedScreenTop;
                         pf.right = df.right = hasNavBar
-                                            ? mDockRight
+                                            ? mRestrictedScreenLeft+mRestrictedScreenWidth
                                             : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
                         pf.bottom = df.bottom = hasNavBar
-                                              ? mDockBottom
+                                              ? mRestrictedScreenTop+mRestrictedScreenHeight
                                               : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
 
+                        if (DEBUG_LAYOUT) {
+                            Log.v(TAG, String.format(
+                                        "Laying out status bar window: (%d,%d - %d,%d)",
+                                        pf.left, pf.top, pf.right, pf.bottom));
+                        }
                     } else {
                         pf.left = df.left = mRestrictedScreenLeft;
                         pf.top = df.top = mRestrictedScreenTop;
@@ -1922,12 +1931,23 @@
                     pf.left = df.left = cf.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
                     pf.top = df.top = cf.top = mUnrestrictedScreenTop;
                     pf.right = df.right = cf.right = hasNavBar
-                                        ? mDockRight
+                                        ? mRestrictedScreenLeft+mRestrictedScreenWidth
                                         : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
                     pf.bottom = df.bottom = cf.bottom = hasNavBar
-                                          ? mDockBottom
+                                          ? mRestrictedScreenTop+mRestrictedScreenHeight
                                           : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
 
+                } else if (attrs.type == TYPE_NAVIGATION_BAR) {
+                    // The navigation bar has Real Ultimate Power.
+                    pf.left = df.left = mUnrestrictedScreenLeft;
+                    pf.top = df.top = mUnrestrictedScreenTop;
+                    pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
+                    pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+                    if (DEBUG_LAYOUT) {
+                        Log.v(TAG, String.format(
+                                    "Laying out navigation bar window: (%d,%d - %d,%d)",
+                                    pf.left, pf.top, pf.right, pf.bottom));
+                    }
                 } else {
                     pf.left = df.left = cf.left = mRestrictedScreenLeft;
                     pf.top = df.top = cf.top = mRestrictedScreenTop;
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 2597978..d39f565f 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -50,6 +50,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.res.Configuration;
@@ -165,7 +166,7 @@
     private final KeyguardManager mKeyguardManager;
     private final Notification mImeSwitcherNotification;
     private final PendingIntent mImeSwitchPendingIntent;
-    private final boolean mShowOngoingImeSwitcherForPhones;
+    private boolean mShowOngoingImeSwitcherForPhones;
     private boolean mNotificationShown;
 
     class SessionState {
@@ -537,8 +538,8 @@
         mImeSwitcherNotification.vibrate = null;
         Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
         mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
-        mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
-                com.android.internal.R.bool.show_ongoing_ime_switcher);
+
+        mShowOngoingImeSwitcherForPhones = false;
 
         synchronized (mMethodMap) {
             mFileManager = new InputMethodFileManager(mMethodMap);
@@ -611,6 +612,8 @@
         synchronized (mMethodMap) {
             if (!mSystemReady) {
                 mSystemReady = true;
+                mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
+                        com.android.internal.R.bool.show_ongoing_ime_switcher);
                 try {
                     startInputInnerLocked();
                 } catch (RuntimeException e) {
@@ -1046,7 +1049,16 @@
                     mStatusBar.setIconVisibility("ime", false);
                 } else if (packageName != null) {
                     if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
-                    mStatusBar.setIcon("ime", packageName, iconId, 0);
+                    CharSequence contentDescription = null;
+                    try {
+                        PackageManager packageManager = mContext.getPackageManager();
+                        contentDescription = packageManager.getApplicationLabel(
+                                packageManager.getApplicationInfo(packageName, 0));
+                    } catch (NameNotFoundException nnfe) {
+                        /* ignore */
+                    }
+                    mStatusBar.setIcon("ime", packageName, iconId, 0,
+                            contentDescription  != null ? contentDescription.toString() : null);
                     mStatusBar.setIconVisibility("ime", true);
                 }
             }
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 41e8a31..2366fcb 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -93,6 +93,7 @@
     private static final String KEY_TX = "tx_bytes";
 
     class NetdResponseCode {
+        /* Keep in sync with system/netd/ResponseCode.h */
         public static final int InterfaceListResult       = 110;
         public static final int TetherInterfaceListResult = 111;
         public static final int TetherDnsFwdTgtListResult = 112;
@@ -108,6 +109,7 @@
         public static final int InterfaceTxThrottleResult = 219;
 
         public static final int InterfaceChange           = 600;
+        public static final int BandwidthControl          = 601;
     }
 
     /**
@@ -265,6 +267,20 @@
     }
 
     /**
+     * Notify our observers of a limit reached.
+     */
+    private void notifyLimitReached(String limitName, String iface) {
+        for (INetworkManagementEventObserver obs : mObservers) {
+            try {
+                obs.limitReached(limitName, iface);
+                Slog.d(TAG, "Observer notified limit reached for " + limitName + " " + iface);
+            } catch (Exception ex) {
+                Slog.w(TAG, "Observer notifier failed", ex);
+            }
+        }
+    }
+
+    /**
      * Let us know the daemon is connected
      */
     protected void onConnected() {
@@ -286,33 +302,52 @@
             }.start();
         }
         public boolean onEvent(int code, String raw, String[] cooked) {
-            if (code == NetdResponseCode.InterfaceChange) {
-                /*
-                 * a network interface change occured
-                 * Format: "NNN Iface added <name>"
-                 *         "NNN Iface removed <name>"
-                 *         "NNN Iface changed <name> <up/down>"
-                 *         "NNN Iface linkstatus <name> <up/down>"
-                 */
-                if (cooked.length < 4 || !cooked[1].equals("Iface")) {
+            switch (code) {
+            case NetdResponseCode.InterfaceChange:
+                    /*
+                     * a network interface change occured
+                     * Format: "NNN Iface added <name>"
+                     *         "NNN Iface removed <name>"
+                     *         "NNN Iface changed <name> <up/down>"
+                     *         "NNN Iface linkstatus <name> <up/down>"
+                     */
+                    if (cooked.length < 4 || !cooked[1].equals("Iface")) {
+                        throw new IllegalStateException(
+                                String.format("Invalid event from daemon (%s)", raw));
+                    }
+                    if (cooked[2].equals("added")) {
+                        notifyInterfaceAdded(cooked[3]);
+                        return true;
+                    } else if (cooked[2].equals("removed")) {
+                        notifyInterfaceRemoved(cooked[3]);
+                        return true;
+                    } else if (cooked[2].equals("changed") && cooked.length == 5) {
+                        notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
+                        return true;
+                    } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
+                        notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
+                        return true;
+                    }
                     throw new IllegalStateException(
                             String.format("Invalid event from daemon (%s)", raw));
-                }
-                if (cooked[2].equals("added")) {
-                    notifyInterfaceAdded(cooked[3]);
-                    return true;
-                } else if (cooked[2].equals("removed")) {
-                    notifyInterfaceRemoved(cooked[3]);
-                    return true;
-                } else if (cooked[2].equals("changed") && cooked.length == 5) {
-                    notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
-                    return true;
-                } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
-                    notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
-                    return true;
-                }
-                throw new IllegalStateException(
-                        String.format("Invalid event from daemon (%s)", raw));
+                    // break;
+            case NetdResponseCode.BandwidthControl:
+                    /*
+                     * Bandwidth control needs some attention
+                     * Format: "NNN limit alert <alertName> <ifaceName>"
+                     */
+                    if (cooked.length < 5 || !cooked[1].equals("limit")) {
+                        throw new IllegalStateException(
+                                String.format("Invalid event from daemon (%s)", raw));
+                    }
+                    if (cooked[2].equals("alert")) {
+                        notifyLimitReached(cooked[3], cooked[4]);
+                        return true;
+                    }
+                    throw new IllegalStateException(
+                            String.format("Invalid event from daemon (%s)", raw));
+                    // break;
+            default: break;
             }
             return false;
         }
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 286a937..4ced83c 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -22,10 +22,10 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
-import android.os.IBinder;
-import android.os.RemoteException;
 import android.os.Binder;
 import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
 import android.util.Slog;
 import android.view.View;
 
@@ -175,7 +175,8 @@
         }
     }
 
-    public void setIcon(String slot, String iconPackage, int iconId, int iconLevel) {
+    public void setIcon(String slot, String iconPackage, int iconId, int iconLevel,
+            String contentDescription) {
         enforceStatusBar();
 
         synchronized (mIcons) {
@@ -184,7 +185,8 @@
                 throw new SecurityException("invalid status bar icon slot: " + slot);
             }
 
-            StatusBarIcon icon = new StatusBarIcon(iconPackage, iconId, iconLevel);
+            StatusBarIcon icon = new StatusBarIcon(iconPackage, iconId, iconLevel, 0,
+                    contentDescription);
             //Slog.d(TAG, "setIcon slot=" + slot + " index=" + index + " icon=" + icon);
             mIcons.setIcon(index, icon);
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 8c7e279..76665915 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -230,6 +230,7 @@
         WallpaperManagerService wallpaper = null;
         LocationManagerService location = null;
         CountryDetectorService countryDetector = null;
+        TextServicesManagerService tsms = null;
 
         if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
             try {
@@ -273,6 +274,14 @@
             }
 
             try {
+                Slog.i(TAG, "Text Service Manager Service");
+                tsms = new TextServicesManagerService(context);
+                ServiceManager.addService(Context.TEXT_SERVICES_MANAGER_SERVICE, tsms);
+            } catch (Throwable e) {
+                Slog.e(TAG, "Failure starting Text Service Manager Service", e);
+            }
+
+            try {
                 Slog.i(TAG, "NetworkStats Service");
                 networkStats = new NetworkStatsService(context, networkManagement, alarm);
                 ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats);
@@ -538,6 +547,7 @@
         final LocationManagerService locationF = location;
         final CountryDetectorService countryDetectorF = countryDetector;
         final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater;
+        final TextServicesManagerService textServiceManagerServiceF = tsms;
 
         // We now tell the activity manager it is okay to run third party
         // code.  It will call back into us once it has gotten to the state
@@ -571,6 +581,7 @@
                 if (countryDetectorF != null) countryDetectorF.systemReady();
                 if (throttleF != null) throttleF.systemReady();
                 if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemReady();
+                if (textServiceManagerServiceF != null) textServiceManagerServiceF.systemReady();
             }
         });
 
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
new file mode 100644
index 0000000..4a0c837
--- /dev/null
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -0,0 +1,346 @@
+/*
+ * 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 com.android.server;
+
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.textservice.ISpellCheckerService;
+import com.android.internal.textservice.ISpellCheckerSession;
+import com.android.internal.textservice.ISpellCheckerSessionListener;
+import com.android.internal.textservice.ITextServicesManager;
+import com.android.internal.textservice.ITextServicesSessionListener;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.service.textservice.SpellCheckerService;
+import android.util.Log;
+import android.util.Slog;
+import android.view.textservice.SpellCheckerInfo;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+public class TextServicesManagerService extends ITextServicesManager.Stub {
+    private static final String TAG = TextServicesManagerService.class.getSimpleName();
+    private static final boolean DBG = false;
+
+    private final Context mContext;
+    private boolean mSystemReady;
+    private final TextServicesMonitor mMonitor;
+    private final HashMap<String, SpellCheckerInfo> mSpellCheckerMap =
+            new HashMap<String, SpellCheckerInfo>();
+    private final ArrayList<SpellCheckerInfo> mSpellCheckerList = new ArrayList<SpellCheckerInfo>();
+    private final HashMap<String, SpellCheckerBindGroup> mSpellCheckerBindGroups =
+            new HashMap<String, SpellCheckerBindGroup>();
+
+    public void systemReady() {
+        if (!mSystemReady) {
+            mSystemReady = true;
+        }
+    }
+
+    public TextServicesManagerService(Context context) {
+        mSystemReady = false;
+        mContext = context;
+        mMonitor = new TextServicesMonitor();
+        mMonitor.register(context, true);
+        synchronized (mSpellCheckerMap) {
+            buildSpellCheckerMapLocked(context, mSpellCheckerList, mSpellCheckerMap);
+        }
+    }
+
+    private class TextServicesMonitor extends PackageMonitor {
+        @Override
+        public void onSomePackagesChanged() {
+            synchronized (mSpellCheckerMap) {
+                buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap);
+                // TODO: Update for each locale
+                SpellCheckerInfo sci = getCurrentSpellChecker(null);
+                if (sci == null) {
+                    sci = findAvailSpellCheckerLocked(null, null);
+                    if (sci == null) return;
+                    // Set the current spell checker if there is one or more spell checkers
+                    // available. In this case, "sci" is the first one in the available spell
+                    // checkers.
+                    setCurrentSpellChecker(sci);
+                }
+                final String packageName = sci.getPackageName();
+                final int change = isPackageDisappearing(packageName);
+                if (change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE) {
+                    // Package disappearing
+                    setCurrentSpellChecker(findAvailSpellCheckerLocked(null, packageName));
+                } else if (isPackageModified(packageName)) {
+                    // Package modified
+                    setCurrentSpellChecker(findAvailSpellCheckerLocked(null, packageName));
+                }
+            }
+        }
+    }
+
+    private static void buildSpellCheckerMapLocked(Context context,
+            ArrayList<SpellCheckerInfo> list, HashMap<String, SpellCheckerInfo> map) {
+        list.clear();
+        map.clear();
+        final PackageManager pm = context.getPackageManager();
+        List<ResolveInfo> services = pm.queryIntentServices(
+                new Intent(SpellCheckerService.SERVICE_INTERFACE), PackageManager.GET_META_DATA);
+        final int N = services.size();
+        for (int i = 0; i < N; ++i) {
+            final ResolveInfo ri = services.get(i);
+            final ServiceInfo si = ri.serviceInfo;
+            final ComponentName compName = new ComponentName(si.packageName, si.name);
+            if (!android.Manifest.permission.BIND_TEXT_SERVICE.equals(si.permission)) {
+                Slog.w(TAG, "Skipping text service " + compName
+                        + ": it does not require the permission "
+                        + android.Manifest.permission.BIND_TEXT_SERVICE);
+                continue;
+            }
+            if (DBG) Slog.d(TAG, "Add: " + compName);
+            final SpellCheckerInfo sci = new SpellCheckerInfo(context, ri);
+            list.add(sci);
+            map.put(sci.getId(), sci);
+        }
+    }
+
+    // TODO: find an appropriate spell checker for specified locale
+    private SpellCheckerInfo findAvailSpellCheckerLocked(String locale, String prefPackage) {
+        final int spellCheckersCount = mSpellCheckerList.size();
+        if (spellCheckersCount == 0) {
+            Slog.w(TAG, "no available spell checker services found");
+            return null;
+        }
+        if (prefPackage != null) {
+            for (int i = 0; i < spellCheckersCount; ++i) {
+                final SpellCheckerInfo sci = mSpellCheckerList.get(i);
+                if (prefPackage.equals(sci.getPackageName())) {
+                    return sci;
+                }
+            }
+        }
+        if (spellCheckersCount > 1) {
+            Slog.w(TAG, "more than one spell checker service found, picking first");
+        }
+        return mSpellCheckerList.get(0);
+    }
+
+    // TODO: Save SpellCheckerService by supported languages. Currently only one spell
+    // checker is saved.
+    @Override
+    public SpellCheckerInfo getCurrentSpellChecker(String locale) {
+        synchronized (mSpellCheckerMap) {
+            final String curSpellCheckerId =
+                    Settings.Secure.getString(mContext.getContentResolver(),
+                            Settings.Secure.SPELL_CHECKER_SERVICE);
+            if (TextUtils.isEmpty(curSpellCheckerId)) {
+                return null;
+            }
+            return mSpellCheckerMap.get(curSpellCheckerId);
+        }
+    }
+
+    @Override
+    public void getSpellCheckerService(SpellCheckerInfo info, String locale,
+            ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener) {
+        if (!mSystemReady) {
+            return;
+        }
+        if (info == null || tsListener == null) {
+            Slog.e(TAG, "getSpellCheckerService: Invalid input.");
+            return;
+        }
+        final String sciId = info.getId();
+        synchronized(mSpellCheckerMap) {
+            if (!mSpellCheckerMap.containsKey(sciId)) {
+                return;
+            }
+            if (mSpellCheckerBindGroups.containsKey(sciId)) {
+                mSpellCheckerBindGroups.get(sciId).addListener(tsListener, locale, scListener);
+                return;
+            }
+            final InternalServiceConnection connection = new InternalServiceConnection(
+                    sciId, locale, scListener);
+            final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE);
+            serviceIntent.setComponent(info.getComponent());
+            if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) {
+                Slog.e(TAG, "Failed to get a spell checker service.");
+                return;
+            }
+            final SpellCheckerBindGroup group = new SpellCheckerBindGroup(
+                    connection, tsListener, locale, scListener);
+            mSpellCheckerBindGroups.put(sciId, group);
+        }
+        return;
+    }
+
+    @Override
+    public void finishSpellCheckerService(ISpellCheckerSessionListener listener) {
+        synchronized(mSpellCheckerMap) {
+            for (SpellCheckerBindGroup group : mSpellCheckerBindGroups.values()) {
+                if (group == null) continue;
+                group.removeListener(listener);
+            }
+        }
+    }
+
+    private void setCurrentSpellChecker(SpellCheckerInfo sci) {
+        if (sci == null || mSpellCheckerMap.containsKey(sci.getId())) return;
+        Settings.Secure.putString(mContext.getContentResolver(),
+                Settings.Secure.SPELL_CHECKER_SERVICE, sci == null ? "" : sci.getId());
+    }
+
+    // SpellCheckerBindGroup contains active text service session listeners.
+    // If there are no listeners anymore, the SpellCheckerBindGroup instance will be removed from
+    // mSpellCheckerBindGroups
+    private class SpellCheckerBindGroup {
+        final InternalServiceConnection mInternalConnection;
+        final ArrayList<InternalDeathRecipient> mListeners =
+                new ArrayList<InternalDeathRecipient>();
+
+        public SpellCheckerBindGroup(InternalServiceConnection connection,
+                ITextServicesSessionListener listener, String locale,
+                ISpellCheckerSessionListener scListener) {
+            mInternalConnection = connection;
+            addListener(listener, locale, scListener);
+        }
+
+        public void onServiceConnected(ISpellCheckerService spellChecker) {
+            synchronized(mSpellCheckerMap) {
+                for (InternalDeathRecipient listener : mListeners) {
+                    try {
+                        final ISpellCheckerSession session = spellChecker.getISpellCheckerSession(
+                                listener.mScLocale, listener.mScListener);
+                        listener.mTsListener.onServiceConnected(session);
+                    } catch (RemoteException e) {
+                    }
+                }
+            }
+        }
+
+        public void addListener(ITextServicesSessionListener tsListener, String locale,
+                ISpellCheckerSessionListener scListener) {
+            synchronized(mSpellCheckerMap) {
+                try {
+                    final int size = mListeners.size();
+                    for (int i = 0; i < size; ++i) {
+                        if (mListeners.get(i).hasSpellCheckerListener(scListener)) {
+                            // do not add the lister if the group already contains this.
+                            return;
+                        }
+                    }
+                    final InternalDeathRecipient recipient = new InternalDeathRecipient(
+                            this, tsListener, locale, scListener);
+                    scListener.asBinder().linkToDeath(recipient, 0);
+                    mListeners.add(new InternalDeathRecipient(
+                            this, tsListener, locale, scListener));
+                } catch(RemoteException e) {
+                    // do nothing
+                }
+                cleanLocked();
+            }
+        }
+
+        public void removeListener(ISpellCheckerSessionListener listener) {
+            synchronized(mSpellCheckerMap) {
+                final int size = mListeners.size();
+                final ArrayList<InternalDeathRecipient> removeList =
+                        new ArrayList<InternalDeathRecipient>();
+                for (int i = 0; i < size; ++i) {
+                    final InternalDeathRecipient tempRecipient = mListeners.get(i);
+                    if(tempRecipient.hasSpellCheckerListener(listener)) {
+                        removeList.add(tempRecipient);
+                    }
+                }
+                final int removeSize = removeList.size();
+                for (int i = 0; i < removeSize; ++i) {
+                    mListeners.remove(removeList.get(i));
+                }
+                cleanLocked();
+            }
+        }
+
+        private void cleanLocked() {
+            if (mListeners.isEmpty()) {
+                mSpellCheckerBindGroups.remove(this);
+                // Unbind service when there is no active clients.
+                mContext.unbindService(mInternalConnection);
+            }
+        }
+    }
+
+    private class InternalServiceConnection implements ServiceConnection {
+        private final ISpellCheckerSessionListener mListener;
+        private final String mSciId;
+        private final String mLocale;
+        public InternalServiceConnection(
+                String id, String locale, ISpellCheckerSessionListener listener) {
+            mSciId = id;
+            mLocale = locale;
+            mListener = listener;
+        }
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            synchronized(mSpellCheckerMap) {
+                ISpellCheckerService spellChecker = ISpellCheckerService.Stub.asInterface(service);
+                final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId);
+                if (group != null) {
+                    group.onServiceConnected(spellChecker);
+                }
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            mSpellCheckerBindGroups.remove(mSciId);
+        }
+    }
+
+    private class InternalDeathRecipient implements IBinder.DeathRecipient {
+        public final ITextServicesSessionListener mTsListener;
+        public final ISpellCheckerSessionListener mScListener;
+        public final String mScLocale;
+        private final SpellCheckerBindGroup mGroup;
+        public InternalDeathRecipient(SpellCheckerBindGroup group,
+                ITextServicesSessionListener tsListener, String scLocale,
+                ISpellCheckerSessionListener scListener) {
+            mTsListener = tsListener;
+            mScListener = scListener;
+            mScLocale = scLocale;
+            mGroup = group;
+        }
+
+        public boolean hasSpellCheckerListener(ISpellCheckerSessionListener listener) {
+            return mScListener.equals(listener);
+        }
+
+        @Override
+        public void binderDied() {
+            mGroup.removeListener(mScListener);
+        }
+    }
+}
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index b8890aa..cd649ce 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -194,6 +194,7 @@
         }
 
         public void interfaceRemoved(String iface) {}
+        public void limitReached(String limitName, String iface) {}
     }
 
 
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 7112553..f9f63b1 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -1461,7 +1461,7 @@
             if (mMulticasters.size() != 0) {
                 return;
             } else {
-                mWifiStateMachine.startPacketFiltering();
+                mWifiStateMachine.startFilteringMulticastV4Packets();
             }
         }
     }
@@ -1472,11 +1472,11 @@
         synchronized (mMulticasters) {
             mMulticastEnabled++;
             mMulticasters.add(new Multicaster(tag, binder));
-            // Note that we could call stopPacketFiltering only when
+            // Note that we could call stopFilteringMulticastV4Packets only when
             // our new size == 1 (first call), but this function won't
             // be called often and by making the stopPacket call each
             // time we're less fragile and self-healing.
-            mWifiStateMachine.stopPacketFiltering();
+            mWifiStateMachine.stopFilteringMulticastV4Packets();
         }
 
         int uid = Binder.getCallingUid();
@@ -1513,7 +1513,7 @@
             removed.unlinkDeathRecipient();
         }
         if (mMulticasters.size() == 0) {
-            mWifiStateMachine.startPacketFiltering();
+            mWifiStateMachine.startFilteringMulticastV4Packets();
         }
 
         Long ident = Binder.clearCallingIdentity();
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 0924b86..3389f33 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -3628,6 +3628,7 @@
         app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
         app.forcingToForeground = null;
         app.foregroundServices = false;
+        app.hasShownUi = false;
         app.debugging = false;
 
         mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
@@ -9218,6 +9219,7 @@
         app.forcingToForeground = null;
         app.foregroundServices = false;
         app.foregroundActivities = false;
+        app.hasShownUi = false;
 
         killServicesLocked(app, true);
 
@@ -9331,8 +9333,6 @@
             // This app is persistent, so we need to keep its record around.
             // If it is not already on the pending app list, add it there
             // and start a new process for it.
-            app.forcingToForeground = null;
-            app.foregroundServices = false;
             if (mPersistentStartingProcesses.indexOf(app) < 0) {
                 mPersistentStartingProcesses.add(app);
                 restart = true;
@@ -12728,21 +12728,31 @@
             while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
                 ServiceRecord s = jt.next();
                 if (s.startRequested) {
-                    if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
-                        // This service has seen some activity within
-                        // recent memory, so we will keep its process ahead
-                        // of the background processes.
+                    if (app.hasShownUi) {
+                        // If this process has shown some UI, let it immediately
+                        // go to the LRU list because it may be pretty heavy with
+                        // UI stuff.  We'll tag it with a label just to help
+                        // debug and understand what is going on.
                         if (adj > SECONDARY_SERVER_ADJ) {
-                            adj = SECONDARY_SERVER_ADJ;
-                            app.adjType = "started-services";
-                            app.hidden = false;
+                            app.adjType = "started-bg-ui-services";
                         }
-                    }
-                    // If we have let the service slide into the background
-                    // state, still have some text describing what it is doing
-                    // even though the service no longer has an impact.
-                    if (adj > SECONDARY_SERVER_ADJ) {
-                        app.adjType = "started-bg-services";
+                    } else {
+                        if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
+                            // This service has seen some activity within
+                            // recent memory, so we will keep its process ahead
+                            // of the background processes.
+                            if (adj > SECONDARY_SERVER_ADJ) {
+                                adj = SECONDARY_SERVER_ADJ;
+                                app.adjType = "started-services";
+                                app.hidden = false;
+                            }
+                        }
+                        // If we have let the service slide into the background
+                        // state, still have some text describing what it is doing
+                        // even though the service no longer has an impact.
+                        if (adj > SECONDARY_SERVER_ADJ) {
+                            app.adjType = "started-bg-services";
+                        }
                     }
                     // Don't kill this process because it is doing work; it
                     // has said it is doing work.
@@ -13351,15 +13361,15 @@
                                 break;
                         }
                     }
-                } else if (app.curAdj >= PERCEPTIBLE_APP_ADJ) {
-                    if (app.trimMemoryLevel < ComponentCallbacks.TRIM_MEMORY_INVISIBLE
+                } else if (app.curAdj == HEAVY_WEIGHT_APP_ADJ) {
+                    if (app.trimMemoryLevel < ComponentCallbacks.TRIM_MEMORY_BACKGROUND
                             && app.thread != null) {
                         try {
-                            app.thread.scheduleTrimMemory(ComponentCallbacks.TRIM_MEMORY_INVISIBLE);
+                            app.thread.scheduleTrimMemory(ComponentCallbacks.TRIM_MEMORY_BACKGROUND);
                         } catch (RemoteException e) {
                         }
                     }
-                    app.trimMemoryLevel = ComponentCallbacks.TRIM_MEMORY_INVISIBLE;
+                    app.trimMemoryLevel = ComponentCallbacks.TRIM_MEMORY_BACKGROUND;
                 } else {
                     app.trimMemoryLevel = 0;
                 }
@@ -13442,7 +13452,7 @@
     }
 
     public boolean profileControl(String process, boolean start,
-            String path, ParcelFileDescriptor fd) throws RemoteException {
+            String path, ParcelFileDescriptor fd, int profileType) throws RemoteException {
 
         try {
             synchronized (this) {
@@ -13487,7 +13497,7 @@
                     }
                 }
             
-                proc.thread.profilerControl(start, path, fd);
+                proc.thread.profilerControl(start, path, fd, profileType);
                 fd = null;
                 return true;
             }
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 0d89081..cc58eaf 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -559,6 +559,7 @@
             r.forceNewConfig = false;
             showAskCompatModeDialogLocked(r);
             r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
+            app.hasShownUi = true;
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
                     System.identityHashCode(r),
                     r.info, r.compat, r.icicle, results, newIntents, !andResume,
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 9e597aa..5b59363 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -66,6 +66,7 @@
     boolean setIsForeground;    // Running foreground UI when last set?
     boolean foregroundServices; // Running any services that are foreground?
     boolean foregroundActivities; // Running any activities that are foreground?
+    boolean hasShownUi;         // Has UI been shown in this process since it was started?
     boolean bad;                // True if disabled in the bad process list
     boolean killedBackground;   // True when proc has been killed due to too many bg
     String waitingToKill;       // Process is waiting to be killed when in the bg; reason
@@ -185,6 +186,7 @@
         pw.print(prefix); pw.print("curSchedGroup="); pw.print(curSchedGroup);
                 pw.print(" setSchedGroup="); pw.print(setSchedGroup);
                 pw.print(" trimMemoryLevel="); pw.println(trimMemoryLevel);
+                pw.print(" hasShownUi="); pw.println(hasShownUi);
         pw.print(prefix); pw.print("setIsForeground="); pw.print(setIsForeground);
                 pw.print(" foregroundServices="); pw.print(foregroundServices);
                 pw.print(" forcingToForeground="); pw.println(forcingToForeground);
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index d7d4b03..82bc505 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -288,6 +288,8 @@
         }
     }
 
+    public void limitReached(String limitName, String iface) {}
+
     public int tether(String iface) {
         Log.d(TAG, "Tethering " + iface);
         TetherInterfaceSM sm = null;
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 05e95a7..cf75d6b 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -248,6 +248,8 @@
         }
     }
 
+    public void limitReached(String limitName, String iface) {}
+
     private void showNotification(VpnConfig config, String label, Bitmap icon) {
         NotificationManager nm = (NotificationManager)
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index c80cd0a..f183f83 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -19,6 +19,7 @@
 import android.app.PendingIntent;
 import android.app.Notification;
 import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -80,6 +81,7 @@
     private static final int MSG_ENABLE_ADB = 1;
     private static final int MSG_SET_CURRENT_FUNCTION = 2;
     private static final int MSG_SYSTEM_READY = 3;
+    private static final int MSG_BOOT_COMPLETED = 4;
 
     // Delay for debouncing USB disconnects.
     // We often get rapid connect/disconnect events when enabling USB functions,
@@ -87,7 +89,7 @@
     private static final int UPDATE_DELAY = 1000;
 
     private UsbHandler mHandler;
-    private boolean mSystemReady;
+    private boolean mBootCompleted;
 
     private final Context mContext;
     private final ContentResolver mContentResolver;
@@ -141,10 +143,15 @@
                 Process.THREAD_PRIORITY_BACKGROUND);
         thread.start();
         mHandler = new UsbHandler(thread.getLooper());
+
+        if (nativeIsStartRequested()) {
+            if (DEBUG) Slog.d(TAG, "accessory attached at boot");
+            setCurrentFunction(UsbManager.USB_FUNCTION_ACCESSORY, false);
+        }
     }
 
     public void systemReady() {
-        mSystemReady = true;
+        if (DEBUG) Slog.d(TAG, "systemReady");
 
         mNotificationManager = (NotificationManager)
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -236,15 +243,22 @@
         private String mCurrentFunctions;
         private String mDefaultFunctions;
         private UsbAccessory mCurrentAccessory;
-        private boolean mDeferAccessoryAttached;
         private int mUsbNotificationId;
         private boolean mAdbNotificationShown;
 
+        private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
+            public void onReceive(Context context, Intent intent) {
+                if (DEBUG) Slog.d(TAG, "boot completed");
+                mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
+            }
+        };
+
         private static final int NOTIFICATION_NONE = 0;
         private static final int NOTIFICATION_MTP = 1;
         private static final int NOTIFICATION_PTP = 2;
         private static final int NOTIFICATION_INSTALLER = 3;
-        private static final int NOTIFICATION_ADB = 4;
+        private static final int NOTIFICATION_ACCESSORY = 4;
+        private static final int NOTIFICATION_ADB = 5;
 
         public UsbHandler(Looper looper) {
             super(looper);
@@ -285,6 +299,9 @@
                 // Watch for USB configuration changes
                 mUEventObserver.startObserving(USB_STATE_MATCH);
                 mUEventObserver.startObserving(ACCESSORY_START_MATCH);
+
+                mContext.registerReceiver(mBootCompletedReceiver,
+                        new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
             } catch (Exception e) {
                 Slog.e(TAG, "Error initializing UsbHandler", e);
             }
@@ -406,11 +423,9 @@
                     mCurrentAccessory = new UsbAccessory(strings);
                     Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
                     // defer accessoryAttached if system is not ready
-                    if (mSystemReady) {
+                    if (mBootCompleted) {
                         mSettingsManager.accessoryAttached(mCurrentAccessory);
-                    } else {
-                        mDeferAccessoryAttached = true;
-                    }
+                    } // else handle in mBootCompletedReceiver
                 } else {
                     Slog.e(TAG, "nativeGetAccessoryStrings failed");
                 }
@@ -421,7 +436,7 @@
                 setEnabledFunctions(mDefaultFunctions);
 
                 if (mCurrentAccessory != null) {
-                    if (mSystemReady) {
+                    if (mBootCompleted) {
                         mSettingsManager.accessoryDetached(mCurrentAccessory);
                     }
                     mCurrentAccessory = null;
@@ -463,7 +478,7 @@
                         // restore defaults when USB is disconnected
                         doSetCurrentFunctions(mDefaultFunctions);
                     }
-                    if (mSystemReady) {
+                    if (mBootCompleted) {
                         updateUsbState();
                     }
                     break;
@@ -497,7 +512,10 @@
                     updateUsbNotification();
                     updateAdbNotification();
                     updateUsbState();
-                    if (mCurrentAccessory != null && mDeferAccessoryAttached) {
+                    break;
+                case MSG_BOOT_COMPLETED:
+                    mBootCompleted = true;
+                    if (mCurrentAccessory != null) {
                         mSettingsManager.accessoryAttached(mCurrentAccessory);
                     }
                     break;
@@ -527,6 +545,10 @@
                     title = r.getText(
                         com.android.internal.R.string.usb_cd_installer_notification_title);
                     id = NOTIFICATION_INSTALLER;
+                } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ACCESSORY)) {
+                    title = r.getText(
+                        com.android.internal.R.string.usb_accessory_notification_title);
+                    id = NOTIFICATION_ACCESSORY;
                 } else {
                     Slog.e(TAG, "No known USB function in updateUsbNotification");
                 }
@@ -671,4 +693,5 @@
 
     private native String[] nativeGetAccessoryStrings();
     private native ParcelFileDescriptor nativeOpenAccessory();
+    private native boolean nativeIsStartRequested();
 }
diff --git a/services/jni/com_android_server_UsbDeviceManager.cpp b/services/jni/com_android_server_UsbDeviceManager.cpp
index 6954171..40f0dbd 100644
--- a/services/jni/com_android_server_UsbDeviceManager.cpp
+++ b/services/jni/com_android_server_UsbDeviceManager.cpp
@@ -99,11 +99,26 @@
         gParcelFileDescriptorOffsets.mConstructor, fileDescriptor);
 }
 
+static jboolean android_server_UsbDeviceManager_isStartRequested(JNIEnv *env, jobject thiz)
+{
+    int fd = open(DRIVER_NAME, O_RDWR);
+    if (fd < 0) {
+        LOGE("could not open %s", DRIVER_NAME);
+        return false;
+    }
+    int result = ioctl(fd, ACCESSORY_IS_START_REQUESTED);
+    close(fd);
+    return (result == 1);
+}
+
+
 static JNINativeMethod method_table[] = {
     { "nativeGetAccessoryStrings",  "()[Ljava/lang/String;",
                                     (void*)android_server_UsbDeviceManager_getAccessoryStrings },
     { "nativeOpenAccessory",        "()Landroid/os/ParcelFileDescriptor;",
                                     (void*)android_server_UsbDeviceManager_openAccessory },
+    { "nativeIsStartRequested",     "()Z",
+                                    (void*)android_server_UsbDeviceManager_isStartRequested },
 };
 
 int register_android_server_UsbDeviceManager(JNIEnv *env)
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index 11f61cc..40659d4 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -60,6 +60,10 @@
 
     sp<Layer> layer(mLayer.promote());
     if (layer != NULL) {
+        uint32_t orientation = layer->getOrientation();
+        if (orientation & Transform::ROT_INVALID) {
+            orientation = 0;
+        }
         *outTransform = layer->getOrientation();
     }
 
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index 40a70a8..a0961ca 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -806,10 +806,10 @@
         mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
     }
 
-    public void notifyDataConnection() {
+    public void notifyDataConnection(String reason) {
         String types[] = getActiveApnTypes();
         for (String apnType : types) {
-            mNotifier.notifyDataConnection(this, null, apnType, getDataConnectionState(apnType));
+            mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
         }
     }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
index 0d551aa..5df2edd 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -134,8 +134,6 @@
                 }
             }
 
-            // Not sure if this is needed in CDMALTE phone.
-            // mDataRoaming = regCodeIsRoaming(regState);
             mLteSS.setRadioTechnology(type);
             mLteSS.setState(regCodeToServiceState(regState));
         } else {
@@ -345,13 +343,14 @@
             }
 
             if (cm.getSimState().isSIMReady()) {
-                // SIM is found on the device. If ERI roaming is OFF, use operator name
-                // from CSIM record.
+                // SIM is found on the device. If ERI roaming is OFF and SID/NID matches
+                // one configfured in SIM, use operator name from CSIM record.
                 boolean showSpn =
                     ((CdmaLteUiccRecords)phone.mIccRecords).getCsimSpnDisplayCondition();
                 int iconIndex = ss.getCdmaEriIconIndex();
 
-                if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF)) {
+                if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) &&
+                    isInHomeSidNid(ss.getSystemId(), ss.getNetworkId())) {
                     ss.setOperatorAlphaLong(phone.mIccRecords.getServiceProviderName());
                 }
             }
@@ -401,7 +400,7 @@
         }
 
         if ((hasCdmaDataConnectionChanged || hasNetworkTypeChanged)) {
-            phone.notifyDataConnection();
+            phone.notifyDataConnection(null);
         }
 
         if (hasRoamingOn) {
@@ -469,6 +468,34 @@
     }
 
     /**
+     * Check whether the specified SID and NID pair appears in the HOME SID/NID list
+     * read from NV or SIM.
+     *
+     * @return true if provided sid/nid pair belongs to operator's home network.
+     */
+    private boolean isInHomeSidNid(int sid, int nid) {
+        // if SID/NID is not available, assume this is home network.
+        if (isSidsAllZeros()) return true;
+
+        // length of SID/NID shold be same
+        if (mHomeSystemId.length != mHomeNetworkId.length) return true;
+
+        if (sid == 0) return true;
+
+        for (int i = 0; i < mHomeSystemId.length; i++) {
+            // Use SID only if NID is a reserved value.
+            // SID 0 and NID 0 and 65535 are reserved. (C.0005 2.6.5.2)
+            if ((mHomeSystemId[i] == sid) &&
+                ((mHomeNetworkId[i] == 0) || (mHomeNetworkId[i] == 65535) ||
+                 (nid == 0) || (nid == 65535) || (mHomeNetworkId[i] == nid))) {
+                return true;
+            }
+        }
+        // SID/NID are not in the list. So device is not in home network
+        return false;
+    }
+
+    /**
      * Returns OTASP_NOT_NEEDED as its not needed for LTE
      */
     @Override
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 24a468a..2cf4b88 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -130,8 +130,8 @@
     protected String mCurPlmn = null;
 
     protected String mMdn;
-    private int mHomeSystemId[] = null;
-    private int mHomeNetworkId[] = null;
+    protected int mHomeSystemId[] = null;
+    protected int mHomeNetworkId[] = null;
     protected String mMin;
     protected String mPrlVersion;
     protected boolean mIsMinInfoReady = false;
@@ -999,7 +999,7 @@
         }
 
         if (hasCdmaDataConnectionChanged || hasNetworkTypeChanged) {
-            phone.notifyDataConnection();
+            phone.notifyDataConnection(null);
         }
 
         if (hasRoamingOn) {
@@ -1481,7 +1481,7 @@
         }
     }
 
-    private boolean isSidsAllZeros() {
+    protected boolean isSidsAllZeros() {
         if (mHomeSystemId != null) {
             for (int i=0; i < mHomeSystemId.length; i++) {
                 if (mHomeSystemId[i] != 0) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 93f4b4e..d3645fa 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -915,7 +915,7 @@
         }
 
         if (hasRadioTechnologyChanged) {
-            phone.notifyDataConnection(Phone.REASON_NW_TYPE_CHANGED, Phone.APN_TYPE_ALL);
+            phone.notifyDataConnection(Phone.REASON_NW_TYPE_CHANGED);
         }
 
         if (hasRoamingOn) {
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
index 1493ab9..13b6129 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
@@ -93,12 +93,9 @@
     }
     
     public void startProfiling(View v) {
-        ViewDebug.startLooperProfiling(new File(Environment.getExternalStorageDirectory(),
-                "looper.trace"));
     }
     
     public void stopProfiling(View v) {
-        ViewDebug.stopLooperProfiling();
     }
 
     @Override
diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
index b212533..e75a079 100644
--- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
@@ -100,22 +100,22 @@
         new Test("Double Remove") {
             public void run() {
                 Log.d(TAG, "set 0");
-                mStatusBarManager.setIcon("speakerphone", R.drawable.stat_sys_phone, 0);
+                mStatusBarManager.setIcon("speakerphone", R.drawable.stat_sys_phone, 0, null);
                 Log.d(TAG, "remove 1");
                 mStatusBarManager.removeIcon("tty");
 
                 SystemClock.sleep(1000);
 
                 Log.d(TAG, "set 1");
-                mStatusBarManager.setIcon("tty", R.drawable.stat_sys_phone, 0);
+                mStatusBarManager.setIcon("tty", R.drawable.stat_sys_phone, 0, null);
                 if (false) {
                     Log.d(TAG, "set 2");
-                    mStatusBarManager.setIcon("tty", R.drawable.stat_sys_phone, 0);
+                    mStatusBarManager.setIcon("tty", R.drawable.stat_sys_phone, 0, null);
                 }
                 Log.d(TAG, "remove 2");
                 mStatusBarManager.removeIcon("tty");
                 Log.d(TAG, "set 3");
-                mStatusBarManager.setIcon("speakerphone", R.drawable.stat_sys_phone, 0);
+                mStatusBarManager.setIcon("speakerphone", R.drawable.stat_sys_phone, 0, null);
             }
         },
         new Test("Hide (FLAG_FULLSCREEN)") {
diff --git a/tests/TileBenchmark/AndroidManifest.xml b/tests/TileBenchmark/AndroidManifest.xml
index 663cc0d..ab61a9e 100644
--- a/tests/TileBenchmark/AndroidManifest.xml
+++ b/tests/TileBenchmark/AndroidManifest.xml
@@ -7,14 +7,16 @@
                  android:label="@string/app_name"
                  android:hardwareAccelerated="true">
         <activity android:name=".ProfileActivity"
-                  android:label="@string/profile_activity">
+                  android:label="@string/profile_activity"
+                  android:theme="@android:style/Theme.Holo.NoActionBar">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
         <activity android:name=".PlaybackActivity"
-                  android:label="@string/playback_activity">
+                  android:label="@string/playback_activity"
+                  android:theme="@android:style/Theme.Holo.NoActionBar">
         </activity>
     </application>
 </manifest>
diff --git a/tests/TileBenchmark/res/layout/main.xml b/tests/TileBenchmark/res/layout/main.xml
index 4a81da6..577c466 100644
--- a/tests/TileBenchmark/res/layout/main.xml
+++ b/tests/TileBenchmark/res/layout/main.xml
@@ -23,11 +23,11 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         >
-        <Button
-            android:id="@+id/inspect"
+        <Spinner
+            android:id="@+id/movement"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:text="@string/inspect_log"
+            android:prompt="@string/movement_method"
             />
         <Spinner
             android:id="@+id/velocity"
@@ -36,6 +36,13 @@
             android:gravity="center_horizontal"
             android:prompt="@string/desired_scroll_velocity"
             />
+        <ToggleButton
+            android:id="@+id/capture"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textOn="@string/capture_stop"
+            android:textOff="@string/capture_start"
+            />
         <EditText
             android:id="@+id/url"
             android:layout_width="0dip"
@@ -44,6 +51,12 @@
             android:imeOptions="actionGo"
             android:layout_weight="1"
             />
+        <Button
+            android:id="@+id/inspect"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/inspect_log"
+            />
     </LinearLayout>
     <com.test.tilebenchmark.ProfiledWebView
         android:id="@+id/web"
diff --git a/tests/TileBenchmark/res/values/colors.xml b/tests/TileBenchmark/res/values/colors.xml
index 3958083..dbb8e72 100644
--- a/tests/TileBenchmark/res/values/colors.xml
+++ b/tests/TileBenchmark/res/values/colors.xml
@@ -18,8 +18,17 @@
     <color name="ready_tile">#ff4ac230</color>
     <!-- The color of tiles with stale / invalid textures -->
     <color name="unready_tile">#ff744400</color>
-    <!-- Background color for logged URLs -->
-    <color name="finished_url">#ff004000</color>
-    <!-- Background color for URLs with logging in progress -->
-    <color name="unfinished_url">#ff400000</color>
+    <!-- Viewport overlay in playback -->
+    <color name="view">#50000050</color>
+    <!-- Invalidated region overlay in playback - start color -->
+    <color name="inval_region_start">#80ff0000</color>
+    <!-- Invalidated region overlay in playback - stop color-->
+    <color name="inval_region_stop">#80ffffff</color>
+
+    <!-- Background color for not testing -->
+    <color name="background_not_testing">#ff000000</color>
+    <!-- Background color for during testing -->
+    <color name="background_start_testing">#ff400000</color>
+    <!-- Background color for testing complete -->
+    <color name="background_stop_testing">#ff004000</color>
 </resources>
diff --git a/tests/TileBenchmark/res/values/strings.xml b/tests/TileBenchmark/res/values/strings.xml
index f70ee2c..66972ac 100644
--- a/tests/TileBenchmark/res/values/strings.xml
+++ b/tests/TileBenchmark/res/values/strings.xml
@@ -28,6 +28,10 @@
     <string name="loadbutton">Load</string>
     <!-- Button, opens the playback activity [CHAR LIMIT=20] -->
     <string name="inspect_log">Inspect Log</string>
+    <!-- ToggleButton label when pressing starts capture [CHAR LIMIT=15] -->
+    <string name="capture_start">Start Capture</string>
+    <!-- ToggleButton label when pressing stops capture [CHAR LIMIT=15] -->
+    <string name="capture_stop">Stop Capture</string>
     <!-- The speed of auto-scrolling [CHAR LIMIT=30] -->
     <string name="desired_scroll_velocity">Choose Scroll Velocity</string>
     <!-- Pixels moved per frame [CHAR LIMIT=10] -->
@@ -39,6 +43,21 @@
         <item>200</item>
         <item>400</item>
     </string-array>
+    <!-- Drop down menu for selecting scrolling vs manual navigation for
+    capturing [CHAR LIMIT=15] -->
+    <string name="movement_method">Movement Method</string>
+    <!-- Drop down menu entry - automatically scroll to the end of the page
+    with scrollBy() [CHAR LIMIT=15] -->
+    <string name="movement_auto_scroll">Auto-scroll</string>
+    <!-- Drop down menu entry -  [CHAR LIMIT=15] -->
+    <string name="movement_auto_fling">Auto-fling</string>
+    <!-- Drop down menu entry - manually navigate the page(s), hit 'capture'
+    button [CHAR LIMIT=15] -->
+    <string name="movement_manual">Manual</string>
+
+    <!-- Error popup indicating log data couldn't be loaded [CHAR LIMIT=60] -->
+    <string name="error_no_data">Error: log data could not be loaded.</string>
+
     <!-- 25th percentile - 25% of frames fall below this value [CHAR LIMIT=12]
     -->
     <string name="percentile_25">25%ile</string>
@@ -56,7 +75,7 @@
     <string name="format_stat">%4.4f</string>
     <!-- Format string for displaying aggregate stats+values (nr of valid tiles,
     etc.) [CHAR LIMIT=20] -->
-    <string name="format_stat_name">%1$9s %2$3d</string>
+    <string name="format_stat_name">%1$-20s %2$3d</string>
     <!-- Text hovering over canvas, number of tiles ready [CHAR LIMIT=15] -->
     <string name="ready_tiles">Ready Tiles</string>
     <!-- Text hovering over canvas, number tiles not ready [CHAR LIMIT=15] -->
@@ -64,4 +83,7 @@
     <!-- Text hovering over canvas, number of tiles that haven't been
     allocated to a place on the page [CHAR LIMIT=15] -->
     <string name="unplaced_tiles">Unplaced Tiles</string>
+    <!-- Text hovering over canvas, number of invalidated regions this frame
+    [CHAR LIMIT=15] -->
+    <string name="number_invalidates">Invalidates</string>
 </resources>
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java
index 5130f5d..36694a7 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java
@@ -27,6 +27,7 @@
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
 import android.widget.TextView;
+import android.widget.Toast;
 
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -102,7 +103,10 @@
         @Override
         protected void onPostExecute(TileData data[][]) {
             if (data == null) {
-                data = genTestPattern();
+                Toast.makeText(getApplicationContext(),
+                        getResources().getString(R.string.error_no_data),
+                        Toast.LENGTH_LONG).show();
+                return;
             }
             mPlaybackView.setData(data);
 
@@ -166,23 +170,4 @@
 
         new LoadFileTask().execute(ProfileActivity.TEMP_FILENAME);
     }
-
-    private TileData[][] genTestPattern() {
-        final int XMAX = 5;
-        final int FRAMEMAX = 99;
-
-        TileData example[][] = new TileData[FRAMEMAX][];
-        for (int frame = 0; frame < FRAMEMAX; frame++) {
-            int numTiles = frame + 10;
-
-            example[frame] = new TileData[numTiles];
-            for (int t = 0; t < numTiles; t++) {
-                int x = t % XMAX;
-                int y = t / XMAX;
-                boolean isReady = y * 10 < frame;
-                example[frame][t] = new TileData(x, y, isReady, 0);
-            }
-        }
-        return example;
-    }
 }
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java
index db4a341..35b1563 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java
@@ -28,19 +28,17 @@
 import java.util.Arrays;
 
 public class PlaybackGraphs {
-    private static final int BAR_WIDTH = PlaybackView.TILEX * 3;
+    private static final int BAR_WIDTH = PlaybackView.TILE_SCALE * 3;
     private static final float CANVAS_SCALE = 0.2f;
     private static final double IDEAL_FRAMES = 60;
     private static final int LABELOFFSET = 100;
     private static Paint whiteLabels;
 
-    private static double viewportCoverage(int l, int b, int r, int t,
-            int tileIndexX,
-            int tileIndexY) {
-        if (tileIndexX * PlaybackView.TILEX < r
-                && (tileIndexX + 1) * PlaybackView.TILEX >= l
-                && tileIndexY * PlaybackView.TILEY < t
-                && (tileIndexY + 1) * PlaybackView.TILEY >= b) {
+    private static double viewportCoverage(TileData view, TileData tile) {
+        if (tile.left < view.right
+                && tile.right >= view.left
+                && tile.top < view.bottom
+                && tile.bottom >= view.top) {
             return 1.0f;
         }
         return 0.0f;
@@ -76,13 +74,10 @@
                 // coverage graph
                 @Override
                 public double getValue(TileData[] frame) {
-                    int l = frame[0].x, b = frame[0].y;
-                    int r = frame[1].x, t = frame[1].y;
                     double total = 0, totalCount = 0;
-                    for (int tileID = 2; tileID < frame.length; tileID++) {
+                    for (int tileID = 1; tileID < frame.length; tileID++) {
                         TileData data = frame[tileID];
-                        double coverage = viewportCoverage(l, b, r, t, data.x,
-                                data.y);
+                        double coverage = viewportCoverage(frame[0], data);
                         total += coverage * (data.isReady ? 1 : 0);
                         totalCount += coverage;
                     }
@@ -158,7 +153,7 @@
     public PlaybackGraphs() {
         whiteLabels = new Paint();
         whiteLabels.setColor(Color.WHITE);
-        whiteLabels.setTextSize(PlaybackView.TILEY / 3);
+        whiteLabels.setTextSize(PlaybackView.TILE_SCALE / 3);
     }
 
     private ArrayList<ShapeDrawable> mShapes = new ArrayList<ShapeDrawable>();
@@ -177,11 +172,13 @@
             int lastBar = 0;
             for (int frameIndex = 0; frameIndex < tileProfilingData.length; frameIndex++) {
                 TileData frame[] = tileProfilingData[frameIndex];
-                int newBar = (frame[0].y + frame[1].y) / 2;
+                int newBar = (frame[0].top + frame[0].bottom) / 2;
 
                 MetricGen s = Metrics[metricIndex];
                 double absoluteValue = s.getValue(frame);
                 double relativeValue = absoluteValue / s.getMax();
+                relativeValue = Math.min(1,relativeValue);
+                relativeValue = Math.max(0,relativeValue);
                 int rightPos = (int) (-BAR_WIDTH * metricIndex);
                 int leftPos = (int) (-BAR_WIDTH * (metricIndex + relativeValue));
 
@@ -207,7 +204,7 @@
             ArrayList<ShapeDrawable> shapes) {
         // Shapes drawn here are drawn relative to the viewRect
         Rect viewRect = shapes.get(shapes.size() - 1).getBounds();
-        canvas.translate(0, 5 * PlaybackView.TILEY - viewRect.top);
+        canvas.translate(0, 5 * PlaybackView.TILE_SCALE - viewRect.top);
 
         for (ShapeDrawable shape : mShapes) {
             shape.draw(canvas);
@@ -234,13 +231,15 @@
             int yPos = LABELOFFSET;
             canvas.drawText(label, xPos, yPos, whiteLabels);
             for (int statIndex = 0; statIndex < Stats.length; statIndex++) {
-                label = resources.getString(R.string.format_stat, mStats[metricIndex][statIndex]);
-                yPos = LABELOFFSET + (1 + statIndex) * PlaybackView.TILEY / 2;
+                label = resources.getString(R.string.format_stat,
+                        mStats[metricIndex][statIndex]);
+                yPos = LABELOFFSET + (1 + statIndex) * PlaybackView.TILE_SCALE
+                        / 2;
                 canvas.drawText(label, xPos, yPos, whiteLabels);
             }
         }
         for (int stringIndex = 0; stringIndex < strings.length; stringIndex++) {
-            int yPos = LABELOFFSET + stringIndex * PlaybackView.TILEY / 2;
+            int yPos = LABELOFFSET + stringIndex * PlaybackView.TILE_SCALE / 2;
             canvas.drawText(strings[stringIndex], 0, yPos, whiteLabels);
         }
     }
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java
index f104eac..edc8643 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java
@@ -16,6 +16,9 @@
 
 package com.test.tilebenchmark;
 
+import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -30,8 +33,9 @@
 import java.util.ArrayList;
 
 public class PlaybackView extends View {
-    public static final int TILEX = 300;
-    public static final int TILEY = 300;
+    public static final int TILE_SCALE = 300;
+    private static final int INVAL_FLAG = -2;
+    private static final int INVAL_CYCLE = 250;
 
     private Paint levelPaint = null, coordPaint = null, goldPaint = null;
     private PlaybackGraphs mGraphs;
@@ -39,28 +43,46 @@
     private ArrayList<ShapeDrawable> mTempShapes = new ArrayList<ShapeDrawable>();
     private TileData mProfData[][] = null;
     private GestureDetector mGestureDetector = null;
-    private String mRenderStrings[] = new String[3];
+    private String mRenderStrings[] = new String[4];
 
     private class TileDrawable extends ShapeDrawable {
         TileData tile;
+        String label;
 
-        public TileDrawable(TileData t) {
-            int tileColorId = t.isReady ? R.color.ready_tile
-                    : R.color.unready_tile;
-            getPaint().setColor(getResources().getColor(tileColorId));
-
-            setBounds(t.x * TILEX, t.y * TILEY, (t.x + 1) * TILEX, (t.y + 1)
-                    * TILEY);
+        public TileDrawable(TileData t, int colorId) {
             this.tile = t;
+            getPaint().setColor(getResources().getColor(colorId));
+            if (colorId == R.color.ready_tile
+                    || colorId == R.color.unready_tile) {
+
+                label = (int) (t.left / TILE_SCALE) + ", "
+                        + (int) (t.top / TILE_SCALE);
+                // ignore scale value for tiles
+                setBounds(t.left, t.top,
+                        t.right, t.bottom);
+            } else {
+                setBounds((int) (t.left * t.scale),
+                        (int) (t.top * t.scale),
+                        (int) (t.right * t.scale),
+                        (int) (t.bottom * t.scale));
+            }
+        }
+
+        @SuppressWarnings("unused")
+        public void setColor(int color) {
+            getPaint().setColor(color);
         }
 
         @Override
         public void draw(Canvas canvas) {
             super.draw(canvas);
-            canvas.drawText(Integer.toString(tile.level), getBounds().left,
-                    getBounds().bottom, levelPaint);
-            canvas.drawText(tile.x + "," + tile.y, getBounds().left,
-                    ((getBounds().bottom + getBounds().top) / 2), coordPaint);
+            if (label != null) {
+                canvas.drawText(Integer.toString(tile.level), getBounds().left,
+                        getBounds().bottom, levelPaint);
+                canvas.drawText(label, getBounds().left,
+                        ((getBounds().bottom + getBounds().top) / 2),
+                        coordPaint);
+            }
         }
     }
 
@@ -92,10 +114,10 @@
     private void init() {
         levelPaint = new Paint();
         levelPaint.setColor(Color.WHITE);
-        levelPaint.setTextSize(TILEY / 2);
+        levelPaint.setTextSize(TILE_SCALE / 2);
         coordPaint = new Paint();
         coordPaint.setColor(Color.BLACK);
-        coordPaint.setTextSize(TILEY / 3);
+        coordPaint.setTextSize(TILE_SCALE / 3);
         goldPaint = new Paint();
         goldPaint.setColor(0xffa0e010);
         mGraphs = new PlaybackGraphs();
@@ -110,6 +132,7 @@
         }
 
         mGraphs.draw(canvas, mTempShapes, mRenderStrings, getResources());
+        invalidate(); // may have animations, force redraw
     }
 
     public int setFrame(int frame) {
@@ -117,35 +140,66 @@
             return 0;
         }
 
-        int readyTiles = 0, unreadyTiles = 0, unplacedTiles = 0;
+        int readyTiles = 0, unreadyTiles = 0, unplacedTiles = 0, numInvals = 0;
         mTempShapes.clear();
 
-        // draw actual tiles
-        for (int tileID = 2; tileID < mProfData[frame].length; tileID++) {
-            TileData t = mProfData[frame][tileID];
-            mTempShapes.add(new TileDrawable(t));
-            if (t.isReady) {
-                readyTiles++;
+        // create tile shapes (as they're drawn on bottom)
+        for (TileData t : mProfData[frame]) {
+            if (t.level != INVAL_FLAG && t != mProfData[frame][0]) {
+                int colorId;
+                if (t.isReady) {
+                    readyTiles++;
+                    colorId = R.color.ready_tile;
+                } else {
+                    unreadyTiles++;
+                    colorId = R.color.unready_tile;
+                }
+                if (t.left < 0 || t.top < 0) {
+                    unplacedTiles++;
+                }
+                mTempShapes.add(new TileDrawable(t, colorId));
             } else {
-                unreadyTiles++;
-            }
-            if (t.x < 0 || t.y < 0) {
-                unplacedTiles++;
+                numInvals++;
             }
         }
+
+        // create invalidate shapes (drawn above tiles)
+        int invalId = 0;
+        for (TileData t : mProfData[frame]) {
+            if (t.level == INVAL_FLAG && t != mProfData[frame][0]) {
+                TileDrawable invalShape = new TileDrawable(t,
+                        R.color.inval_region_start);
+                ValueAnimator tileAnimator = ObjectAnimator.ofInt(invalShape,
+                        "color",
+                        getResources().getColor(R.color.inval_region_start),
+                        getResources().getColor(R.color.inval_region_stop));
+                tileAnimator.setDuration(numInvals * INVAL_CYCLE);
+                tileAnimator.setEvaluator(new ArgbEvaluator());
+                tileAnimator.setRepeatCount(ValueAnimator.INFINITE);
+                tileAnimator.setRepeatMode(ValueAnimator.RESTART);
+                float delay = (float) (invalId) * INVAL_CYCLE;
+                tileAnimator.setStartDelay((int) delay);
+                invalId++;
+                tileAnimator.start();
+
+                mTempShapes.add(invalShape);
+            }
+        }
+
         mRenderStrings[0] = getResources().getString(R.string.format_stat_name,
                 getResources().getString(R.string.ready_tiles), readyTiles);
         mRenderStrings[1] = getResources().getString(R.string.format_stat_name,
                 getResources().getString(R.string.unready_tiles), unreadyTiles);
         mRenderStrings[2] = getResources().getString(R.string.format_stat_name,
-                getResources().getString(R.string.unplaced_tiles), unplacedTiles);
+                getResources().getString(R.string.unplaced_tiles),
+                unplacedTiles);
+        mRenderStrings[3] = getResources().getString(R.string.format_stat_name,
+                getResources().getString(R.string.number_invalidates),
+                numInvals);
 
-        // draw view rect (using first two TileData objects)
-        ShapeDrawable viewShape = new ShapeDrawable();
-        viewShape.getPaint().setColor(0xff0000ff);
-        viewShape.setAlpha(64);
-        viewShape.setBounds(mProfData[frame][0].x, mProfData[frame][0].y,
-                mProfData[frame][1].x, mProfData[frame][1].y);
+        // draw view rect (using first TileData object, on top)
+        TileDrawable viewShape = new TileDrawable(mProfData[frame][0],
+                R.color.view);
         mTempShapes.add(viewShape);
         this.invalidate();
         return frame;
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java
index 23b6275..1521807 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java
@@ -38,6 +38,7 @@
 import android.widget.Spinner;
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
+import android.widget.ToggleButton;
 
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -58,11 +59,24 @@
                                                      // before test
 
     Button mInspectButton;
+    ToggleButton mCaptureButton;
     Spinner mVelocitySpinner;
+    Spinner mMovementSpinner;
     EditText mUrl;
     ProfiledWebView mWeb;
     ProfileCallback mCallback;
 
+    LoggingWebViewClient mLoggingWebViewClient = new LoggingWebViewClient();
+    AutoLoggingWebViewClient mAutoLoggingWebViewClient = new AutoLoggingWebViewClient();
+
+    private enum TestingState {
+        NOT_TESTING,
+        PRE_TESTING,
+        START_TESTING,
+        STOP_TESTING,
+        SAVED_TESTING
+    };
+
     private class VelocitySelectedListener implements OnItemSelectedListener {
         @Override
         public void onItemSelected(AdapterView<?> parent, View view,
@@ -77,6 +91,31 @@
         }
     }
 
+    private class MovementSelectedListener implements OnItemSelectedListener {
+        @Override
+        public void onItemSelected(AdapterView<?> parent, View view,
+                int position, long id) {
+            String movementStr = parent.getItemAtPosition(position).toString();
+            if (movementStr == getResources().getString(
+                    R.string.movement_auto_scroll)
+                    || movementStr == getResources().getString(
+                            R.string.movement_auto_fling)) {
+                mWeb.setWebViewClient(mAutoLoggingWebViewClient);
+                mCaptureButton.setEnabled(false);
+                mVelocitySpinner.setEnabled(true);
+            } else if (movementStr == getResources().getString(
+                    R.string.movement_manual)) {
+                mWeb.setWebViewClient(mLoggingWebViewClient);
+                mCaptureButton.setEnabled(true);
+                mVelocitySpinner.setEnabled(false);
+            }
+        }
+
+        @Override
+        public void onNothingSelected(AdapterView<?> parent) {
+        }
+    }
+
     private class LoggingWebViewClient extends WebViewClient {
         @Override
         public boolean shouldOverrideUrlLoading(WebView view, String url) {
@@ -88,6 +127,9 @@
             super.onPageStarted(view, url, favicon);
             mUrl.setText(url);
         }
+    }
+
+    private class AutoLoggingWebViewClient extends LoggingWebViewClient {
 
         @Override
         public void onPageFinished(WebView view, String url) {
@@ -100,10 +142,16 @@
 
                 @Override
                 public void onFinish() {
-                    mWeb.startScrollTest(mCallback);
+                    startViewProfiling(true);
                 }
             }.start();
         }
+
+        @Override
+        public void onPageStarted(WebView view, String url, Bitmap favicon) {
+            super.onPageStarted(view, url, favicon);
+            setTestingState(TestingState.PRE_TESTING);
+        }
     }
 
     private class StoreFileTask extends
@@ -125,24 +173,65 @@
 
         @Override
         protected void onPostExecute(Void v) {
-            mUrl.setBackgroundResource(R.color.finished_url);
+            setTestingState(TestingState.SAVED_TESTING);
         }
     }
 
+    public void setTestingState(TestingState state) {
+        switch (state) {
+            case NOT_TESTING:
+                mUrl.setBackgroundResource(R.color.background_not_testing);
+                mInspectButton.setEnabled(true);
+                mMovementSpinner.setEnabled(true);
+                break;
+            case PRE_TESTING:
+                mInspectButton.setEnabled(false);
+                mMovementSpinner.setEnabled(false);
+                break;
+            case START_TESTING:
+                mUrl.setBackgroundResource(R.color.background_start_testing);
+                mInspectButton.setEnabled(false);
+                mMovementSpinner.setEnabled(false);
+                break;
+            case STOP_TESTING:
+                mUrl.setBackgroundResource(R.color.background_stop_testing);
+                break;
+            case SAVED_TESTING:
+                mInspectButton.setEnabled(true);
+                mMovementSpinner.setEnabled(true);
+                break;
+        }
+    }
+
+    /** auto - automatically scroll. */
+    private void startViewProfiling(boolean auto) {
+        if (!auto) {
+            // manual, toggle capture button to indicate capture state to user
+            mCaptureButton.setChecked(true);
+        }
+        mWeb.startScrollTest(mCallback, auto);
+        setTestingState(TestingState.START_TESTING);
+    }
+
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
         mInspectButton = (Button) findViewById(R.id.inspect);
+        mCaptureButton = (ToggleButton) findViewById(R.id.capture);
         mVelocitySpinner = (Spinner) findViewById(R.id.velocity);
+        mMovementSpinner = (Spinner) findViewById(R.id.movement);
         mUrl = (EditText) findViewById(R.id.url);
         mWeb = (ProfiledWebView) findViewById(R.id.web);
         mCallback = new ProfileCallback() {
             @SuppressWarnings("unchecked")
             @Override
             public void profileCallback(TileData[][] data) {
-                new StoreFileTask().execute(new Pair<String, TileData[][]>(TEMP_FILENAME, data));
+                new StoreFileTask().execute(new Pair<String, TileData[][]>(
+                        TEMP_FILENAME, data));
+                mCaptureButton.setChecked(false);
+                setTestingState(TestingState.STOP_TESTING);
             }
         };
 
@@ -166,6 +255,33 @@
                 new VelocitySelectedListener());
         mVelocitySpinner.setSelection(3);
 
+        // Movement spinner
+        String content[] = {
+                getResources().getString(R.string.movement_auto_scroll),
+                getResources().getString(R.string.movement_auto_fling),
+                getResources().getString(R.string.movement_manual)
+        };
+        adapter = new ArrayAdapter<CharSequence>(this,
+                android.R.layout.simple_spinner_item, content);
+        adapter.setDropDownViewResource(
+                android.R.layout.simple_spinner_dropdown_item);
+        mMovementSpinner.setAdapter(adapter);
+        mMovementSpinner.setOnItemSelectedListener(
+                new MovementSelectedListener());
+        mMovementSpinner.setSelection(0);
+
+        // Capture toggle button
+        mCaptureButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mCaptureButton.isChecked()) {
+                    startViewProfiling(false);
+                } else {
+                    mWeb.stopScrollTest();
+                }
+            }
+        });
+
         // Custom profiling WebView
         WebSettings settings = mWeb.getSettings();
         settings.setJavaScriptEnabled(true);
@@ -180,12 +296,13 @@
             public boolean onEditorAction(TextView v, int actionId,
                     KeyEvent event) {
                 String url = mUrl.getText().toString();
-                mUrl.setBackgroundResource(R.color.unfinished_url);
                 mWeb.loadUrl(url);
                 mWeb.requestFocus();
                 return true;
             }
         });
+
+        setTestingState(TestingState.NOT_TESTING);
     }
 
     public void setCallback(ProfileCallback callback) {
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
index 6560624..d3941be 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
@@ -59,12 +59,13 @@
     }
 
     /*
-     * Called once the page is loaded to start scrolling for evaluating tiles
+     * Called once the page is loaded to start scrolling for evaluating tiles.
+     * If autoScrolling isn't set, stop must be called manually.
      */
-    public void startScrollTest(ProfileCallback callback) {
-        isScrolling = true;
+    public void startScrollTest(ProfileCallback callback, boolean autoScrolling) {
+        isScrolling = autoScrolling;
         mCallback = callback;
-        super.tileProfilingStart();
+        tileProfilingStart();
         invalidate();
     }
 
@@ -72,19 +73,31 @@
      * Called once the page has stopped scrolling
      */
     public void stopScrollTest() {
-        float testRatio = super.tileProfilingStop();
+        super.tileProfilingStop();
+
+        if (mCallback == null) {
+            tileProfilingClear();
+            return;
+        }
 
         TileData data[][] = new TileData[super.tileProfilingNumFrames()][];
         for (int frame = 0; frame < data.length; frame++) {
             data[frame] = new TileData[
-                    super.tileProfilingNumTilesInFrame(frame)];
+                    tileProfilingNumTilesInFrame(frame)];
             for (int tile = 0; tile < data[frame].length; tile++) {
-                int x = super.tileProfilingGetX(frame, tile);
-                int y = super.tileProfilingGetY(frame, tile);
-                boolean isReady = super.tileProfilingGetReady(frame, tile);
-                int level = super.tileProfilingGetLevel(frame, tile);
+                int left = tileProfilingGetInt(frame, tile, "left");
+                int top = tileProfilingGetInt(frame, tile, "top");
+                int right = tileProfilingGetInt(frame, tile, "right");
+                int bottom = tileProfilingGetInt(frame, tile, "bottom");
 
-                data[frame][tile] = new TileData(x, y, isReady, level);
+                boolean isReady = super.tileProfilingGetInt(
+                        frame, tile, "isReady") == 1;
+                int level = tileProfilingGetInt(frame, tile, "level");
+
+                float scale = tileProfilingGetFloat(frame, tile, "scale");
+
+                data[frame][tile] = new TileData(left, top, right, bottom,
+                        isReady, level, scale);
             }
         }
         super.tileProfilingClear();
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java b/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java
index 7d4bb9f..3e729a6 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java
@@ -19,14 +19,24 @@
 import java.io.Serializable;
 
 public class TileData implements Serializable {
-    public int x, y;
+    int left, top, right, bottom;
     public boolean isReady;
     public int level;
+    public float scale;
 
-    public TileData(int x, int y, boolean isReady, int level) {
-        this.x = x;
-        this.y = y;
+    public TileData(int left, int top, int right, int bottom, boolean isReady,
+            int level, float scale) {
+        this.left = left;
+        this.right = right;
+        this.top = top;
+        this.bottom = bottom;
         this.isReady = isReady;
         this.level = level;
+        this.scale = scale;
+    }
+
+    public String toString() {
+        return "Tile (" + left + "," + top + ")->("
+                + right + "," + bottom + ")";
     }
 }
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 6e13d0f..f1f0fcc 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -104,18 +104,30 @@
 
     public native static boolean stopDriverCommand();
 
-    /**
-     * Start filtering out multicast packets, to reduce battery consumption
-     * that would result from processing them, only to discard them.
-     * @return {@code true} if the operation succeeded, {@code false} otherwise
-     */
-    public native static boolean startPacketFiltering();
 
     /**
-     * Stop filtering out multicast packets.
+     * Start filtering out Multicast V4 packets
      * @return {@code true} if the operation succeeded, {@code false} otherwise
      */
-    public native static boolean stopPacketFiltering();
+    public native static boolean startFilteringMulticastV4Packets();
+
+    /**
+     * Stop filtering out Multicast V4 packets.
+     * @return {@code true} if the operation succeeded, {@code false} otherwise
+     */
+    public native static boolean stopFilteringMulticastV4Packets();
+
+    /**
+     * Start filtering out Multicast V6 packets
+     * @return {@code true} if the operation succeeded, {@code false} otherwise
+     */
+    public native static boolean startFilteringMulticastV6Packets();
+
+    /**
+     * Stop filtering out Multicast V6 packets.
+     * @return {@code true} if the operation succeeded, {@code false} otherwise
+     */
+    public native static boolean stopFilteringMulticastV6Packets();
 
     public native static boolean setPowerModeCommand(int mode);
 
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 12efeb1..f08bb6a 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -82,6 +82,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.regex.Pattern;
 
 /**
@@ -160,6 +161,9 @@
     /* Tracks current frequency mode */
     private AtomicInteger mFrequencyBand = new AtomicInteger(WifiManager.WIFI_FREQUENCY_BAND_AUTO);
 
+    /* Tracks if we are filtering Multicast v4 packets. Default is to filter. */
+    private AtomicBoolean mFilteringMulticastV4Packets = new AtomicBoolean(true);
+
     // Channel for sending replies.
     private AsyncChannel mReplyChannel = new AsyncChannel();
 
@@ -285,6 +289,11 @@
     static final int CMD_START_PACKET_FILTERING           = BASE + 84;
     /* Clear packet filter */
     static final int CMD_STOP_PACKET_FILTERING            = BASE + 85;
+
+    /* arg1 values to CMD_STOP_PACKET_FILTERING and CMD_START_PACKET_FILTERING */
+    static final int MULTICAST_V6  = 1;
+    static final int MULTICAST_V4  = 0;
+
     /* Connect to a specified network (network id
      * or WifiConfiguration) This involves increasing
      * the priority of the network, enabling the network
@@ -868,17 +877,33 @@
     }
 
     /**
-     * Start packet filtering
+     * Start filtering Multicast v4 packets
      */
-    public void startPacketFiltering() {
-        sendMessage(CMD_START_PACKET_FILTERING);
+    public void startFilteringMulticastV4Packets() {
+        mFilteringMulticastV4Packets.set(true);
+        sendMessage(obtainMessage(CMD_START_PACKET_FILTERING, MULTICAST_V4, 0));
     }
 
     /**
-     * Stop packet filtering
+     * Stop filtering Multicast v4 packets
      */
-    public void stopPacketFiltering() {
-        sendMessage(CMD_STOP_PACKET_FILTERING);
+    public void stopFilteringMulticastV4Packets() {
+        mFilteringMulticastV4Packets.set(false);
+        sendMessage(obtainMessage(CMD_STOP_PACKET_FILTERING, MULTICAST_V4, 0));
+    }
+
+    /**
+     * Start filtering Multicast v4 packets
+     */
+    public void startFilteringMulticastV6Packets() {
+        sendMessage(obtainMessage(CMD_START_PACKET_FILTERING, MULTICAST_V6, 0));
+    }
+
+    /**
+     * Stop filtering Multicast v4 packets
+     */
+    public void stopFilteringMulticastV6Packets() {
+        sendMessage(obtainMessage(CMD_STOP_PACKET_FILTERING, MULTICAST_V6, 0));
     }
 
     /**
@@ -2074,9 +2099,6 @@
 
                     WifiConfigStore.initialize(mContext);
 
-                    //TODO: initialize and fix multicast filtering
-                    //mWM.initializeMulticastFiltering();
-
                     sendSupplicantConnectionChangedBroadcast(true);
                     transitionTo(mDriverStartedState);
                     break;
@@ -2359,6 +2381,16 @@
             /* initialize network state */
             setNetworkDetailedState(DetailedState.DISCONNECTED);
 
+            /* Remove any filtering on Multicast v6 at start */
+            WifiNative.stopFilteringMulticastV6Packets();
+
+            /* Reset Multicast v4 filtering state */
+            if (mFilteringMulticastV4Packets.get()) {
+                WifiNative.startFilteringMulticastV4Packets();
+            } else {
+                WifiNative.stopFilteringMulticastV4Packets();
+            }
+
             if (mIsScanMode) {
                 WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE);
                 WifiNative.disconnectCommand();
@@ -2419,10 +2451,22 @@
                     mWakeLock.release();
                     break;
                 case CMD_START_PACKET_FILTERING:
-                    WifiNative.startPacketFiltering();
+                    if (message.arg1 == MULTICAST_V6) {
+                        WifiNative.startFilteringMulticastV6Packets();
+                    } else if (message.arg1 == MULTICAST_V4) {
+                        WifiNative.startFilteringMulticastV4Packets();
+                    } else {
+                        Log.e(TAG, "Illegal arugments to CMD_START_PACKET_FILTERING");
+                    }
                     break;
                 case CMD_STOP_PACKET_FILTERING:
-                    WifiNative.stopPacketFiltering();
+                    if (message.arg1 == MULTICAST_V6) {
+                        WifiNative.stopFilteringMulticastV6Packets();
+                    } else if (message.arg1 == MULTICAST_V4) {
+                        WifiNative.stopFilteringMulticastV4Packets();
+                    } else {
+                        Log.e(TAG, "Illegal arugments to CMD_STOP_PACKET_FILTERING");
+                    }
                     break;
                 default:
                     return NOT_HANDLED;