Merge "Don't change system sound defaults for upgrades."
diff --git a/api/14.txt b/api/14.txt
index 895c44d..3d96c11 100644
--- a/api/14.txt
+++ b/api/14.txt
@@ -20979,45 +20979,17 @@
 
   public class Surface implements android.os.Parcelable {
     method public int describeContents();
-    method public void freeze();
-    method public void hide();
     method public boolean isValid();
     method public android.graphics.Canvas lockCanvas(android.graphics.Rect) throws java.lang.IllegalArgumentException, android.view.Surface.OutOfResourcesException;
     method public void readFromParcel(android.os.Parcel);
-    method public void setAlpha(float);
-    method public void setFlags(int, int);
-    method public void setFreezeTint(int);
-    method public void setLayer(int);
-    method public void setMatrix(float, float, float, float);
-    method public static void setOrientation(int, int);
-    method public void setPosition(int, int);
-    method public void setSize(int, int);
-    method public void setTransparentRegionHint(android.graphics.Region);
-    method public void show();
-    method public void unfreeze();
     method public void unlockCanvas(android.graphics.Canvas);
     method public void unlockCanvasAndPost(android.graphics.Canvas);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
-    field public static final int FX_SURFACE_BLUR = 65536; // 0x10000
-    field public static final int FX_SURFACE_DIM = 131072; // 0x20000
-    field public static final int FX_SURFACE_MASK = 983040; // 0xf0000
-    field public static final int FX_SURFACE_NORMAL = 0; // 0x0
-    field public static final deprecated int GPU = 40; // 0x28
-    field public static final deprecated int HARDWARE = 16; // 0x10
-    field public static final int HIDDEN = 4; // 0x4
-    field public static final int NON_PREMULTIPLIED = 256; // 0x100
-    field public static final deprecated int PUSH_BUFFERS = 512; // 0x200
     field public static final int ROTATION_0 = 0; // 0x0
     field public static final int ROTATION_180 = 2; // 0x2
     field public static final int ROTATION_270 = 3; // 0x3
     field public static final int ROTATION_90 = 1; // 0x1
-    field public static final int SECURE = 128; // 0x80
-    field public static final deprecated int SURACE_FROZEN = 2; // 0x2
-    field public static final int SURFACE_BLUR_FREEZE = 16; // 0x10
-    field public static final int SURFACE_DITHER = 4; // 0x4
-    field public static final int SURFACE_FROZEN = 2; // 0x2
-    field public static final int SURFACE_HIDDEN = 1; // 0x1
   }
 
   public static class Surface.OutOfResourcesException extends java.lang.Exception {
diff --git a/api/current.txt b/api/current.txt
index 8595eb3..035da89 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -84,7 +84,6 @@
     field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
     field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
     field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
-    field public static final java.lang.String READ_WRITE_OWN_VOICEMAIL = "com.android.voicemail.permission.READ_WRITE_OWN_VOICEMAIL";
     field public static final java.lang.String REBOOT = "android.permission.REBOOT";
     field public static final java.lang.String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED";
     field public static final java.lang.String RECEIVE_MMS = "android.permission.RECEIVE_MMS";
@@ -1499,6 +1498,12 @@
     field public static final int Animation_InputMethod = 16973910; // 0x1030056
     field public static final int Animation_Toast = 16973828; // 0x1030004
     field public static final int Animation_Translucent = 16973827; // 0x1030003
+    field public static final int DeviceDefault_ButtonBar = 16974287; // 0x10301cf
+    field public static final int DeviceDefault_ButtonBar_AlertDialog = 16974288; // 0x10301d0
+    field public static final int DeviceDefault_Light_ButtonBar = 16974290; // 0x10301d2
+    field public static final int DeviceDefault_Light_ButtonBar_AlertDialog = 16974291; // 0x10301d3
+    field public static final int DeviceDefault_Light_SegmentedButton = 16974292; // 0x10301d4
+    field public static final int DeviceDefault_SegmentedButton = 16974289; // 0x10301d1
     field public static final int Holo_ButtonBar = 16974053; // 0x10300e5
     field public static final int Holo_ButtonBar_AlertDialog = 16974055; // 0x10300e7
     field public static final int Holo_Light_ButtonBar = 16974054; // 0x10300e6
@@ -1513,6 +1518,40 @@
     field public static final int MediaButton_Previous = 16973880; // 0x1030038
     field public static final int MediaButton_Rew = 16973884; // 0x103003c
     field public static final int TextAppearance = 16973886; // 0x103003e
+    field public static final int TextAppearance_DeviceDefault = 16974253; // 0x10301ad
+    field public static final int TextAppearance_DeviceDefault_DialogWindowTitle = 16974264; // 0x10301b8
+    field public static final int TextAppearance_DeviceDefault_Inverse = 16974254; // 0x10301ae
+    field public static final int TextAppearance_DeviceDefault_Large = 16974255; // 0x10301af
+    field public static final int TextAppearance_DeviceDefault_Large_Inverse = 16974256; // 0x10301b0
+    field public static final int TextAppearance_DeviceDefault_Medium = 16974257; // 0x10301b1
+    field public static final int TextAppearance_DeviceDefault_Medium_Inverse = 16974258; // 0x10301b2
+    field public static final int TextAppearance_DeviceDefault_SearchResult_Subtitle = 16974262; // 0x10301b6
+    field public static final int TextAppearance_DeviceDefault_SearchResult_Title = 16974261; // 0x10301b5
+    field public static final int TextAppearance_DeviceDefault_Small = 16974259; // 0x10301b3
+    field public static final int TextAppearance_DeviceDefault_Small_Inverse = 16974260; // 0x10301b4
+    field public static final int TextAppearance_DeviceDefault_Widget = 16974265; // 0x10301b9
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Menu = 16974286; // 0x10301ce
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Subtitle = 16974279; // 0x10301c7
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Subtitle_Inverse = 16974283; // 0x10301cb
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Title = 16974278; // 0x10301c6
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Title_Inverse = 16974282; // 0x10301ca
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Subtitle = 16974281; // 0x10301c9
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Subtitle_Inverse = 16974285; // 0x10301cd
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Title = 16974280; // 0x10301c8
+    field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Title_Inverse = 16974284; // 0x10301cc
+    field public static final int TextAppearance_DeviceDefault_Widget_Button = 16974266; // 0x10301ba
+    field public static final int TextAppearance_DeviceDefault_Widget_DropDownHint = 16974271; // 0x10301bf
+    field public static final int TextAppearance_DeviceDefault_Widget_DropDownItem = 16974272; // 0x10301c0
+    field public static final int TextAppearance_DeviceDefault_Widget_EditText = 16974274; // 0x10301c2
+    field public static final int TextAppearance_DeviceDefault_Widget_IconMenu_Item = 16974267; // 0x10301bb
+    field public static final int TextAppearance_DeviceDefault_Widget_PopupMenu = 16974275; // 0x10301c3
+    field public static final int TextAppearance_DeviceDefault_Widget_PopupMenu_Large = 16974276; // 0x10301c4
+    field public static final int TextAppearance_DeviceDefault_Widget_PopupMenu_Small = 16974277; // 0x10301c5
+    field public static final int TextAppearance_DeviceDefault_Widget_TabWidget = 16974268; // 0x10301bc
+    field public static final int TextAppearance_DeviceDefault_Widget_TextView = 16974269; // 0x10301bd
+    field public static final int TextAppearance_DeviceDefault_Widget_TextView_PopupMenu = 16974270; // 0x10301be
+    field public static final int TextAppearance_DeviceDefault_Widget_TextView_SpinnerItem = 16974273; // 0x10301c1
+    field public static final int TextAppearance_DeviceDefault_WindowTitle = 16974263; // 0x10301b7
     field public static final int TextAppearance_DialogWindowTitle = 16973889; // 0x1030041
     field public static final int TextAppearance_Holo = 16974075; // 0x10300fb
     field public static final int TextAppearance_Holo_DialogWindowTitle = 16974103; // 0x1030117
@@ -1578,6 +1617,30 @@
     field public static final int Theme_Black = 16973832; // 0x1030008
     field public static final int Theme_Black_NoTitleBar = 16973833; // 0x1030009
     field public static final int Theme_Black_NoTitleBar_Fullscreen = 16973834; // 0x103000a
+    field public static final int Theme_DeviceDefault = 16974120; // 0x1030128
+    field public static final int Theme_DeviceDefault_Dialog = 16974126; // 0x103012e
+    field public static final int Theme_DeviceDefault_DialogWhenLarge = 16974134; // 0x1030136
+    field public static final int Theme_DeviceDefault_DialogWhenLarge_NoActionBar = 16974135; // 0x1030137
+    field public static final int Theme_DeviceDefault_Dialog_MinWidth = 16974127; // 0x103012f
+    field public static final int Theme_DeviceDefault_Dialog_NoActionBar = 16974128; // 0x1030130
+    field public static final int Theme_DeviceDefault_Dialog_NoActionBar_MinWidth = 16974129; // 0x1030131
+    field public static final int Theme_DeviceDefault_InputMethod = 16974142; // 0x103013e
+    field public static final int Theme_DeviceDefault_Light = 16974123; // 0x103012b
+    field public static final int Theme_DeviceDefault_Light_DarkActionBar = 16974143; // 0x103013f
+    field public static final int Theme_DeviceDefault_Light_Dialog = 16974130; // 0x1030132
+    field public static final int Theme_DeviceDefault_Light_DialogWhenLarge = 16974136; // 0x1030138
+    field public static final int Theme_DeviceDefault_Light_DialogWhenLarge_NoActionBar = 16974137; // 0x1030139
+    field public static final int Theme_DeviceDefault_Light_Dialog_MinWidth = 16974131; // 0x1030133
+    field public static final int Theme_DeviceDefault_Light_Dialog_NoActionBar = 16974132; // 0x1030134
+    field public static final int Theme_DeviceDefault_Light_Dialog_NoActionBar_MinWidth = 16974133; // 0x1030135
+    field public static final int Theme_DeviceDefault_Light_NoActionBar = 16974124; // 0x103012c
+    field public static final int Theme_DeviceDefault_Light_NoActionBar_Fullscreen = 16974125; // 0x103012d
+    field public static final int Theme_DeviceDefault_Light_Panel = 16974139; // 0x103013b
+    field public static final int Theme_DeviceDefault_NoActionBar = 16974121; // 0x1030129
+    field public static final int Theme_DeviceDefault_NoActionBar_Fullscreen = 16974122; // 0x103012a
+    field public static final int Theme_DeviceDefault_Panel = 16974138; // 0x103013a
+    field public static final int Theme_DeviceDefault_Wallpaper = 16974140; // 0x103013c
+    field public static final int Theme_DeviceDefault_Wallpaper_NoTitleBar = 16974141; // 0x103013d
     field public static final int Theme_Dialog = 16973835; // 0x103000b
     field public static final int Theme_Holo = 16973931; // 0x103006b
     field public static final int Theme_Holo_Dialog = 16973935; // 0x103006f
@@ -1642,6 +1705,115 @@
     field public static final int Widget_CompoundButton_RadioButton = 16973850; // 0x103001a
     field public static final int Widget_CompoundButton_Star = 16973851; // 0x103001b
     field public static final int Widget_DatePicker = 16974062; // 0x10300ee
+    field public static final int Widget_DeviceDefault = 16974144; // 0x1030140
+    field public static final int Widget_DeviceDefault_ActionBar = 16974187; // 0x103016b
+    field public static final int Widget_DeviceDefault_ActionBar_Solid = 16974195; // 0x1030173
+    field public static final int Widget_DeviceDefault_ActionBar_TabBar = 16974194; // 0x1030172
+    field public static final int Widget_DeviceDefault_ActionBar_TabText = 16974193; // 0x1030171
+    field public static final int Widget_DeviceDefault_ActionBar_TabView = 16974192; // 0x1030170
+    field public static final int Widget_DeviceDefault_ActionButton = 16974182; // 0x1030166
+    field public static final int Widget_DeviceDefault_ActionButton_CloseMode = 16974186; // 0x103016a
+    field public static final int Widget_DeviceDefault_ActionButton_Overflow = 16974183; // 0x1030167
+    field public static final int Widget_DeviceDefault_ActionButton_TextButton = 16974184; // 0x1030168
+    field public static final int Widget_DeviceDefault_ActionMode = 16974185; // 0x1030169
+    field public static final int Widget_DeviceDefault_AutoCompleteTextView = 16974151; // 0x1030147
+    field public static final int Widget_DeviceDefault_Button = 16974145; // 0x1030141
+    field public static final int Widget_DeviceDefault_Button_Borderless = 16974188; // 0x103016c
+    field public static final int Widget_DeviceDefault_Button_Borderless_Small = 16974149; // 0x1030145
+    field public static final int Widget_DeviceDefault_Button_Inset = 16974147; // 0x1030143
+    field public static final int Widget_DeviceDefault_Button_Small = 16974146; // 0x1030142
+    field public static final int Widget_DeviceDefault_Button_Toggle = 16974148; // 0x1030144
+    field public static final int Widget_DeviceDefault_CalendarView = 16974190; // 0x103016e
+    field public static final int Widget_DeviceDefault_CompoundButton_CheckBox = 16974152; // 0x1030148
+    field public static final int Widget_DeviceDefault_CompoundButton_RadioButton = 16974169; // 0x1030159
+    field public static final int Widget_DeviceDefault_CompoundButton_Star = 16974173; // 0x103015d
+    field public static final int Widget_DeviceDefault_DatePicker = 16974191; // 0x103016f
+    field public static final int Widget_DeviceDefault_DropDownItem = 16974177; // 0x1030161
+    field public static final int Widget_DeviceDefault_DropDownItem_Spinner = 16974178; // 0x1030162
+    field public static final int Widget_DeviceDefault_EditText = 16974154; // 0x103014a
+    field public static final int Widget_DeviceDefault_ExpandableListView = 16974155; // 0x103014b
+    field public static final int Widget_DeviceDefault_GridView = 16974156; // 0x103014c
+    field public static final int Widget_DeviceDefault_HorizontalScrollView = 16974171; // 0x103015b
+    field public static final int Widget_DeviceDefault_ImageButton = 16974157; // 0x103014d
+    field public static final int Widget_DeviceDefault_Light = 16974196; // 0x1030174
+    field public static final int Widget_DeviceDefault_Light_ActionBar = 16974243; // 0x10301a3
+    field public static final int Widget_DeviceDefault_Light_ActionBar_Solid = 16974247; // 0x10301a7
+    field public static final int Widget_DeviceDefault_Light_ActionBar_Solid_Inverse = 16974248; // 0x10301a8
+    field public static final int Widget_DeviceDefault_Light_ActionBar_TabBar = 16974246; // 0x10301a6
+    field public static final int Widget_DeviceDefault_Light_ActionBar_TabBar_Inverse = 16974249; // 0x10301a9
+    field public static final int Widget_DeviceDefault_Light_ActionBar_TabText = 16974245; // 0x10301a5
+    field public static final int Widget_DeviceDefault_Light_ActionBar_TabText_Inverse = 16974251; // 0x10301ab
+    field public static final int Widget_DeviceDefault_Light_ActionBar_TabView = 16974244; // 0x10301a4
+    field public static final int Widget_DeviceDefault_Light_ActionBar_TabView_Inverse = 16974250; // 0x10301aa
+    field public static final int Widget_DeviceDefault_Light_ActionButton = 16974239; // 0x103019f
+    field public static final int Widget_DeviceDefault_Light_ActionButton_CloseMode = 16974242; // 0x10301a2
+    field public static final int Widget_DeviceDefault_Light_ActionButton_Overflow = 16974240; // 0x10301a0
+    field public static final int Widget_DeviceDefault_Light_ActionMode = 16974241; // 0x10301a1
+    field public static final int Widget_DeviceDefault_Light_ActionMode_Inverse = 16974252; // 0x10301ac
+    field public static final int Widget_DeviceDefault_Light_AutoCompleteTextView = 16974203; // 0x103017b
+    field public static final int Widget_DeviceDefault_Light_Button = 16974197; // 0x1030175
+    field public static final int Widget_DeviceDefault_Light_Button_Borderless_Small = 16974201; // 0x1030179
+    field public static final int Widget_DeviceDefault_Light_Button_Inset = 16974199; // 0x1030177
+    field public static final int Widget_DeviceDefault_Light_Button_Small = 16974198; // 0x1030176
+    field public static final int Widget_DeviceDefault_Light_Button_Toggle = 16974200; // 0x1030178
+    field public static final int Widget_DeviceDefault_Light_CalendarView = 16974238; // 0x103019e
+    field public static final int Widget_DeviceDefault_Light_CompoundButton_CheckBox = 16974204; // 0x103017c
+    field public static final int Widget_DeviceDefault_Light_CompoundButton_RadioButton = 16974224; // 0x1030190
+    field public static final int Widget_DeviceDefault_Light_CompoundButton_Star = 16974228; // 0x1030194
+    field public static final int Widget_DeviceDefault_Light_DropDownItem = 16974232; // 0x1030198
+    field public static final int Widget_DeviceDefault_Light_DropDownItem_Spinner = 16974233; // 0x1030199
+    field public static final int Widget_DeviceDefault_Light_EditText = 16974206; // 0x103017e
+    field public static final int Widget_DeviceDefault_Light_ExpandableListView = 16974207; // 0x103017f
+    field public static final int Widget_DeviceDefault_Light_GridView = 16974208; // 0x1030180
+    field public static final int Widget_DeviceDefault_Light_HorizontalScrollView = 16974226; // 0x1030192
+    field public static final int Widget_DeviceDefault_Light_ImageButton = 16974209; // 0x1030181
+    field public static final int Widget_DeviceDefault_Light_ListPopupWindow = 16974235; // 0x103019b
+    field public static final int Widget_DeviceDefault_Light_ListView = 16974210; // 0x1030182
+    field public static final int Widget_DeviceDefault_Light_ListView_DropDown = 16974205; // 0x103017d
+    field public static final int Widget_DeviceDefault_Light_PopupMenu = 16974236; // 0x103019c
+    field public static final int Widget_DeviceDefault_Light_PopupWindow = 16974211; // 0x1030183
+    field public static final int Widget_DeviceDefault_Light_ProgressBar = 16974212; // 0x1030184
+    field public static final int Widget_DeviceDefault_Light_ProgressBar_Horizontal = 16974213; // 0x1030185
+    field public static final int Widget_DeviceDefault_Light_ProgressBar_Inverse = 16974217; // 0x1030189
+    field public static final int Widget_DeviceDefault_Light_ProgressBar_Large = 16974216; // 0x1030188
+    field public static final int Widget_DeviceDefault_Light_ProgressBar_Large_Inverse = 16974219; // 0x103018b
+    field public static final int Widget_DeviceDefault_Light_ProgressBar_Small = 16974214; // 0x1030186
+    field public static final int Widget_DeviceDefault_Light_ProgressBar_Small_Inverse = 16974218; // 0x103018a
+    field public static final int Widget_DeviceDefault_Light_ProgressBar_Small_Title = 16974215; // 0x1030187
+    field public static final int Widget_DeviceDefault_Light_RatingBar = 16974221; // 0x103018d
+    field public static final int Widget_DeviceDefault_Light_RatingBar_Indicator = 16974222; // 0x103018e
+    field public static final int Widget_DeviceDefault_Light_RatingBar_Small = 16974223; // 0x103018f
+    field public static final int Widget_DeviceDefault_Light_ScrollView = 16974225; // 0x1030191
+    field public static final int Widget_DeviceDefault_Light_SeekBar = 16974220; // 0x103018c
+    field public static final int Widget_DeviceDefault_Light_Spinner = 16974227; // 0x1030193
+    field public static final int Widget_DeviceDefault_Light_Tab = 16974237; // 0x103019d
+    field public static final int Widget_DeviceDefault_Light_TabWidget = 16974229; // 0x1030195
+    field public static final int Widget_DeviceDefault_Light_TextView = 16974202; // 0x103017a
+    field public static final int Widget_DeviceDefault_Light_TextView_SpinnerItem = 16974234; // 0x103019a
+    field public static final int Widget_DeviceDefault_Light_WebTextView = 16974230; // 0x1030196
+    field public static final int Widget_DeviceDefault_Light_WebView = 16974231; // 0x1030197
+    field public static final int Widget_DeviceDefault_ListPopupWindow = 16974180; // 0x1030164
+    field public static final int Widget_DeviceDefault_ListView = 16974158; // 0x103014e
+    field public static final int Widget_DeviceDefault_ListView_DropDown = 16974153; // 0x1030149
+    field public static final int Widget_DeviceDefault_PopupMenu = 16974181; // 0x1030165
+    field public static final int Widget_DeviceDefault_PopupWindow = 16974159; // 0x103014f
+    field public static final int Widget_DeviceDefault_ProgressBar = 16974160; // 0x1030150
+    field public static final int Widget_DeviceDefault_ProgressBar_Horizontal = 16974161; // 0x1030151
+    field public static final int Widget_DeviceDefault_ProgressBar_Large = 16974164; // 0x1030154
+    field public static final int Widget_DeviceDefault_ProgressBar_Small = 16974162; // 0x1030152
+    field public static final int Widget_DeviceDefault_ProgressBar_Small_Title = 16974163; // 0x1030153
+    field public static final int Widget_DeviceDefault_RatingBar = 16974166; // 0x1030156
+    field public static final int Widget_DeviceDefault_RatingBar_Indicator = 16974167; // 0x1030157
+    field public static final int Widget_DeviceDefault_RatingBar_Small = 16974168; // 0x1030158
+    field public static final int Widget_DeviceDefault_ScrollView = 16974170; // 0x103015a
+    field public static final int Widget_DeviceDefault_SeekBar = 16974165; // 0x1030155
+    field public static final int Widget_DeviceDefault_Spinner = 16974172; // 0x103015c
+    field public static final int Widget_DeviceDefault_Tab = 16974189; // 0x103016d
+    field public static final int Widget_DeviceDefault_TabWidget = 16974174; // 0x103015e
+    field public static final int Widget_DeviceDefault_TextView = 16974150; // 0x1030146
+    field public static final int Widget_DeviceDefault_TextView_SpinnerItem = 16974179; // 0x1030163
+    field public static final int Widget_DeviceDefault_WebTextView = 16974175; // 0x103015f
+    field public static final int Widget_DeviceDefault_WebView = 16974176; // 0x1030160
     field public static final int Widget_DropDownItem = 16973867; // 0x103002b
     field public static final int Widget_DropDownItem_Spinner = 16973868; // 0x103002c
     field public static final int Widget_EditText = 16973859; // 0x1030023
@@ -8454,6 +8626,7 @@
     ctor public SurfaceTexture(int, boolean);
     method public long getTimestamp();
     method public void getTransformMatrix(float[]);
+    method public void release();
     method public void setOnFrameAvailableListener(android.graphics.SurfaceTexture.OnFrameAvailableListener);
     method public void updateTexImage();
   }
@@ -18012,13 +18185,21 @@
 
   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 abstract android.service.textservice.SpellCheckerService.Session createSession();
     method public final android.os.IBinder onBind(android.content.Intent);
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.textservice.SpellCheckerService";
   }
 
+  public abstract class SpellCheckerService.Session {
+    ctor public SpellCheckerService.Session();
+    method public android.os.Bundle getBundle();
+    method public java.lang.String getLocale();
+    method public void onCancel();
+    method public abstract void onCreate();
+    method public abstract android.view.textservice.SuggestionsInfo onGetSuggestions(android.view.textservice.TextInfo, int);
+    method public android.view.textservice.SuggestionsInfo[] onGetSuggestionsMultiple(android.view.textservice.TextInfo[], int, boolean);
+  }
+
 }
 
 package android.service.wallpaper {
@@ -22079,45 +22260,18 @@
 
   public class Surface implements android.os.Parcelable {
     method public int describeContents();
-    method public void freeze();
-    method public void hide();
     method public boolean isValid();
     method public android.graphics.Canvas lockCanvas(android.graphics.Rect) throws java.lang.IllegalArgumentException, android.view.Surface.OutOfResourcesException;
     method public void readFromParcel(android.os.Parcel);
-    method public void setAlpha(float);
-    method public void setFlags(int, int);
-    method public void setFreezeTint(int);
-    method public void setLayer(int);
-    method public void setMatrix(float, float, float, float);
-    method public static void setOrientation(int, int);
-    method public void setPosition(int, int);
-    method public void setSize(int, int);
-    method public void setTransparentRegionHint(android.graphics.Region);
-    method public void show();
-    method public void unfreeze();
+    method public void release();
     method public void unlockCanvas(android.graphics.Canvas);
     method public void unlockCanvasAndPost(android.graphics.Canvas);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
-    field public static final int FX_SURFACE_BLUR = 65536; // 0x10000
-    field public static final int FX_SURFACE_DIM = 131072; // 0x20000
-    field public static final int FX_SURFACE_MASK = 983040; // 0xf0000
-    field public static final int FX_SURFACE_NORMAL = 0; // 0x0
-    field public static final deprecated int GPU = 40; // 0x28
-    field public static final deprecated int HARDWARE = 16; // 0x10
-    field public static final int HIDDEN = 4; // 0x4
-    field public static final int NON_PREMULTIPLIED = 256; // 0x100
-    field public static final deprecated int PUSH_BUFFERS = 512; // 0x200
     field public static final int ROTATION_0 = 0; // 0x0
     field public static final int ROTATION_180 = 2; // 0x2
     field public static final int ROTATION_270 = 3; // 0x3
     field public static final int ROTATION_90 = 1; // 0x1
-    field public static final int SECURE = 128; // 0x80
-    field public static final deprecated int SURACE_FROZEN = 2; // 0x2
-    field public static final int SURFACE_BLUR_FREEZE = 16; // 0x10
-    field public static final int SURFACE_DITHER = 4; // 0x4
-    field public static final int SURFACE_FROZEN = 2; // 0x2
-    field public static final int SURFACE_HIDDEN = 1; // 0x1
   }
 
   public static class Surface.OutOfResourcesException extends java.lang.Exception {
@@ -24162,7 +24316,7 @@
   }
 
   public final class TextServicesManager {
-    method public android.view.textservice.SpellCheckerSession newSpellCheckerSession(java.util.Locale, android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener, boolean);
+    method public android.view.textservice.SpellCheckerSession newSpellCheckerSession(android.os.Bundle, java.util.Locale, android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener, boolean);
   }
 
 }
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 5fe3644..57e0583 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -32,10 +32,9 @@
 
     /**
      * Starts this animation. If the animation has a nonzero startDelay, the animation will start
-     * running after that delay elapses. Note that the animation does not start synchronously with
-     * this call, because all animation events are posted to a central timing loop so that animation
-     * times are all synchronized on a single timing pulse on the UI thread. So the animation will
-     * start the next time that event handler processes events.
+     * running after that delay elapses. A non-delayed animation will have its initial
+     * value(s) set immediately, followed by calls to
+     * {@link AnimatorListener#onAnimationStart(Animator)} for any listeners of this animator.
      *
      * <p>The animation started by calling this method will be run on the thread that called
      * this method. This thread should have a Looper on it (a runtime exception will be thrown if
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 61a12ee..ce3dd13 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -349,7 +349,8 @@
                 return true;
             }
         }
-        return false;
+        // Also return true if we're currently running the startDelay animator
+        return (mDelayAnim != null && mDelayAnim.isRunning());
     }
 
     /**
@@ -487,7 +488,6 @@
                 mPlayingSet.add(node.animation);
             }
         } else {
-            // TODO: Need to cancel out of the delay appropriately
             mDelayAnim = ValueAnimator.ofFloat(0f, 1f);
             mDelayAnim.setDuration(mStartDelay);
             mDelayAnim.addListener(new AnimatorListenerAdapter() {
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 90d676e..c22306a 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -186,6 +186,16 @@
     int mPlayingState = STOPPED;
 
     /**
+     * Additional playing state to indicate whether an animator has been start()'d. There is
+     * some lag between a call to start() and the first animation frame. We should still note
+     * that the animation has been started, even if it's first animation frame has not yet
+     * happened, and reflect that state in isRunning().
+     * Note that delayed animations are different: they are not started until their first
+     * animation frame, which occurs after their delay elapses.
+     */
+    private boolean mStarted = false;
+
+    /**
      * Flag that denotes whether the animation is set up and ready to go. Used to
      * set up animation that has not yet been started.
      */
@@ -618,6 +628,7 @@
                         for (int i = 0; i < numReadyAnims; ++i) {
                             ValueAnimator anim = readyAnims.get(i);
                             anim.startAnimation();
+                            anim.mStarted = true;
                             delayedAnims.remove(anim);
                         }
                         readyAnims.clear();
@@ -908,6 +919,7 @@
             // This sets the initial value of the animation, prior to actually starting it running
             setCurrentPlayTime(getCurrentPlayTime());
             mPlayingState = STOPPED;
+            mStarted = true;
 
             if (mListeners != null) {
                 ArrayList<AnimatorListener> tmpListeners =
@@ -937,7 +949,8 @@
         // to run
         if (mPlayingState != STOPPED || sPendingAnimations.get().contains(this) ||
                 sDelayedAnims.get().contains(this)) {
-            if (mListeners != null) {
+            // Only notify listeners if the animator has actually started
+            if (mStarted && mListeners != null) {
                 ArrayList<AnimatorListener> tmpListeners =
                         (ArrayList<AnimatorListener>) mListeners.clone();
                 for (AnimatorListener listener : tmpListeners) {
@@ -969,7 +982,7 @@
 
     @Override
     public boolean isRunning() {
-        return (mPlayingState == RUNNING);
+        return (mPlayingState == RUNNING || mStarted);
     }
 
     /**
@@ -1000,7 +1013,7 @@
         sPendingAnimations.get().remove(this);
         sDelayedAnims.get().remove(this);
         mPlayingState = STOPPED;
-        if (mListeners != null) {
+        if (mStarted && mListeners != null) {
             ArrayList<AnimatorListener> tmpListeners =
                     (ArrayList<AnimatorListener>) mListeners.clone();
             int numListeners = tmpListeners.size();
@@ -1008,6 +1021,7 @@
                 tmpListeners.get(i).onAnimationEnd(this);
             }
         }
+        mStarted = false;
     }
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index ca6f085..28bc424 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1163,7 +1163,10 @@
      * <p> If this API returns true, it means the callback will be called.
      * The callback will be called with the current state of Bluetooth.
      * If the state is not what was requested, an internal error would be the
-     * reason.
+     * reason. If Bluetooth is already on and if this function is called to turn
+     * it on, the api will return true and a callback will be called.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
      *
      * @param on True for on, false for off.
      * @param callback The callback to notify changes to the state.
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 6767747..58c79fc 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1708,6 +1708,7 @@
         private static final String PIXEL_FORMAT_YUV420P = "yuv420p";
         private static final String PIXEL_FORMAT_RGB565 = "rgb565";
         private static final String PIXEL_FORMAT_JPEG = "jpeg";
+        private static final String PIXEL_FORMAT_BAYER_RGGB = "bayer-rggb";
 
         private HashMap<String, String> mMap;
 
@@ -2258,6 +2259,7 @@
             case ImageFormat.YV12:      return PIXEL_FORMAT_YUV420P;
             case ImageFormat.RGB_565:   return PIXEL_FORMAT_RGB565;
             case ImageFormat.JPEG:      return PIXEL_FORMAT_JPEG;
+            case ImageFormat.BAYER_RGGB: return PIXEL_FORMAT_BAYER_RGGB;
             default:                    return null;
             }
         }
diff --git a/core/java/android/net/DnsPinger.java b/core/java/android/net/DnsPinger.java
index f2d84eb..81738f3 100644
--- a/core/java/android/net/DnsPinger.java
+++ b/core/java/android/net/DnsPinger.java
@@ -17,20 +17,27 @@
 package android.net;
 
 import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.LinkProperties;
-import android.net.NetworkUtils;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.util.Slog;
 
+import com.android.internal.util.Protocol;
+
+import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.net.SocketTimeoutException;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Random;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Performs a simple DNS "ping" by sending a "server status" query packet to the
@@ -40,42 +47,174 @@
  * API may not differentiate between a time out and a failure lookup (which we
  * really care about).
  * <p>
- * TODO : More general API. Socket does not bind to specified connection type
- * TODO : Choice of DNS query location - current looks up www.android.com
  *
  * @hide
  */
-public final class DnsPinger {
+public final class DnsPinger extends Handler {
     private static final boolean V = true;
 
-    /** Number of bytes for the query */
-    private static final int DNS_QUERY_BASE_SIZE = 32;
-
-    /** The DNS port */
+    private static final int RECEIVE_POLL_INTERVAL_MS = 30;
     private static final int DNS_PORT = 53;
 
+    /** Short socket timeout so we don't block one any 'receive' call */
+    private static final int SOCKET_TIMEOUT_MS = 1;
+
     /** Used to generate IDs */
-    private static Random sRandom = new Random();
+    private static final Random sRandom = new Random();
+    private static final AtomicInteger sCounter = new AtomicInteger();
 
     private ConnectivityManager mConnectivityManager = null;
-    private Context mContext;
-    private int mConnectionType;
-    private InetAddress mDefaultDns;
-
+    private final Context mContext;
+    private final int mConnectionType;
+    private final Handler mTarget;
+    private final InetAddress mDefaultDns;
     private String TAG;
 
+    private static final int BASE = Protocol.BASE_DNS_PINGER;
+
     /**
-     * @param connectionType The connection type from {@link ConnectivityManager}
+     * Async response packet for dns pings.
+     * arg1 is the ID of the ping, also returned by {@link #pingDnsAsync(InetAddress, int, int)}
+     * arg2 is the delay, or is negative on error.
      */
-    public DnsPinger(String TAG, Context context, int connectionType) {
+    public static final int DNS_PING_RESULT = BASE;
+    /** An error code for a {@link #DNS_PING_RESULT} packet */
+    public static final int TIMEOUT = -1;
+    /** An error code for a {@link #DNS_PING_RESULT} packet */
+    public static final int SOCKET_EXCEPTION = -2;
+
+    /**
+     * Send a new ping via a socket.  arg1 is ID, arg2 is timeout, obj is InetAddress to ping
+     */
+    private static final int ACTION_PING_DNS = BASE + 1;
+    private static final int ACTION_LISTEN_FOR_RESPONSE = BASE + 2;
+    private static final int ACTION_CANCEL_ALL_PINGS = BASE + 3;
+
+    private List<ActivePing> mActivePings = new ArrayList<ActivePing>();
+    private int mEventCounter;
+
+    private class ActivePing {
+        DatagramSocket socket;
+        int internalId;
+        short packetId;
+        int timeout;
+        Integer result;
+        long start = SystemClock.elapsedRealtime();
+    }
+
+    public DnsPinger(Context context, String TAG, Looper looper,
+            Handler target, int connectionType) {
+        super(looper);
+        this.TAG = TAG;
         mContext = context;
+        mTarget = target;
         mConnectionType = connectionType;
         if (!ConnectivityManager.isNetworkTypeValid(connectionType)) {
-            Slog.e(TAG, "Invalid connectionType in constructor: " + connectionType);
+            throw new IllegalArgumentException("Invalid connectionType in constructor: "
+                    + connectionType);
         }
-        this.TAG = TAG;
-
         mDefaultDns = getDefaultDns();
+        mEventCounter = 0;
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+        switch (msg.what) {
+            case ACTION_PING_DNS:
+                try {
+                    ActivePing newActivePing = new ActivePing();
+                    InetAddress dnsAddress = (InetAddress) msg.obj;
+                    newActivePing.internalId = msg.arg1;
+                    newActivePing.timeout = msg.arg2;
+                    newActivePing.socket = new DatagramSocket();
+                    // Set some socket properties
+                    newActivePing.socket.setSoTimeout(SOCKET_TIMEOUT_MS);
+
+                    // Try to bind but continue ping if bind fails
+                    try {
+                        newActivePing.socket.setNetworkInterface(NetworkInterface.getByName(
+                                getCurrentLinkProperties().getInterfaceName()));
+                    } catch (Exception e) {
+                        Slog.w(TAG,"sendDnsPing::Error binding to socket", e);
+                    }
+
+                    newActivePing.packetId = (short) sRandom.nextInt();
+                    byte[] buf = mDnsQuery.clone();
+                    buf[0] = (byte) (newActivePing.packetId >> 8);
+                    buf[1] = (byte) newActivePing.packetId;
+
+                    // Send the DNS query
+                    DatagramPacket packet = new DatagramPacket(buf,
+                            buf.length, dnsAddress, DNS_PORT);
+                    if (V) {
+                        Slog.v(TAG, "Sending a ping to " + dnsAddress.getHostAddress()
+                                + " with ID " + newActivePing.packetId + ".");
+                    }
+
+                    newActivePing.socket.send(packet);
+                    mActivePings.add(newActivePing);
+                    mEventCounter++;
+                    sendMessageDelayed(obtainMessage(ACTION_LISTEN_FOR_RESPONSE, mEventCounter, 0),
+                            RECEIVE_POLL_INTERVAL_MS);
+                } catch (IOException e) {
+                    sendResponse((short) msg.arg1, SOCKET_EXCEPTION);
+                }
+                break;
+            case ACTION_LISTEN_FOR_RESPONSE:
+                if (msg.arg1 != mEventCounter) {
+                    break;
+                }
+                for (ActivePing curPing : mActivePings) {
+                    try {
+                        /** Each socket will block for {@link #SOCKET_TIMEOUT_MS} in receive() */
+                        byte[] responseBuf = new byte[2];
+                        DatagramPacket replyPacket = new DatagramPacket(responseBuf, 2);
+                        curPing.socket.receive(replyPacket);
+                        // Check that ID field matches (we're throwing out the rest of the packet)
+                        if (responseBuf[0] == (byte) (curPing.packetId >> 8) &&
+                                responseBuf[1] == (byte) curPing.packetId) {
+                            curPing.result =
+                                    (int) (SystemClock.elapsedRealtime() - curPing.start);
+                        } else {
+                            if (V) {
+                                Slog.v(TAG, "response ID didn't match, ignoring packet");
+                            }
+                        }
+                    } catch (SocketTimeoutException e) {
+                        // A timeout here doesn't mean anything - squelsh this exception
+                    } catch (Exception e) {
+                        if (V) {
+                            Slog.v(TAG, "DnsPinger.pingDns got socket exception: ", e);
+                        }
+                        curPing.result = SOCKET_EXCEPTION;
+                    }
+                }
+                Iterator<ActivePing> iter = mActivePings.iterator();
+                while (iter.hasNext()) {
+                   ActivePing curPing = iter.next();
+                   if (curPing.result != null) {
+                       sendResponse(curPing.internalId, curPing.result);
+                       curPing.socket.close();
+                       iter.remove();
+                   } else if (SystemClock.elapsedRealtime() >
+                                  curPing.start + curPing.timeout) {
+                       sendResponse(curPing.internalId, TIMEOUT);
+                       curPing.socket.close();
+                       iter.remove();
+                   }
+                }
+                if (!mActivePings.isEmpty()) {
+                    sendMessageDelayed(obtainMessage(ACTION_LISTEN_FOR_RESPONSE, mEventCounter, 0),
+                            RECEIVE_POLL_INTERVAL_MS);
+                }
+                break;
+            case ACTION_CANCEL_ALL_PINGS:
+                for (ActivePing activePing : mActivePings)
+                    activePing.socket.close();
+                mActivePings.clear();
+                removeMessages(ACTION_PING_DNS);
+                break;
+        }
     }
 
     /**
@@ -99,6 +238,30 @@
         return dnses.iterator().next();
     }
 
+    /**
+     * Send a ping.  The response will come via a {@link #DNS_PING_RESULT} to the handler
+     * specified at creation.
+     * @param dns address of dns server to ping
+     * @param timeout timeout for ping
+     * @return an ID field, which will also be included in the {@link #DNS_PING_RESULT} message.
+     */
+    public int pingDnsAsync(InetAddress dns, int timeout, int delay) {
+        int id = sCounter.incrementAndGet();
+        sendMessageDelayed(obtainMessage(ACTION_PING_DNS, id, timeout, dns), delay);
+        return id;
+    }
+
+    public void cancelPings() {
+        obtainMessage(ACTION_CANCEL_ALL_PINGS).sendToTarget();
+    }
+
+    private void sendResponse(int internalId, int responseVal) {
+        if(V) {
+            Slog.v(TAG, "Responding with id " + internalId + " and val " + responseVal);
+        }
+        mTarget.sendMessage(obtainMessage(DNS_PING_RESULT, internalId, responseVal));
+    }
+
     private LinkProperties getCurrentLinkProperties() {
         if (mConnectivityManager == null) {
             mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
@@ -123,106 +286,18 @@
         }
     }
 
-    /**
-     * @return time to response. Negative value on error.
-     */
-    public long pingDns(InetAddress dnsAddress, int timeout) {
-        DatagramSocket socket = null;
-        try {
-            socket = new DatagramSocket();
-
-            // Set some socket properties
-            socket.setSoTimeout(timeout);
-
-            // Try to bind but continue ping if bind fails
-            try {
-                socket.setNetworkInterface(NetworkInterface.getByName(
-                        getCurrentLinkProperties().getInterfaceName()));
-            } catch (Exception e) {
-                Slog.d(TAG,"pingDns::Error binding to socket", e);
-            }
-
-            byte[] buf = constructQuery();
-
-            // Send the DNS query
-
-            DatagramPacket packet = new DatagramPacket(buf,
-                    buf.length, dnsAddress, DNS_PORT);
-            long start = SystemClock.elapsedRealtime();
-            socket.send(packet);
-
-            // Wait for reply (blocks for the above timeout)
-            DatagramPacket replyPacket = new DatagramPacket(buf, buf.length);
-            socket.receive(replyPacket);
-
-            // If a timeout occurred, an exception would have been thrown. We
-            // got a reply!
-            return SystemClock.elapsedRealtime() - start;
-
-        } catch (SocketTimeoutException e) {
-            // Squelch this exception.
-            return -1;
-        } catch (Exception e) {
-            if (V) {
-                Slog.v(TAG, "DnsPinger.pingDns got socket exception: ", e);
-            }
-            return -2;
-        } finally {
-            if (socket != null) {
-                socket.close();
-            }
-        }
-
-    }
-
-    /**
-     * @return google.com DNS query packet
-     */
-    private static byte[] constructQuery() {
-        byte[] buf = new byte[DNS_QUERY_BASE_SIZE];
-
-        // [0-1] bytes are an ID, generate random ID for this query
-        buf[0] = (byte) sRandom.nextInt(256);
-        buf[1] = (byte) sRandom.nextInt(256);
-
-        // [2-3] bytes are for flags.
-        buf[2] = 0x01; // Recursion desired
-
-        // [4-5] bytes are for number of queries (QCOUNT)
-        buf[5] = 0x01;
-
-        // [6-7] [8-9] [10-11] are all counts of other fields we don't use
-
-        // [12-15] for www
-        writeString(buf, 12, "www");
-
-        // [16-22] for google
-        writeString(buf, 16, "google");
-
-        // [23-26] for com
-        writeString(buf, 23, "com");
-
-        // [27] is a null byte terminator byte for the url
-
-        // [28-29] bytes are for QTYPE, set to 1 = A (host address)
-        buf[29] = 0x01;
-
-        // [30-31] bytes are for QCLASS, set to 1 = IN (internet)
-        buf[31] = 0x01;
-
-        return buf;
-    }
-
-    /**
-     * Writes the string's length and its contents to the buffer
-     */
-    private static void writeString(byte[] buf, int startPos, String string) {
-        int pos = startPos;
-
-        // Write the length first
-        buf[pos++] = (byte) string.length();
-        for (int i = 0; i < string.length(); i++) {
-            buf[pos++] = (byte) string.charAt(i);
-        }
-    }
+    private static final byte[] mDnsQuery = new byte[] {
+        0, 0, // [0-1] is for ID (will set each time)
+        0, 0, // [2-3] are flags.  Set byte[2] = 1 for recursion desired (RD) on.  Currently off. 
+        0, 1, // [4-5] bytes are for number of queries (QCOUNT)
+        0, 0, // [6-7] unused count field for dns response packets
+        0, 0, // [8-9] unused count field for dns response packets
+        0, 0, // [10-11] unused count field for dns response packets
+        3, 'w', 'w', 'w',
+        6, 'g', 'o', 'o', 'g', 'l', 'e',
+        3, 'c', 'o', 'm',
+        0,    // null terminator of address (also called empty TLD)
+        0, 1, // QTYPE, set to 1 = A (host address)
+        0, 1  // QCLASS, set to 1 = IN (internet)
+    };
 }
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index c41d182..b65506c 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -24,9 +24,9 @@
 interface INetworkStatsService {
 
     /** Return historical network layer stats for traffic that matches template. */
-    NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template);
+    NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
     /** Return historical network layer stats for specific UID traffic that matches template. */
-    NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int tag);
+    NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int tag, int fields);
 
     /** Return network layer usage summary for traffic that matches template. */
     NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 1e9d813..9d253c7 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -189,9 +189,10 @@
      */
     public static void snapToCycleDay(Time time, int cycleDay) {
         if (cycleDay > time.getActualMaximum(MONTH_DAY)) {
-            // cycle day isn't valid this month; snap to 1st of next month
+            // cycle day isn't valid this month; snap to last second of month
             time.month += 1;
             time.monthDay = 1;
+            time.second = -1;
         } else {
             time.monthDay = cycleDay;
         }
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 0e8e7fc..f2fcb8f 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -58,7 +58,7 @@
     private long[] rxPackets;
     private long[] txBytes;
     private long[] txPackets;
-    private int[] operations;
+    private long[] operations;
 
     public static class Entry {
         public String iface;
@@ -68,13 +68,18 @@
         public long rxPackets;
         public long txBytes;
         public long txPackets;
-        public int operations;
+        public long operations;
 
         public Entry() {
+            this(IFACE_ALL, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
+        }
+
+        public Entry(long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
+            this(IFACE_ALL, UID_ALL, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, operations);
         }
 
         public Entry(String iface, int uid, int tag, long rxBytes, long rxPackets, long txBytes,
-                long txPackets, int operations) {
+                long txPackets, long operations) {
             this.iface = iface;
             this.uid = uid;
             this.tag = tag;
@@ -96,7 +101,7 @@
         this.rxPackets = new long[initialSize];
         this.txBytes = new long[initialSize];
         this.txPackets = new long[initialSize];
-        this.operations = new int[initialSize];
+        this.operations = new long[initialSize];
     }
 
     public NetworkStats(Parcel parcel) {
@@ -109,7 +114,7 @@
         rxPackets = parcel.createLongArray();
         txBytes = parcel.createLongArray();
         txPackets = parcel.createLongArray();
-        operations = parcel.createIntArray();
+        operations = parcel.createLongArray();
     }
 
     /** {@inheritDoc} */
@@ -123,16 +128,16 @@
         dest.writeLongArray(rxPackets);
         dest.writeLongArray(txBytes);
         dest.writeLongArray(txPackets);
-        dest.writeIntArray(operations);
+        dest.writeLongArray(operations);
     }
 
     public NetworkStats addValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
             long txBytes, long txPackets) {
-        return addValues(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, 0);
+        return addValues(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, 0L);
     }
 
     public NetworkStats addValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
-            long txBytes, long txPackets, int operations) {
+            long txBytes, long txPackets, long operations) {
         return addValues(
                 new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
     }
@@ -197,7 +202,7 @@
     }
 
     public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
-            long txBytes, long txPackets, int operations) {
+            long txBytes, long txPackets, long operations) {
         return combineValues(
                 new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
     }
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index 7a4b811..c917af9 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -19,11 +19,11 @@
 import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
-import static android.net.NetworkStatsHistory.DataStreamUtils.readLongArray;
-import static android.net.NetworkStatsHistory.DataStreamUtils.writeLongArray;
-import static android.net.NetworkStatsHistory.ParcelUtils.readIntArray;
+import static android.net.NetworkStatsHistory.DataStreamUtils.readFullLongArray;
+import static android.net.NetworkStatsHistory.DataStreamUtils.readVarLongArray;
+import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLongArray;
+import static android.net.NetworkStatsHistory.Entry.UNKNOWN;
 import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray;
-import static android.net.NetworkStatsHistory.ParcelUtils.writeIntArray;
 import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray;
 
 import android.os.Parcel;
@@ -51,42 +51,53 @@
  */
 public class NetworkStatsHistory implements Parcelable {
     private static final int VERSION_INIT = 1;
+    private static final int VERSION_ADD_PACKETS = 2;
 
-    // TODO: teach about varint encoding to use less disk space
-    // TODO: teach about omitting entire fields to reduce parcel pressure
-    // TODO: persist/restore packet and operation counts
+    public static final int FIELD_RX_BYTES = 0x01;
+    public static final int FIELD_RX_PACKETS = 0x02;
+    public static final int FIELD_TX_BYTES = 0x04;
+    public static final int FIELD_TX_PACKETS = 0x08;
+    public static final int FIELD_OPERATIONS = 0x10;
 
-    private final long bucketDuration;
+    public static final int FIELD_ALL = 0xFFFFFFFF;
+
+    private long bucketDuration;
     private int bucketCount;
     private long[] bucketStart;
     private long[] rxBytes;
     private long[] rxPackets;
     private long[] txBytes;
     private long[] txPackets;
-    private int[] operations;
+    private long[] operations;
 
     public static class Entry {
+        public static final long UNKNOWN = -1;
+
         public long bucketStart;
         public long bucketDuration;
         public long rxBytes;
         public long rxPackets;
         public long txBytes;
         public long txPackets;
-        public int operations;
+        public long operations;
     }
 
     public NetworkStatsHistory(long bucketDuration) {
-        this(bucketDuration, 10);
+        this(bucketDuration, 10, FIELD_ALL);
     }
 
     public NetworkStatsHistory(long bucketDuration, int initialSize) {
+        this(bucketDuration, initialSize, FIELD_ALL);
+    }
+
+    public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) {
         this.bucketDuration = bucketDuration;
         bucketStart = new long[initialSize];
-        rxBytes = new long[initialSize];
-        rxPackets = new long[initialSize];
-        txBytes = new long[initialSize];
-        txPackets = new long[initialSize];
-        operations = new int[initialSize];
+        if ((fields & FIELD_RX_BYTES) != 0) rxBytes = new long[initialSize];
+        if ((fields & FIELD_RX_PACKETS) != 0) rxPackets = new long[initialSize];
+        if ((fields & FIELD_TX_BYTES) != 0) txBytes = new long[initialSize];
+        if ((fields & FIELD_TX_PACKETS) != 0) txPackets = new long[initialSize];
+        if ((fields & FIELD_OPERATIONS) != 0) operations = new long[initialSize];
         bucketCount = 0;
     }
 
@@ -97,7 +108,7 @@
         rxPackets = readLongArray(in);
         txBytes = readLongArray(in);
         txPackets = readLongArray(in);
-        operations = readIntArray(in);
+        operations = readLongArray(in);
         bucketCount = bucketStart.length;
     }
 
@@ -109,21 +120,31 @@
         writeLongArray(out, rxPackets, bucketCount);
         writeLongArray(out, txBytes, bucketCount);
         writeLongArray(out, txPackets, bucketCount);
-        writeIntArray(out, operations, bucketCount);
+        writeLongArray(out, operations, bucketCount);
     }
 
     public NetworkStatsHistory(DataInputStream in) throws IOException {
-        // TODO: read packet and operation counts
         final int version = in.readInt();
         switch (version) {
             case VERSION_INIT: {
                 bucketDuration = in.readLong();
-                bucketStart = readLongArray(in);
-                rxBytes = readLongArray(in);
+                bucketStart = readFullLongArray(in);
+                rxBytes = readFullLongArray(in);
                 rxPackets = new long[bucketStart.length];
-                txBytes = readLongArray(in);
+                txBytes = readFullLongArray(in);
                 txPackets = new long[bucketStart.length];
-                operations = new int[bucketStart.length];
+                operations = new long[bucketStart.length];
+                bucketCount = bucketStart.length;
+                break;
+            }
+            case VERSION_ADD_PACKETS: {
+                bucketDuration = in.readLong();
+                bucketStart = readVarLongArray(in);
+                rxBytes = readVarLongArray(in);
+                rxPackets = readVarLongArray(in);
+                txBytes = readVarLongArray(in);
+                txPackets = readVarLongArray(in);
+                operations = readVarLongArray(in);
                 bucketCount = bucketStart.length;
                 break;
             }
@@ -134,12 +155,14 @@
     }
 
     public void writeToStream(DataOutputStream out) throws IOException {
-        // TODO: write packet and operation counts
-        out.writeInt(VERSION_INIT);
+        out.writeInt(VERSION_ADD_PACKETS);
         out.writeLong(bucketDuration);
-        writeLongArray(out, bucketStart, bucketCount);
-        writeLongArray(out, rxBytes, bucketCount);
-        writeLongArray(out, txBytes, bucketCount);
+        writeVarLongArray(out, bucketStart, bucketCount);
+        writeVarLongArray(out, rxBytes, bucketCount);
+        writeVarLongArray(out, rxPackets, bucketCount);
+        writeVarLongArray(out, txBytes, bucketCount);
+        writeVarLongArray(out, txPackets, bucketCount);
+        writeVarLongArray(out, operations, bucketCount);
     }
 
     /** {@inheritDoc} */
@@ -178,11 +201,11 @@
         final Entry entry = recycle != null ? recycle : new Entry();
         entry.bucketStart = bucketStart[i];
         entry.bucketDuration = bucketDuration;
-        entry.rxBytes = rxBytes[i];
-        entry.rxPackets = rxPackets[i];
-        entry.txBytes = txBytes[i];
-        entry.txPackets = txPackets[i];
-        entry.operations = operations[i];
+        entry.rxBytes = getLong(rxBytes, i, UNKNOWN);
+        entry.rxPackets = getLong(rxPackets, i, UNKNOWN);
+        entry.txBytes = getLong(txBytes, i, UNKNOWN);
+        entry.txPackets = getLong(txPackets, i, UNKNOWN);
+        entry.operations = getLong(operations, i, UNKNOWN);
         return entry;
     }
 
@@ -193,7 +216,7 @@
     @Deprecated
     public void recordData(long start, long end, long rxBytes, long txBytes) {
         recordData(start, end,
-                new NetworkStats.Entry(IFACE_ALL, UID_ALL, TAG_NONE, rxBytes, 0L, txBytes, 0L, 0));
+                new NetworkStats.Entry(IFACE_ALL, UID_ALL, TAG_NONE, rxBytes, 0L, txBytes, 0L, 0L));
     }
 
     /**
@@ -230,11 +253,11 @@
             final long fracTxPackets = entry.txPackets * overlap / duration;
             final int fracOperations = (int) (entry.operations * overlap / duration);
 
-            rxBytes[i] += fracRxBytes; entry.rxBytes -= fracRxBytes;
-            rxPackets[i] += fracRxPackets; entry.rxPackets -= fracRxPackets;
-            txBytes[i] += fracTxBytes; entry.txBytes -= fracTxBytes;
-            txPackets[i] += fracTxPackets; entry.txPackets -= fracTxPackets;
-            operations[i] += fracOperations; entry.operations -= fracOperations;
+            addLong(rxBytes, i, fracRxBytes); entry.rxBytes -= fracRxBytes;
+            addLong(rxPackets, i, fracRxPackets); entry.rxPackets -= fracRxPackets;
+            addLong(txBytes, i, fracTxBytes); entry.txBytes -= fracTxBytes;
+            addLong(txPackets, i, fracTxPackets); entry.txPackets -= fracTxPackets;
+            addLong(operations, i, fracOperations); entry.operations -= fracOperations;
 
             duration -= overlap;
         }
@@ -246,16 +269,16 @@
      */
     public void recordEntireHistory(NetworkStatsHistory input) {
         final NetworkStats.Entry entry = new NetworkStats.Entry(
-                IFACE_ALL, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0);
+                IFACE_ALL, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
         for (int i = 0; i < input.bucketCount; i++) {
             final long start = input.bucketStart[i];
             final long end = start + input.bucketDuration;
 
-            entry.rxBytes = input.rxBytes[i];
-            entry.rxPackets = input.rxPackets[i];
-            entry.txBytes = input.txBytes[i];
-            entry.txPackets = input.txPackets[i];
-            entry.operations = input.operations[i];
+            entry.rxBytes = getLong(input.rxBytes, i, 0L);
+            entry.rxPackets = getLong(input.rxPackets, i, 0L);
+            entry.txBytes = getLong(input.txBytes, i, 0L);
+            entry.txPackets = getLong(input.txPackets, i, 0L);
+            entry.operations = getLong(input.operations, i, 0L);
 
             recordData(start, end, entry);
         }
@@ -287,11 +310,11 @@
         if (bucketCount >= bucketStart.length) {
             final int newLength = Math.max(bucketStart.length, 10) * 3 / 2;
             bucketStart = Arrays.copyOf(bucketStart, newLength);
-            rxBytes = Arrays.copyOf(rxBytes, newLength);
-            rxPackets = Arrays.copyOf(rxPackets, newLength);
-            txBytes = Arrays.copyOf(txBytes, newLength);
-            txPackets = Arrays.copyOf(txPackets, newLength);
-            operations = Arrays.copyOf(operations, newLength);
+            if (rxBytes != null) rxBytes = Arrays.copyOf(rxBytes, newLength);
+            if (rxPackets != null) rxPackets = Arrays.copyOf(rxPackets, newLength);
+            if (txBytes != null) txBytes = Arrays.copyOf(txBytes, newLength);
+            if (txPackets != null) txPackets = Arrays.copyOf(txPackets, newLength);
+            if (operations != null) operations = Arrays.copyOf(operations, newLength);
         }
 
         // create gap when inserting bucket in middle
@@ -300,19 +323,19 @@
             final int length = bucketCount - index;
 
             System.arraycopy(bucketStart, index, bucketStart, dstPos, length);
-            System.arraycopy(rxBytes, index, rxBytes, dstPos, length);
-            System.arraycopy(rxPackets, index, rxPackets, dstPos, length);
-            System.arraycopy(txBytes, index, txBytes, dstPos, length);
-            System.arraycopy(txPackets, index, txPackets, dstPos, length);
-            System.arraycopy(operations, index, operations, dstPos, length);
+            if (rxBytes != null) System.arraycopy(rxBytes, index, rxBytes, dstPos, length);
+            if (rxPackets != null) System.arraycopy(rxPackets, index, rxPackets, dstPos, length);
+            if (txBytes != null) System.arraycopy(txBytes, index, txBytes, dstPos, length);
+            if (txPackets != null) System.arraycopy(txPackets, index, txPackets, dstPos, length);
+            if (operations != null) System.arraycopy(operations, index, operations, dstPos, length);
         }
 
         bucketStart[index] = start;
-        rxBytes[index] = 0;
-        rxPackets[index] = 0;
-        txBytes[index] = 0;
-        txPackets[index] = 0;
-        operations[index] = 0;
+        setLong(rxBytes, index, 0L);
+        setLong(rxPackets, index, 0L);
+        setLong(txBytes, index, 0L);
+        setLong(txPackets, index, 0L);
+        setLong(operations, index, 0L);
         bucketCount++;
     }
 
@@ -333,11 +356,11 @@
         if (i > 0) {
             final int length = bucketStart.length;
             bucketStart = Arrays.copyOfRange(bucketStart, i, length);
-            rxBytes = Arrays.copyOfRange(rxBytes, i, length);
-            rxPackets = Arrays.copyOfRange(rxPackets, i, length);
-            txBytes = Arrays.copyOfRange(txBytes, i, length);
-            txPackets = Arrays.copyOfRange(txPackets, i, length);
-            operations = Arrays.copyOfRange(operations, i, length);
+            if (rxBytes != null) rxBytes = Arrays.copyOfRange(rxBytes, i, length);
+            if (rxPackets != null) rxPackets = Arrays.copyOfRange(rxPackets, i, length);
+            if (txBytes != null) txBytes = Arrays.copyOfRange(txBytes, i, length);
+            if (txPackets != null) txPackets = Arrays.copyOfRange(txPackets, i, length);
+            if (operations != null) operations = Arrays.copyOfRange(operations, i, length);
             bucketCount -= i;
         }
     }
@@ -358,11 +381,11 @@
         final Entry entry = recycle != null ? recycle : new Entry();
         entry.bucketStart = start;
         entry.bucketDuration = end - start;
-        entry.rxBytes = 0;
-        entry.rxPackets = 0;
-        entry.txBytes = 0;
-        entry.txPackets = 0;
-        entry.operations = 0;
+        entry.rxBytes = rxBytes != null ? 0 : UNKNOWN;
+        entry.rxPackets = rxPackets != null ? 0 : UNKNOWN;
+        entry.txBytes = txBytes != null ? 0 : UNKNOWN;
+        entry.txPackets = txPackets != null ? 0 : UNKNOWN;
+        entry.operations = operations != null ? 0 : UNKNOWN;
 
         for (int i = bucketCount - 1; i >= 0; i--) {
             final long curStart = bucketStart[i];
@@ -380,11 +403,11 @@
             if (overlap <= 0) continue;
 
             // integer math each time is faster than floating point
-            entry.rxBytes += rxBytes[i] * overlap / bucketDuration;
-            entry.rxPackets += rxPackets[i] * overlap / bucketDuration;
-            entry.txBytes += txBytes[i] * overlap / bucketDuration;
-            entry.txPackets += txPackets[i] * overlap / bucketDuration;
-            entry.operations += operations[i] * overlap / bucketDuration;
+            if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketDuration;
+            if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketDuration;
+            if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketDuration;
+            if (txPackets != null) entry.txPackets += txPackets[i] * overlap / bucketDuration;
+            if (operations != null) entry.operations += operations[i] * overlap / bucketDuration;
         }
 
         return entry;
@@ -394,19 +417,29 @@
      * @deprecated only for temporary testing
      */
     @Deprecated
-    public void generateRandom(long start, long end, long rx, long tx) {
+    public void generateRandom(long start, long end, long rxBytes, long rxPackets, long txBytes,
+            long txPackets, long operations) {
         ensureBuckets(start, end);
 
         final NetworkStats.Entry entry = new NetworkStats.Entry(
-                IFACE_ALL, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0);
+                IFACE_ALL, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
         final Random r = new Random();
-        while (rx > 1024 && tx > 1024) {
+        while (rxBytes > 1024 && rxPackets > 128 && txBytes > 1024 && txPackets > 128
+                && operations > 32) {
             final long curStart = randomLong(r, start, end);
             final long curEnd = randomLong(r, curStart, end);
-            entry.rxBytes = randomLong(r, 0, rx);
-            entry.txBytes = randomLong(r, 0, tx);
-            rx -= entry.rxBytes;
-            tx -= entry.txBytes;
+
+            entry.rxBytes = randomLong(r, 0, rxBytes);
+            entry.rxPackets = randomLong(r, 0, rxPackets);
+            entry.txBytes = randomLong(r, 0, txBytes);
+            entry.txPackets = randomLong(r, 0, txPackets);
+            entry.operations = randomLong(r, 0, operations);
+
+            rxBytes -= entry.rxBytes;
+            rxPackets -= entry.rxPackets;
+            txBytes -= entry.txBytes;
+            txPackets -= entry.txPackets;
+            operations -= entry.operations;
 
             recordData(curStart, curEnd, entry);
         }
@@ -429,11 +462,12 @@
         for (int i = start; i < bucketCount; i++) {
             pw.print(prefix);
             pw.print("  bucketStart="); pw.print(bucketStart[i]);
-            pw.print(" rxBytes="); pw.print(rxBytes[i]);
-            pw.print(" rxPackets="); pw.print(rxPackets[i]);
-            pw.print(" txBytes="); pw.print(txBytes[i]);
-            pw.print(" txPackets="); pw.print(txPackets[i]);
-            pw.print(" operations="); pw.println(operations[i]);
+            if (rxBytes != null) pw.print(" rxBytes="); pw.print(rxBytes[i]);
+            if (rxPackets != null) pw.print(" rxPackets="); pw.print(rxPackets[i]);
+            if (txBytes != null) pw.print(" txBytes="); pw.print(txBytes[i]);
+            if (txPackets != null) pw.print(" txPackets="); pw.print(txPackets[i]);
+            if (operations != null) pw.print(" operations="); pw.print(operations[i]);
+            pw.println();
         }
     }
 
@@ -454,12 +488,25 @@
         }
     };
 
+    private static long getLong(long[] array, int i, long value) {
+        return array != null ? array[i] : value;
+    }
+
+    private static void setLong(long[] array, int i, long value) {
+        if (array != null) array[i] = value;
+    }
+
+    private static void addLong(long[] array, int i, long value) {
+        if (array != null) array[i] += value;
+    }
+
     /**
      * Utility methods for interacting with {@link DataInputStream} and
      * {@link DataOutputStream}, mostly dealing with writing partial arrays.
      */
     public static class DataStreamUtils {
-        public static long[] readLongArray(DataInputStream in) throws IOException {
+        @Deprecated
+        public static long[] readFullLongArray(DataInputStream in) throws IOException {
             final int size = in.readInt();
             final long[] values = new long[size];
             for (int i = 0; i < values.length; i++) {
@@ -468,14 +515,59 @@
             return values;
         }
 
-        public static void writeLongArray(DataOutputStream out, long[] values, int size)
+        /**
+         * Read variable-length {@link Long} using protobuf-style approach.
+         */
+        public static long readVarLong(DataInputStream in) throws IOException {
+            int shift = 0;
+            long result = 0;
+            while (shift < 64) {
+                byte b = in.readByte();
+                result |= (long) (b & 0x7F) << shift;
+                if ((b & 0x80) == 0)
+                    return result;
+                shift += 7;
+            }
+            throw new ProtocolException("malformed long");
+        }
+
+        /**
+         * Write variable-length {@link Long} using protobuf-style approach.
+         */
+        public static void writeVarLong(DataOutputStream out, long value) throws IOException {
+            while (true) {
+                if ((value & ~0x7FL) == 0) {
+                    out.writeByte((int) value);
+                    return;
+                } else {
+                    out.writeByte(((int) value & 0x7F) | 0x80);
+                    value >>>= 7;
+                }
+            }
+        }
+
+        public static long[] readVarLongArray(DataInputStream in) throws IOException {
+            final int size = in.readInt();
+            if (size == -1) return null;
+            final long[] values = new long[size];
+            for (int i = 0; i < values.length; i++) {
+                values[i] = readVarLong(in);
+            }
+            return values;
+        }
+
+        public static void writeVarLongArray(DataOutputStream out, long[] values, int size)
                 throws IOException {
+            if (values == null) {
+                out.writeInt(-1);
+                return;
+            }
             if (size > values.length) {
                 throw new IllegalArgumentException("size larger than length");
             }
             out.writeInt(size);
             for (int i = 0; i < size; i++) {
-                out.writeLong(values[i]);
+                writeVarLong(out, values[i]);
             }
         }
     }
@@ -487,6 +579,7 @@
     public static class ParcelUtils {
         public static long[] readLongArray(Parcel in) {
             final int size = in.readInt();
+            if (size == -1) return null;
             final long[] values = new long[size];
             for (int i = 0; i < values.length; i++) {
                 values[i] = in.readLong();
@@ -495,6 +588,10 @@
         }
 
         public static void writeLongArray(Parcel out, long[] values, int size) {
+            if (values == null) {
+                out.writeInt(-1);
+                return;
+            }
             if (size > values.length) {
                 throw new IllegalArgumentException("size larger than length");
             }
@@ -503,25 +600,6 @@
                 out.writeLong(values[i]);
             }
         }
-
-        public static int[] readIntArray(Parcel in) {
-            final int size = in.readInt();
-            final int[] values = new int[size];
-            for (int i = 0; i < values.length; i++) {
-                values[i] = in.readInt();
-            }
-            return values;
-        }
-
-        public static void writeIntArray(Parcel out, int[] values, int size) {
-            if (size > values.length) {
-                throw new IllegalArgumentException("size larger than length");
-            }
-            out.writeInt(size);
-            for (int i = 0; i < size; i++) {
-                out.writeInt(values[i]);
-            }
-        }
     }
 
 }
diff --git a/core/java/android/net/VpnBuilder.java b/core/java/android/net/VpnBuilder.java
deleted file mode 100644
index 4582523..0000000
--- a/core/java/android/net/VpnBuilder.java
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-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/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index b668f30..6ba3451 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -21,6 +21,7 @@
 import android.os.Parcelable;
 
 import java.lang.UnsupportedOperationException;
+import java.nio.charset.Charset;
 import java.nio.charset.Charsets;
 import java.util.Arrays;
 
@@ -139,6 +140,22 @@
      */
     public static final byte[] RTD_HANDOVER_SELECT = {0x48, 0x73}; // "Hs"
 
+    /**
+     * RTD Android app type. For use with TNF_EXTERNAL.
+     * <p>
+     * The payload of a record with type RTD_ANDROID_APP
+     * should be the package name identifying an application.
+     * Multiple RTD_ANDROID_APP records may be included
+     * in a single {@link NdefMessage}.
+     * <p>
+     * Use {@link #createApplicationRecord(String)} to create
+     * RTD_ANDROID_APP records.
+     * @hide
+     */
+    // TODO unhide for ICS
+    // TODO recheck docs
+    public static final byte[] RTD_ANDROID_APP = "android.com:pkg".getBytes();
+
     private static final byte FLAG_MB = (byte) 0x80;
     private static final byte FLAG_ME = (byte) 0x40;
     private static final byte FLAG_CF = (byte) 0x20;
@@ -333,6 +350,29 @@
     }
 
     /**
+     * Creates an Android application NDEF record.
+     * <p>
+     * When an Android device dispatches an {@link NdefMessage}
+     * containing one or more Android application records,
+     * the applications contained in those records will be the
+     * preferred target for the NDEF_DISCOVERED intent, in
+     * the order in which they appear in the {@link NdefMessage}.
+     * <p>
+     * If none of the applications are installed on the device,
+     * a Market link will be opened to the first application.
+     * <p>
+     * Note that Android application records do not overrule
+     * applications that have called {@link NfcAdapter#enableForegroundDispatch}.
+     * @hide
+     */
+    // TODO unhide for ICS
+    // TODO recheck javadoc - should mention this works from ICS only
+    public static NdefRecord createApplicationRecord(String packageName) {
+        return new NdefRecord(TNF_EXTERNAL_TYPE, RTD_ANDROID_APP, new byte[] {},
+                packageName.getBytes(Charsets.US_ASCII));
+    }
+
+    /**
      * Creates an NDEF record of well known type URI.
      */
     public static NdefRecord createUri(Uri uri) {
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 3704248..bc4e00c 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -240,6 +240,11 @@
     void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces);
 
     /**
+     * Return status of bandwidth control module.
+     */
+    boolean isBandwidthControlEnabled();
+
+    /**
      * Configures bandwidth throttling on an interface.
      */
     void setInterfaceThrottle(String iface, int rxKbps, int txKbps);
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 5217624..814f50b 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -41,7 +41,7 @@
  * </ul>
  *
  * <P> The minimum permission needed to access this content provider is
- * {@link Manifest.permission#READ_WRITE_OWN_VOICEMAIL}
+ * {@link Manifest.permission#ADD_VOICEMAIL}
  *
  * <P>Voicemails are inserted by what is called as a "voicemail source"
  * application, which is responsible for syncing voicemail data between a remote
diff --git a/core/java/android/server/BluetoothAdapterStateMachine.java b/core/java/android/server/BluetoothAdapterStateMachine.java
index cb18ade..031375e 100644
--- a/core/java/android/server/BluetoothAdapterStateMachine.java
+++ b/core/java/android/server/BluetoothAdapterStateMachine.java
@@ -39,7 +39,7 @@
  *                         (BluetootOn)<----------------------<-
  *                           |    ^    -------------------->-  |
  *                           |    |                         |  |
- *                 TURN_OFF  |    | BECAME_PAIRABLE     m1 |  | USER_TURN_ON
+ *                 TURN_OFF  |    | BECAME_PAIRABLE      m1 |  | USER_TURN_ON
  *         AIRPLANE_MODE_ON  |    |                         |  |
  *                           V    |                         |  |
  *                         (Switching)                   (PerProcessState)
@@ -47,7 +47,7 @@
  *     BECAME_NON_PAIRABLE&  |    | TURN_ON(_CONTINUE)      |  |
  * ALL_DEVICES_DISCONNECTED  |    |                     m2  |  |
  *                           V    |------------------------<   | BECAME_PAIRABLE
- *                          (HotOff)---------------------------- PER_PROCESS_TURN_ON
+ *                          (HotOff)-------------------------->- PER_PROCESS_TURN_ON
  *                           /    ^
  *                          /     |  SERVICE_RECORD_LOADED
  *                         |      |
@@ -59,7 +59,7 @@
  *                           (PowerOff)   <----- initial state
  *
  * Legend:
- * m1 = USER_TURN_OFF
+ * m1 = TURN_HOT
  * m2 = Transition to HotOff when number of process wanting BT on is 0.
  *      BECAME_NON_PAIRABLE will make the transition.
  */
@@ -73,6 +73,9 @@
     static final int USER_TURN_ON = 1;
     // We get this message when user tries to turn off BT
     static final int USER_TURN_OFF = 2;
+    // Per process enable / disable messages
+    static final int PER_PROCESS_TURN_ON = 3;
+    static final int PER_PROCESS_TURN_OFF = 4;
 
     // Message(what) to report a event that the state machine need to respond to
     //
@@ -102,9 +105,8 @@
     private static final int TURN_ON_CONTINUE = 102;
     // Unload firmware, turning off Bluetooth module power
     private static final int TURN_COLD = 103;
-    // Per process enable / disable messages
-    static final int PER_PROCESS_TURN_ON = 104;
-    static final int PER_PROCESS_TURN_OFF = 105;
+    // Device disconnecting timeout happens
+    private static final int DEVICES_DISCONNECT_TIMEOUT = 104;
 
     private Context mContext;
     private BluetoothService mBluetoothService;
@@ -120,6 +122,9 @@
     // this is the BluetoothAdapter state that reported externally
     private int mPublicState;
 
+    // timeout value waiting for all the devices to be disconnected
+    private static final int DEVICES_DISCONNECT_TIMEOUT_TIME = 3000;
+
     BluetoothAdapterStateMachine(Context context, BluetoothService bluetoothService,
                                  BluetoothAdapter bluetoothAdapter) {
         super(TAG);
@@ -214,8 +219,9 @@
                 case PER_PROCESS_TURN_OFF:
                     perProcessCallback(false, (IBluetoothStateChangeCallback) message.obj);
                     break;
-                case AIRPLANE_MODE_ON:
-                case USER_TURN_OFF: // ignore
+                case USER_TURN_OFF:
+                    Log.w(TAG, "PowerOff received: " + message.what);
+                case AIRPLANE_MODE_ON: // ignore
                     break;
                 default:
                     return NOT_HANDLED;
@@ -301,7 +307,8 @@
                 case PER_PROCESS_TURN_OFF:
                     deferMessage(message);
                     break;
-                case USER_TURN_OFF: // ignore
+                case USER_TURN_OFF:
+                    Log.w(TAG, "WarmUp received: " + message.what);
                     break;
                 default:
                     return NOT_HANDLED;
@@ -344,7 +351,6 @@
                     mBluetoothService.shutoffBluetooth();
                     mEventLoop.stop();
                     transitionTo(mPowerOff);
-                    // ASSERT no support of config_bluetooth_adapter_quick_switch
                     broadcastState(BluetoothAdapter.STATE_OFF);
                     break;
                 case AIRPLANE_MODE_OFF:
@@ -354,8 +360,6 @@
                         broadcastState(BluetoothAdapter.STATE_TURNING_ON);
                     }
                     break;
-                case USER_TURN_OFF: // ignore
-                    break;
                 case PER_PROCESS_TURN_ON:
                     transitionTo(mPerProcessState);
 
@@ -368,6 +372,8 @@
                 case PER_PROCESS_TURN_OFF:
                     perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
                     break;
+                case USER_TURN_OFF: // ignore
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -399,16 +405,28 @@
                 case BECAME_NON_PAIRABLE:
                     if (mBluetoothService.getAdapterConnectionState() ==
                         BluetoothAdapter.STATE_DISCONNECTED) {
+                        removeMessages(DEVICES_DISCONNECT_TIMEOUT);
                         transitionTo(mHotOff);
                         finishSwitchingOff();
                     }
                     break;
                 case ALL_DEVICES_DISCONNECTED:
+                    removeMessages(DEVICES_DISCONNECT_TIMEOUT);
                     if (mBluetoothService.getScanMode() == BluetoothAdapter.SCAN_MODE_NONE) {
                         transitionTo(mHotOff);
                         finishSwitchingOff();
                     }
                     break;
+                case DEVICES_DISCONNECT_TIMEOUT:
+                    sendMessage(ALL_DEVICES_DISCONNECTED);
+                    // reset the hardware for error recovery
+                    Log.e(TAG, "Devices failed to disconnect, reseting...");
+                    deferMessage(obtainMessage(TURN_COLD));
+                    if (mContext.getResources().getBoolean
+                        (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+                        deferMessage(obtainMessage(TURN_HOT));
+                    }
+                    break;
                 case USER_TURN_ON:
                 case AIRPLANE_MODE_OFF:
                 case AIRPLANE_MODE_ON:
@@ -457,7 +475,7 @@
                     }
                     if (!mBluetoothService.isApplicationStateChangeTrackerEmpty()) {
                         transitionTo(mPerProcessState);
-                        deferMessage(obtainMessage(USER_TURN_OFF));
+                        deferMessage(obtainMessage(TURN_HOT));
                         break;
                     }
                     //$FALL-THROUGH$ to AIRPLANE_MODE_ON
@@ -466,6 +484,7 @@
                     broadcastState(BluetoothAdapter.STATE_TURNING_OFF);
                     mBluetoothService.switchConnectable(false);
                     mBluetoothService.disconnectDevices();
+                    sendMessageDelayed(DEVICES_DISCONNECT_TIMEOUT, DEVICES_DISCONNECT_TIMEOUT_TIME);
 
                     // we turn all the way to PowerOff with AIRPLANE_MODE_ON
                     if (message.what == AIRPLANE_MODE_ON) {
@@ -474,8 +493,9 @@
                         deferMessage(obtainMessage(AIRPLANE_MODE_ON));
                     }
                     break;
-                case AIRPLANE_MODE_OFF: // ignore
-                case USER_TURN_ON: // ignore
+                case AIRPLANE_MODE_OFF:
+                case USER_TURN_ON:
+                    Log.w(TAG, "BluetoothOn received: " + message.what);
                     break;
                 case PER_PROCESS_TURN_ON:
                     perProcessCallback(true, (IBluetoothStateChangeCallback)message.obj);
@@ -526,19 +546,34 @@
                     // run bluetooth now that it's turned on
                     mBluetoothService.runBluetooth();
                     break;
-               case USER_TURN_OFF:
+                case TURN_HOT:
                     broadcastState(BluetoothAdapter.STATE_TURNING_OFF);
                     if (mBluetoothService.getAdapterConnectionState() !=
                         BluetoothAdapter.STATE_DISCONNECTED) {
                         mBluetoothService.disconnectDevices();
+                        sendMessageDelayed(DEVICES_DISCONNECT_TIMEOUT,
+                                           DEVICES_DISCONNECT_TIMEOUT_TIME);
                         break;
                     }
                     //$FALL-THROUGH$ all devices are already disconnected
                 case ALL_DEVICES_DISCONNECTED:
+                    removeMessages(DEVICES_DISCONNECT_TIMEOUT);
                     mBluetoothService.finishDisable();
                     broadcastState(BluetoothAdapter.STATE_OFF);
                     break;
-               case PER_PROCESS_TURN_OFF:
+                case DEVICES_DISCONNECT_TIMEOUT:
+                    mBluetoothService.finishDisable();
+                    broadcastState(BluetoothAdapter.STATE_OFF);
+                    Log.e(TAG, "Devices fail to disconnect, reseting...");
+                    transitionTo(mHotOff);
+                    deferMessage(obtainMessage(TURN_COLD));
+                    for (IBluetoothStateChangeCallback c:
+                             mBluetoothService.getApplicationStateChangeCallbacks()) {
+                        perProcessCallback(false, c);
+                        deferMessage(obtainMessage(PER_PROCESS_TURN_ON, c));
+                    }
+                    break;
+                case PER_PROCESS_TURN_OFF:
                     perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
                     if (mBluetoothService.isApplicationStateChangeTrackerEmpty()) {
                         mBluetoothService.switchConnectable(false);
@@ -557,6 +592,9 @@
                     // we turn all the way to PowerOff with AIRPLANE_MODE_ON
                     deferMessage(obtainMessage(AIRPLANE_MODE_ON));
                     break;
+                case USER_TURN_OFF:
+                    Log.w(TAG, "PerProcessState received: " + message.what);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
diff --git a/core/java/android/server/BluetoothPanProfileHandler.java b/core/java/android/server/BluetoothPanProfileHandler.java
index ff22a45..37cfdc4 100644
--- a/core/java/android/server/BluetoothPanProfileHandler.java
+++ b/core/java/android/server/BluetoothPanProfileHandler.java
@@ -145,13 +145,14 @@
             return false;
         }
 
-        handlePanDeviceStateChange(device, BluetoothPan.STATE_CONNECTING,
+        // Send interface as null as it is not known
+        handlePanDeviceStateChange(device, null, BluetoothPan.STATE_CONNECTING,
                                            BluetoothPan.LOCAL_PANU_ROLE);
         if (mBluetoothService.connectPanDeviceNative(objectPath, "nap")) {
             debugLog("connecting to PAN");
             return true;
         } else {
-            handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTED,
+            handlePanDeviceStateChange(device, null, BluetoothPan.STATE_DISCONNECTED,
                                                 BluetoothPan.LOCAL_PANU_ROLE);
             errorLog("could not connect to PAN");
             return false;
@@ -168,8 +169,8 @@
                     panDevice.mLocalRole == BluetoothPan.LOCAL_NAP_ROLE) {
                 String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
 
-                handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTING,
-                        panDevice.mLocalRole);
+                handlePanDeviceStateChange(device, panDevice.mIface,
+                        BluetoothPan.STATE_DISCONNECTING, panDevice.mLocalRole);
 
                 if (!mBluetoothService.disconnectPanServerDeviceNative(objectPath,
                         device.getAddress(),
@@ -177,7 +178,7 @@
                     errorLog("could not disconnect Pan Server Device "+device.getAddress());
 
                     // Restore prev state
-                    handlePanDeviceStateChange(device, state,
+                    handlePanDeviceStateChange(device, panDevice.mIface, state,
                             panDevice.mLocalRole);
 
                     return false;
@@ -230,19 +231,19 @@
             return false;
         }
 
-        handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTING,
+        handlePanDeviceStateChange(device, panDevice.mIface, BluetoothPan.STATE_DISCONNECTING,
                                     panDevice.mLocalRole);
         if (panDevice.mLocalRole == BluetoothPan.LOCAL_NAP_ROLE) {
             if (!mBluetoothService.disconnectPanServerDeviceNative(objectPath, device.getAddress(),
                     panDevice.mIface)) {
                 // Restore prev state, this shouldn't happen
-                handlePanDeviceStateChange(device, state, panDevice.mLocalRole);
+                handlePanDeviceStateChange(device, panDevice.mIface, state, panDevice.mLocalRole);
                 return false;
             }
         } else {
             if (!mBluetoothService.disconnectPanDeviceNative(objectPath)) {
                 // Restore prev state, this shouldn't happen
-                handlePanDeviceStateChange(device, state, panDevice.mLocalRole);
+                handlePanDeviceStateChange(device, panDevice.mIface, state, panDevice.mLocalRole);
                 return false;
             }
         }
@@ -305,11 +306,6 @@
         mBluetoothService.sendConnectionStateChange(device, state, prevState);
     }
 
-    void handlePanDeviceStateChange(BluetoothDevice device,
-                                                 int state, int role) {
-        handlePanDeviceStateChange(device, null, state, role);
-    }
-
     private class BluetoothPanDevice {
         private int mState;
         private String mIfaceAddr;
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 28546dc..3029c9d 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -1565,6 +1565,8 @@
     @Override
     public boolean changeApplicationBluetoothState(boolean on,
             IBluetoothStateChangeCallback callback, IBinder binder) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+
         int pid = Binder.getCallingPid();
         //mStateChangeTracker is a synchronized map
         if (!mStateChangeTracker.containsKey(pid)) {
diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java
index 6f70ab8..3e2e38e 100644
--- a/core/java/android/service/textservice/SpellCheckerService.java
+++ b/core/java/android/service/textservice/SpellCheckerService.java
@@ -22,6 +22,7 @@
 
 import android.app.Service;
 import android.content.Intent;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
@@ -43,45 +44,6 @@
 
     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
@@ -95,36 +57,125 @@
         return mBinder;
     }
 
-    private static class SpellCheckerSessionImpl extends ISpellCheckerSession.Stub {
-        private final WeakReference<SpellCheckerService> mInternalServiceRef;
-        private final String mLocale;
-        private final ISpellCheckerSessionListener mListener;
+    /**
+     * Factory method to create a spell checker session impl
+     * @return SpellCheckerSessionImpl which should be overridden by a concrete implementation.
+     */
+    public abstract Session createSession();
 
-        public SpellCheckerSessionImpl(
-                SpellCheckerService service, String locale, ISpellCheckerSessionListener listener) {
-            mInternalServiceRef = new WeakReference<SpellCheckerService>(service);
-            mLocale = locale;
+    /**
+     * This abstract class should be overridden by a concrete implementation of a spell checker.
+     */
+    public abstract class Session {
+        private InternalISpellCheckerSession mInternalSession;
+
+        /**
+         * @hide
+         */
+        public final void setInternalISpellCheckerSession(InternalISpellCheckerSession session) {
+            mInternalSession = session;
+        }
+
+        /**
+         * This is called after the class is initialized, at which point it knows it can call
+         * getLocale() etc...
+         */
+        public abstract void onCreate();
+
+        /**
+         * 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
+         * @return SuggestionInfo which contains suggestions for textInfo
+         */
+        public abstract SuggestionsInfo onGetSuggestions(TextInfo textInfo, int suggestionsLimit);
+
+        /**
+         * 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 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[] onGetSuggestionsMultiple(TextInfo[] textInfos,
+                int suggestionsLimit, boolean sequentialWords) {
+            final int length = textInfos.length;
+            final SuggestionsInfo[] retval = new SuggestionsInfo[length];
+            for (int i = 0; i < length; ++i) {
+                retval[i] = onGetSuggestions(textInfos[i], suggestionsLimit);
+                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 onCancel() {}
+
+        /**
+         * @return Locale for this session
+         */
+        public String getLocale() {
+            return mInternalSession.getLocale();
+        }
+
+        /**
+         * @return Bundle for this session
+         */
+        public Bundle getBundle() {
+            return mInternalSession.getBundle();
+        }
+    }
+
+    // Preventing from exposing ISpellCheckerSession.aidl, create an internal class.
+    private static class InternalISpellCheckerSession extends ISpellCheckerSession.Stub {
+        private final ISpellCheckerSessionListener mListener;
+        private final Session mSession;
+        private final String mLocale;
+        private final Bundle mBundle;
+
+        public InternalISpellCheckerSession(String locale, ISpellCheckerSessionListener listener,
+                Bundle bundle, Session session) {
             mListener = listener;
+            mSession = session;
+            mLocale = locale;
+            mBundle = bundle;
+            session.setInternalISpellCheckerSession(this);
         }
 
         @Override
-        public void getSuggestionsMultiple(
+        public void onGetSuggestionsMultiple(
                 TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) {
-            final SpellCheckerService service = mInternalServiceRef.get();
-            if (service == null) return;
             try {
                 mListener.onGetSuggestions(
-                        service.getSuggestionsMultiple(textInfos, mLocale,
-                                suggestionsLimit, sequentialWords));
+                        mSession.onGetSuggestionsMultiple(
+                                textInfos, suggestionsLimit, sequentialWords));
             } catch (RemoteException e) {
             }
         }
 
         @Override
-        public void cancel() {
-            final SpellCheckerService service = mInternalServiceRef.get();
-            if (service == null) return;
-            service.cancel();
+        public void onCancel() {
+            mSession.onCancel();
+        }
+
+        public String getLocale() {
+            return mLocale;
+        }
+
+        public Bundle getBundle() {
+            return mBundle;
         }
     }
 
@@ -137,10 +188,14 @@
 
         @Override
         public ISpellCheckerSession getISpellCheckerSession(
-                String locale, ISpellCheckerSessionListener listener) {
+                String locale, ISpellCheckerSessionListener listener, Bundle bundle) {
             final SpellCheckerService service = mInternalServiceRef.get();
             if (service == null) return null;
-            return new SpellCheckerSessionImpl(service, locale, listener);
+            final Session session = service.createSession();
+            final InternalISpellCheckerSession internalSession =
+                    new InternalISpellCheckerSession(locale, listener, bundle, session);
+            session.onCreate();
+            return internalSession;
         }
     }
 }
diff --git a/core/java/android/text/TextDirectionHeuristics.java b/core/java/android/text/TextDirectionHeuristics.java
index 5f9ffc5..20170bf 100644
--- a/core/java/android/text/TextDirectionHeuristics.java
+++ b/core/java/android/text/TextDirectionHeuristics.java
@@ -164,6 +164,7 @@
             case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
             case Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING:
             case Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE:
+            case Character.DIRECTIONALITY_ARABIC_NUMBER:
                 return TriState.TRUE;
             default:
                 return TriState.UNKNOWN;
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 836867b..7a96a50 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -29,30 +29,84 @@
     private static final String LOG_TAG = "Surface";
     private static final boolean DEBUG_RELEASE = false;
     
+    /* orientations for setOrientation() */
+    public static final int ROTATION_0       = 0;
+    public static final int ROTATION_90      = 1;
+    public static final int ROTATION_180     = 2;
+    public static final int ROTATION_270     = 3;
+
+    /**
+     * Does this object hold a valid surface?  Returns true if it holds
+     * a physical surface, so lockCanvas() will succeed.  Otherwise
+     * returns false.
+     */
+    public native   boolean isValid();
+
+    /** Release the local reference to the server-side surface.  
+     * Always call release() when you're done with a Surface. This will
+     * make the surface invalid.
+     */
+    public native void release();
+
+    /** draw into a surface */
+    public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException, IllegalArgumentException {
+        /*
+         * the dirty rectangle may be expanded to the surface's size, if for
+         * instance it has been resized or if the bits were lost, since the last
+         * call.
+         */
+        return lockCanvasNative(dirty);
+    }
+
+    /** unlock the surface and asks a page flip */
+    public native   void unlockCanvasAndPost(Canvas canvas);
+
+    /** 
+     * unlock the surface. the screen won't be updated until
+     * post() or postAll() is called
+     */
+    public native   void unlockCanvas(Canvas canvas);
+
+    @Override
+    public String toString() {
+        return "Surface(name=" + mName + ", identity=" + getIdentity() + ")";
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public native   void readFromParcel(Parcel source);
+    public native   void writeToParcel(Parcel dest, int flags);
+
+    /**
+     * Exception thrown when a surface couldn't be created or resized
+     */
+    public static class OutOfResourcesException extends Exception {
+        public OutOfResourcesException() {
+        }
+        public OutOfResourcesException(String name) {
+            super(name);
+        }
+    }
+    
+    /*
+     * -----------------------------------------------------------------------
+     * No user serviceable parts beyond this point
+     * -----------------------------------------------------------------------
+     */
+
     /* flags used in constructor (keep in sync with ISurfaceComposer.h) */
 
-    /** Surface is created hidden */
+    /** Surface is created hidden @hide */
     public static final int HIDDEN              = 0x00000004;
 
-    /** The surface is to be used by hardware accelerators or DMA engines 
-     * @deprecated this is ignored, this value is set automatically when needed.
-     */
-    @Deprecated
-    public static final int HARDWARE            = 0x00000010;
-
-    /** Implies "HARDWARE", the surface is to be used by the GPU;
-     * additionally the backbuffer is never preserved for these
-     * surfaces. 
-     * @deprecated this is ignored, this value is set automatically when needed.
-     */
-    @Deprecated
-    public static final int GPU                 = 0x00000028;
-
     /** The surface contains secure content, special measures will
      * be taken to disallow the surface's content to be copied from
      * another process. In particular, screenshots and VNC servers will
      * be disabled, but other measures can take place, for instance the
-     * surface might not be hardware accelerated. */
+     * surface might not be hardware accelerated. 
+     * @hide*/
     public static final int SECURE              = 0x00000080;
     
     /** Creates a surface where color components are interpreted as 
@@ -75,20 +129,11 @@
      *  
      *  In some rare situations, a non pre-multiplied surface is preferable.
      *  
+     *  @hide
      */
     public static final int NON_PREMULTIPLIED   = 0x00000100;
     
     /**
-     * Creates a surface without a rendering buffer. Instead, the content
-     * of the surface must be pushed by an external entity. This type
-     * of surface can be used for efficient camera preview or movie
-     * playback.
-     *
-     * @deprecated not support by the system anymore
-     */
-    @Deprecated
-    public static final int PUSH_BUFFERS        = 0x00000200;
-    /**
      * Indicates that the surface must be considered opaque, even if its
      * pixel format is set to translucent. This can be useful if an
      * application needs full RGBA 8888 support for instance but will
@@ -109,7 +154,7 @@
 
     // 0x1000 is reserved for an independent DRM protected flag in framework
 
-    /** Creates a normal surface. This is the default. */
+    /** Creates a normal surface. This is the default. @hide */
     public static final int FX_SURFACE_NORMAL   = 0x00000000;
     
     /** Creates a Blur surface. Everything behind this surface is blurred
@@ -117,6 +162,7 @@
      * is not settable or guaranteed.
      * It is an error to lock a Blur surface, since it doesn't have
      * a backing store.
+     * @hide
      */
     public static final int FX_SURFACE_BLUR     = 0x00010000;
     
@@ -124,55 +170,35 @@
      * by the amount specified in {@link #setAlpha}.
      * It is an error to lock a Dim surface, since it doesn't have
      * a backing store.
+     * @hide
      */
     public static final int FX_SURFACE_DIM     = 0x00020000;
 
-    /** Mask used for FX values above */
+    /** Mask used for FX values above @hide */
     public static final int FX_SURFACE_MASK     = 0x000F0000;
 
     /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */
     
-    /** Hide the surface. Equivalent to calling hide(). */
+    /** Hide the surface. Equivalent to calling hide(). @hide */
     public static final int SURFACE_HIDDEN    = 0x01;
     
-    /** Freeze the surface. Equivalent to calling freeze(). */
+    /** Freeze the surface. Equivalent to calling freeze(). @hide */
     public static final int SURFACE_FROZEN     = 0x02;
 
-    /**
-     * @deprecated Use {@link #SURFACE_FROZEN} instead.
-     */
-    @Deprecated
-    public static final int SURACE_FROZEN     = 0x02;
-
-    /** Enable dithering when compositing this surface */
+    /** Enable dithering when compositing this surface @hide */
     public static final int SURFACE_DITHER    = 0x04;
-
-    public static final int SURFACE_BLUR_FREEZE= 0x10;
-
-    /* orientations for setOrientation() */
-    public static final int ROTATION_0       = 0;
-    public static final int ROTATION_90      = 1;
-    public static final int ROTATION_180     = 2;
-    public static final int ROTATION_270     = 3;
     
-    /** 
-     * Disable the orientation animation 
-     * {@hide} 
-     */
+    /** Disable the orientation animation @hide */
     public static final int FLAGS_ORIENTATION_ANIMATION_DISABLE = 0x000000001;
 
     // The mSurfaceControl will only be present for Surfaces used by the window
     // server or system processes. When this class is parceled we defer to the
-    // mSurfaceControl to do the parceling. Otherwise we parcel the mNativeSurface.
-    @SuppressWarnings("unused")
+    // mSurfaceControl to do the parceling. Otherwise we parcel the
+    // mNativeSurface.
     private int mSurfaceControl;
-    @SuppressWarnings("unused")
     private int mSaveCount;
-    @SuppressWarnings("unused")
     private Canvas mCanvas;
-    @SuppressWarnings("unused")
     private int mNativeSurface;
-    @SuppressWarnings("unused")
     private int mSurfaceGenerationId;
     private String mName;
 
@@ -184,19 +210,8 @@
     // non compatibility mode.
     private Matrix mCompatibleMatrix;
 
-    @SuppressWarnings("unused")
     private Exception mCreationStack;
 
-    /**
-     * Exception thrown when a surface couldn't be created or resized
-     */
-    public static class OutOfResourcesException extends Exception {
-        public OutOfResourcesException() {
-        }
-        public OutOfResourcesException(String name) {
-            super(name);
-        }
-    }
 
     /*
      * We use a class initializer to allow the native code to cache some
@@ -219,10 +234,7 @@
         initFromSurfaceTexture(surfaceTexture);
     }
     
-    /**
-     * create a surface
-     * {@hide}
-     */
+    /** create a surface @hide */
     public Surface(SurfaceSession s,
             int pid, int display, int w, int h, int format, int flags)
         throws OutOfResourcesException {
@@ -233,10 +245,7 @@
         init(s,pid,null,display,w,h,format,flags);
     }
 
-    /**
-     * create a surface with a name
-     * {@hide}
-     */
+    /** create a surface with a name @hide */
     public Surface(SurfaceSession s,
             int pid, String name, int display, int w, int h, int format, int flags)
         throws OutOfResourcesException {
@@ -251,7 +260,7 @@
     /**
      * Create an empty surface, which will later be filled in by
      * readFromParcel().
-     * {@hide}
+     * @hide
      */
     public Surface() {
         if (DEBUG_RELEASE) {
@@ -260,16 +269,35 @@
         mCanvas = new CompatibleCanvas();
     }
 
+    private Surface(Parcel source) throws OutOfResourcesException {
+        init(source);
+    }
+
     /**
-     * A Canvas class that can handle the compatibility mode. This does two things differently.
+     * Copy another surface to this one.  This surface now holds a reference
+     * to the same data as the original surface, and is -not- the owner.
+     * @hide
+     */
+    public native void copyFrom(Surface o);
+    
+    /** @hide */
+    public int getGenerationId() {
+        return mSurfaceGenerationId;
+    }
+
+    /**
+     * A Canvas class that can handle the compatibility mode. This does two
+     * things differently.
      * <ul>
-     *  <li> Returns the width and height of the target metrics, rather than native.
-     *  For example, the canvas returns 320x480 even if an app is running in WVGA high density.
-     *  <li> Scales the matrix in setMatrix by the application scale, except if the matrix looks
-     *  like obtained from getMatrix. This is a hack to handle the case that an application
-     *  uses getMatrix to keep the original matrix, set matrix of its own, then set the original
-     *  matrix back. There is no perfect solution that works for all cases, and there are a lot of
-     *  cases that this model does not work, but we hope this works for many apps.
+     * <li>Returns the width and height of the target metrics, rather than
+     * native. For example, the canvas returns 320x480 even if an app is running
+     * in WVGA high density.
+     * <li>Scales the matrix in setMatrix by the application scale, except if
+     * the matrix looks like obtained from getMatrix. This is a hack to handle
+     * the case that an application uses getMatrix to keep the original matrix,
+     * set matrix of its own, then set the original matrix back. There is no
+     * perfect solution that works for all cases, and there are a lot of cases
+     * that this model does not work, but we hope this works for many apps.
      * </ul>
      */
     private class CompatibleCanvas extends Canvas {
@@ -318,7 +346,8 @@
     }
 
     /**
-     * Sets the translator used to scale canvas's width/height in compatibility mode.
+     * Sets the translator used to scale canvas's width/height in compatibility
+     * mode.
      */
     void setCompatibilityTranslator(Translator translator) {
         if (translator != null) {
@@ -328,73 +357,29 @@
         }
     }
     
-    /**
-     * Copy another surface to this one.  This surface now holds a reference
-     * to the same data as the original surface, and is -not- the owner.
-     * {@hide}
-     */
-    public native   void copyFrom(Surface o);
-    
-    /**
-     * Does this object hold a valid surface?  Returns true if it holds
-     * a physical surface, so lockCanvas() will succeed.  Otherwise
-     * returns false.
-     */
-    public native   boolean isValid();
-
-    /**
-     * @hide
-     */
-    public int getGenerationId() {
-        return mSurfaceGenerationId;
-    }
-    
     /** Free all server-side state associated with this surface and
-     * release this object's reference. {@hide} */
+     * release this object's reference. @hide */
     public native void destroy();
     
-    /** Release the local reference to the server-side surface. @hide */
-    public native void release();
+    private native Canvas lockCanvasNative(Rect dirty);   
     
-    /** draw into a surface */
-    public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException, IllegalArgumentException
-    {
-        /* the dirty rectangle may be expanded to the surface's size, if
-         * for instance it has been resized or if the bits were lost, since
-         * the last call.
-         */
-        return lockCanvasNative(dirty);
-    }
-
-    private native Canvas lockCanvasNative(Rect dirty);
-
-    /** unlock the surface and asks a page flip */
-    public native   void unlockCanvasAndPost(Canvas canvas);
-
-    /** 
-     * unlock the surface. the screen won't be updated until
-     * post() or postAll() is called
+    /*
+     * set display parameters & screenshots
      */
-    public native   void unlockCanvas(Canvas canvas);
     
-    /** start/end a transaction {@hide} */
-    public static native   void openTransaction();
-    /** {@hide} */
-    public static native   void closeTransaction();
-
     /**
      * Freezes the specified display, No updating of the screen will occur
      * until unfreezeDisplay() is called. Everything else works as usual though,
      * in particular transactions.
      * @param display
-     * {@hide}
+     * @hide
      */
     public static native   void freezeDisplay(int display);
 
     /**
      * resume updating the specified display.
      * @param display
-     * {@hide}
+     * @hide
      */
     public static native   void unfreezeDisplay(int display);
 
@@ -403,7 +388,7 @@
      * @param display
      * @param orientation
      * @param flags
-     * {@hide}
+     * @hide
      */
     public static native   void setOrientation(int display, int orientation, int flags);
 
@@ -411,6 +396,7 @@
      * set the orientation of the given display.
      * @param display
      * @param orientation
+     * @hide
      */
     public static void setOrientation(int display, int orientation) {
         setOrientation(display, orientation, 0);
@@ -441,44 +427,43 @@
      */
     public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer);
 
-    /**
+    
+    /*
      * set surface parameters.
      * needs to be inside open/closeTransaction block
      */
+    
+    /** start a transaction @hide */
+    public static native   void openTransaction();
+    /** end a transaction @hide */
+    public static native   void closeTransaction();
+    /** @hide */
     public native   void setLayer(int zorder);
+    /** @hide */
     public native   void setPosition(int x, int y);
+    /** @hide */
     public native   void setSize(int w, int h);
-
+    /** @hide */
     public native   void hide();
+    /** @hide */
     public native   void show();
+    /** @hide */
     public native   void setTransparentRegionHint(Region region);
+    /** @hide */
     public native   void setAlpha(float alpha);
-    public native   void setMatrix(float dsdx, float dtdx,
-                                   float dsdy, float dtdy);
-
+    /** @hide */
+    public native   void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
+    /** @hide */
     public native   void freeze();
+    /** @hide */
     public native   void unfreeze();
-
+    /** @hide */
     public native   void setFreezeTint(int tint);
-
+    /** @hide */
     public native   void setFlags(int flags, int mask);
 
-    @Override
-    public String toString() {
-        return "Surface(name=" + mName + ", identity=" + getIdentity() + ")";
-    }
 
-    private Surface(Parcel source) throws OutOfResourcesException {
-        init(source);
-    }
-    
-    public int describeContents() {
-        return 0;
-    }
-
-    public native   void readFromParcel(Parcel source);
-    public native   void writeToParcel(Parcel dest, int flags);
-    
+   
     public static final Parcelable.Creator<Surface> CREATOR
             = new Parcelable.Creator<Surface>()
     {
@@ -496,7 +481,6 @@
         }
     };
 
-    /* no user serviceable parts here ... */
     @Override
     protected void finalize() throws Throwable {
         try {
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 96d6f09..76aa21f 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -204,6 +204,7 @@
             }
 
             mLayer.destroy();
+            mSurface.release();
             mSurface = null;
             mLayer = null;
         }
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index 08ccd94..662137a 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -26,7 +26,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
 import android.media.AudioService;
 import android.media.AudioSystem;
@@ -36,13 +35,9 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.Vibrator;
-import android.telephony.TelephonyManager;
 import android.util.Log;
 import android.widget.ImageView;
-import android.widget.ProgressBar;
 import android.widget.SeekBar;
-import android.widget.TextView;
-import android.widget.Toast;
 import android.widget.SeekBar.OnSeekBarChangeListener;
 
 import java.util.HashMap;
@@ -52,6 +47,10 @@
  *
  * This code really should be moved elsewhere.
  *
+ * Seriously, it really really should be moved elsewhere.  This is used by
+ * android.media.AudioService, which actually runs in the system process, to
+ * show the volume dialog when the user changes the volume.  What a mess.
+ *
  * @hide
  */
 public class VolumePanel extends Handler implements OnSeekBarChangeListener, View.OnClickListener
@@ -194,7 +193,7 @@
         window.setGravity(Gravity.TOP);
         WindowManager.LayoutParams lp = window.getAttributes();
         lp.token = null;
-        lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
+        lp.type = WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
         window.setAttributes(lp);
         window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
 
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index d1ad113..ff378a6 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -394,6 +394,13 @@
         public static final int TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19;
 
         /**
+         * Window type: The volume level overlay/dialog shown when the user
+         * changes the system volume.
+         * @hide
+         */
+        public static final int TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20;
+
+        /**
          * End of types of system windows.
          */
         public static final int LAST_SYSTEM_WINDOW      = 2999;
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 9be2a67..c93b564 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -784,7 +784,7 @@
                 builder.append("\n");
             }
         } else {
-            builder.append("; recordCount: ").append(getAddedCount());
+            builder.append("; recordCount: ").append(getRecordCount());
         }
         return builder.toString();
     }
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index bf07e71..b940b80 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -233,7 +233,7 @@
                 Log.w(TAG, "Cancel spell checker tasks.");
             }
             try {
-                mISpellCheckerSession.cancel();
+                mISpellCheckerSession.onCancel();
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to cancel " + e);
             }
@@ -247,7 +247,7 @@
                 Log.w(TAG, "Get suggestions from the spell checker.");
             }
             try {
-                mISpellCheckerSession.getSuggestionsMultiple(
+                mISpellCheckerSession.onGetSuggestionsMultiple(
                         scp.mTextInfos, scp.mSuggestionsLimit, scp.mSequentialWords);
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to get suggestions " + e);
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index a60eb24..d60ce4f 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -19,11 +19,11 @@
 import com.android.internal.textservice.ITextServicesManager;
 
 import android.content.Context;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Log;
-import android.view.textservice.SpellCheckerSession;
 import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener;
 
 import java.util.Locale;
@@ -74,7 +74,7 @@
      */
     // TODO: Add a method to get enabled spell checkers.
     // TODO: Handle referToSpellCheckerLanguageSettings
-    public SpellCheckerSession newSpellCheckerSession(Locale locale,
+    public SpellCheckerSession newSpellCheckerSession(Bundle bundle, Locale locale,
             SpellCheckerSessionListener listener, boolean referToSpellCheckerLanguageSettings) {
         if (listener == null) {
             throw new NullPointerException();
@@ -94,7 +94,7 @@
         try {
             sService.getSpellCheckerService(sci.getId(), localeString,
                     session.getTextServicesSessionListener(),
-                    session.getSpellCheckerSessionListener());
+                    session.getSpellCheckerSessionListener(), bundle);
         } catch (RemoteException e) {
             return null;
         }
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index cadf2ab..9737a5a9 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -628,6 +628,9 @@
     private int mGlowPaddingLeft;
     private int mGlowPaddingRight;
 
+    private int mLastAccessibilityScrollEventFromIndex;
+    private int mLastAccessibilityScrollEventToIndex;
+
     /**
      * Interface definition for a callback to be invoked when the list or grid
      * has been scrolled.
@@ -1265,6 +1268,24 @@
     }
 
     @Override
+    public void sendAccessibilityEvent(int eventType) {
+        // Since this class calls onScrollChanged even if the mFirstPosition and the
+        // child count have not changed we will avoid sending duplicate accessibility
+        // events.
+        if (eventType == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            final int lastPosition = mFirstPosition + getChildCount();
+            if (mLastAccessibilityScrollEventFromIndex == mFirstPosition
+                    && mLastAccessibilityScrollEventToIndex == lastPosition) {
+                return;   
+            } else {
+                mLastAccessibilityScrollEventFromIndex = mFirstPosition;
+                mLastAccessibilityScrollEventToIndex = lastPosition;       
+            }
+        }
+        super.sendAccessibilityEvent(eventType);
+    }
+
+    @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
         event.setScrollable(true);
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 00c75a9..9f5737e 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -277,6 +277,7 @@
      *         called, false otherwise is returned.
      */
     public boolean performItemClick(View view, int position, long id) {
+        view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
         if (mOnItemClickListener != null) {
             playSoundEffect(SoundEffectConstants.CLICK);
             mOnItemClickListener.onItemClick(this, view, position, id);
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 00ebe0d..7ad5d6c 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -116,6 +116,8 @@
 
     private int mOverlayPosition;
 
+    private boolean mMatchDragPosition;
+
     private static final int FADE_TIMEOUT = 1500;
 
     private final Rect mTmpRect = new Rect();
@@ -262,6 +264,9 @@
 
         ta.recycle();
 
+        mMatchDragPosition = context.getApplicationInfo().targetSdkVersion >=
+                android.os.Build.VERSION_CODES.HONEYCOMB;
+
         setScrollbarPosition(mList.getVerticalScrollbarPosition());
     }
     
@@ -417,7 +422,7 @@
             }
             return;
         }
-        if (totalItemCount - visibleItemCount > 0 && mState != STATE_DRAGGING ) {
+        if (totalItemCount - visibleItemCount > 0 && mState != STATE_DRAGGING) {
             mThumbY = getThumbPositionForListPosition(firstVisibleItem, visibleItemCount,
                     totalItemCount);
             if (mChangedBounds) {
@@ -595,7 +600,7 @@
         if (mSectionIndexer == null) {
             getSectionsFromIndexer();
         }
-        if (mSectionIndexer == null) {
+        if (mSectionIndexer == null || !mMatchDragPosition) {
             return ((mList.getHeight() - mThumbH) * firstVisibleItem)
                     / (totalItemCount - visibleItemCount);
         }
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 299e1ff..fc60949 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -83,6 +83,7 @@
     // Avoid allocations...
     private RectF mTempSrc = new RectF();
     private RectF mTempDst = new RectF();
+    private float[] mTempPoints;
 
     private boolean mCropToPadding;
 
@@ -337,7 +338,6 @@
         }
     }
 
-    
     /**
      * Sets a drawable as the content of this ImageView.
      * 
@@ -347,8 +347,31 @@
         if (mDrawable != drawable) {
             mResource = 0;
             mUri = null;
+            int oldWidth = mDrawableWidth;
+            int oldHeight = mDrawableHeight;
             updateDrawable(drawable);
-            requestLayout();
+
+            boolean needsLayout;
+            if (mScaleType == ScaleType.CENTER) {
+                needsLayout = mDrawableWidth != oldWidth || mDrawableHeight != oldHeight;
+            } else {
+                if (mTempPoints == null) {
+                    mTempPoints = new float[4];
+                }
+                float[] points = mTempPoints;
+                points[0] = oldWidth;
+                points[1] = oldHeight;
+                points[2] = mDrawableWidth;
+                points[3] = mDrawableHeight;
+                if (!mMatrix.isIdentity()) {
+                    mMatrix.mapPoints(points);
+                }
+                needsLayout = points[0] != points[2] || points[1] != points[3];
+            }
+
+            if (needsLayout) {
+                requestLayout();
+            }
             invalidate();
         }
     }
@@ -643,6 +666,9 @@
         // We are allowed to change the view's height
         boolean resizeHeight = false;
         
+        final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
+        final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
+
         if (mDrawable == null) {
             // If no drawable, its intrinsic size is 0.
             mDrawableWidth = -1;
@@ -657,10 +683,6 @@
             // We are supposed to adjust view bounds to match the aspect
             // ratio of our drawable. See if that is possible.
             if (mAdjustViewBounds) {
-                
-                int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
-                int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
-                
                 resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
                 resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;
                 
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 3a22bfb..8c288d10 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -112,6 +112,7 @@
     private boolean mClearingFocus;
     private int mMaxWidth;
     private boolean mVoiceButtonEnabled;
+    private CharSequence mOldQueryText;
     private CharSequence mUserQuery;
     private boolean mExpandedInActionView;
 
@@ -462,6 +463,7 @@
         if (mIconifiedByDefault == iconified) return;
         mIconifiedByDefault = iconified;
         updateViewsVisibility(iconified);
+        updateQueryHint();
     }
 
     /**
@@ -970,9 +972,10 @@
         updateVoiceButton(!hasText);
         updateCloseButton();
         updateSubmitArea();
-        if (mOnQueryChangeListener != null) {
+        if (mOnQueryChangeListener != null && !TextUtils.equals(newText, mOldQueryText)) {
             mOnQueryChangeListener.onQueryTextChange(newText.toString());
         }
+        mOldQueryText = newText.toString();
     }
 
     private void onSubmitQuery() {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 968d612..04cf69b 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8449,6 +8449,17 @@
         info.setPassword(isPassword);
     }
 
+    @Override
+    public void sendAccessibilityEvent(int eventType) {
+        // Do not send scroll events since first they are not interesting for
+        // accessibility and second such events a generated too frequently.
+        // For details see the implementation of bringTextIntoView().
+        if (eventType == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            return;
+        }
+        super.sendAccessibilityEvent(eventType);
+    }
+
     void sendAccessibilityEventTypeViewTextChanged(CharSequence beforeText,
             int fromIndex, int removedCount, int addedCount) {
         AccessibilityEvent event =
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index d36be10..d61a579 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -32,7 +32,7 @@
  */
 public class VpnConfig implements Parcelable {
 
-    public static final String ACTION_VPN_REVOKED = "android.net.vpn.action.REVOKED";
+    public static final String SERVICE_INTERFACE = "android.net.VpnService";
 
     public static final String LEGACY_VPN = "[Legacy VPN]";
 
@@ -52,7 +52,7 @@
                 PendingIntent.FLAG_NO_CREATE : PendingIntent.FLAG_CANCEL_CURRENT);
     }
 
-    public String packagz;
+    public String user;
     public String interfaze;
     public String session;
     public int mtu = -1;
@@ -70,7 +70,7 @@
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
-        out.writeString(packagz);
+        out.writeString(user);
         out.writeString(interfaze);
         out.writeString(session);
         out.writeInt(mtu);
@@ -87,7 +87,7 @@
         @Override
         public VpnConfig createFromParcel(Parcel in) {
             VpnConfig config = new VpnConfig();
-            config.packagz = in.readString();
+            config.user = in.readString();
             config.interfaze = in.readString();
             config.session = in.readString();
             config.mtu = in.readInt();
diff --git a/core/java/com/android/internal/textservice/ISpellCheckerService.aidl b/core/java/com/android/internal/textservice/ISpellCheckerService.aidl
index ff00492..67d7b3e 100644
--- a/core/java/com/android/internal/textservice/ISpellCheckerService.aidl
+++ b/core/java/com/android/internal/textservice/ISpellCheckerService.aidl
@@ -19,11 +19,13 @@
 import com.android.internal.textservice.ISpellCheckerSession;
 import com.android.internal.textservice.ISpellCheckerSessionListener;
 
+import android.os.Bundle;
+
 /**
  * Public interface to the global spell checker.
  * @hide
  */
 interface ISpellCheckerService {
     ISpellCheckerSession getISpellCheckerSession(
-            String locale, ISpellCheckerSessionListener listener);
+            String locale, ISpellCheckerSessionListener listener, in Bundle bundle);
 }
diff --git a/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl b/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl
index 79e43510c0..5a00603 100644
--- a/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl
+++ b/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl
@@ -22,7 +22,7 @@
  * @hide
  */
 oneway interface ISpellCheckerSession {
-    void getSuggestionsMultiple(
+    void onGetSuggestionsMultiple(
             in TextInfo[] textInfos, int suggestionsLimit, boolean multipleWords);
-    void cancel();
+    void onCancel();
 }
diff --git a/core/java/com/android/internal/textservice/ITextServicesManager.aidl b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
index 4d7dfbb..bb4b2a3 100644
--- a/core/java/com/android/internal/textservice/ITextServicesManager.aidl
+++ b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
@@ -20,6 +20,7 @@
 import com.android.internal.textservice.ITextServicesSessionListener;
 
 import android.content.ComponentName;
+import android.os.Bundle;
 import android.view.textservice.SpellCheckerInfo;
 
 /**
@@ -30,7 +31,7 @@
     SpellCheckerInfo getCurrentSpellChecker(String locale);
     oneway void getSpellCheckerService(String sciId, in String locale,
             in ITextServicesSessionListener tsListener,
-            in ISpellCheckerSessionListener scListener);
+            in ISpellCheckerSessionListener scListener, in Bundle bundle);
     oneway void finishSpellCheckerService(in ISpellCheckerSessionListener listener);
     oneway void setCurrentSpellChecker(String sciId);
     SpellCheckerInfo[] getEnabledSpellCheckers();
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index 9ecd29f..0cadb16 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -49,5 +49,6 @@
     public static final int BASE_DATA_CONNECTION_AC                                 = 0x00041000;
     public static final int BASE_DATA_CONNECTION_TRACKER                            = 0x00042000;
 
+    public static final int BASE_DNS_PINGER                                         = 0x00050000;
     //TODO: define all used protocols
 }
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index cbe72dd..36f0246 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -1226,6 +1226,12 @@
      * be executed and upon the next message arriving
      * destState.enter will be invoked.
      *
+     * this function can also be called inside the enter function of the
+     * previous transition target, but the behavior is undefined when it is
+     * called mid-way through a previous transition (for example, calling this
+     * in the enter() routine of a intermediate node when the current transition
+     * target is one of the nodes descendants).
+     *
      * @param destState will be the state that receives the next message.
      */
     protected final void transitionTo(IState destState) {
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 4878b0f..61df5c7 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -583,7 +583,7 @@
     }
 
     public void setLogo(int resId) {
-        mContext.getResources().getDrawable(resId);
+        setLogo(mContext.getResources().getDrawable(resId));
     }
 
     /**
diff --git a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
index fb33748..366b983 100644
--- a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
+++ b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
@@ -29,6 +29,7 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewRootImpl;
 import com.android.internal.R;
 
@@ -62,7 +63,8 @@
         mContext = context;
         mTargetView = targetView;
         mKeyboardView = keyboardView;
-        if (useFullScreenWidth || mKeyboardView.getLayoutParams().width == -1) {
+        if (useFullScreenWidth
+                || mKeyboardView.getLayoutParams().width == ViewGroup.LayoutParams.MATCH_PARENT) {
             createKeyboards();
         } else {
             createKeyboardsWithSpecificSize(mKeyboardView.getLayoutParams().width,
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 0510023..ec926e4 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -127,6 +127,7 @@
             mAnimatingTargets = false;
         }
     };
+    private int mTargetResourceId;
 
     public MultiWaveView(Context context) {
         this(context, null);
@@ -474,6 +475,7 @@
             Drawable drawable = array.getDrawable(i);
             targetDrawables.add(new TargetDrawable(res, drawable));
         }
+        mTargetResourceId = resourceId;
         mTargetDrawables = targetDrawables;
         updateTargetPositions();
     }
@@ -492,6 +494,10 @@
         }
     }
 
+    public int getTargetResourceId() {
+        return mTargetResourceId;
+    }
+
     /**
      * Enable or disable vibrate on touch.
      *
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 6e73889..170957c 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -178,6 +178,7 @@
 	external/icu4c/i18n \
 	external/icu4c/common \
 	external/jpeg \
+	external/harfbuzz/contrib \
 	external/harfbuzz/src \
 	external/zlib \
 	frameworks/opt/emoji \
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 2de0932..ffcd1a0 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -233,6 +233,12 @@
     return surfaceTexture->getTimestamp();
 }
 
+static void SurfaceTexture_release(JNIEnv* env, jobject thiz)
+{
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    surfaceTexture->abandon();
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gSurfaceTextureMethods[] = {
@@ -243,6 +249,7 @@
     {"nativeUpdateTexImage",     "()V",   (void*)SurfaceTexture_updateTexImage },
     {"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix },
     {"nativeGetTimestamp",       "()J",   (void*)SurfaceTexture_getTimestamp },
+    {"nativeRelease",            "()V",   (void*)SurfaceTexture_release },
 };
 
 int register_android_graphics_SurfaceTexture(JNIEnv* env)
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 30fe298..a29eb38 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -17,6 +17,10 @@
 #include "TextLayoutCache.h"
 #include "TextLayout.h"
 
+extern "C" {
+#include "harfbuzz-unicode.h"
+}
+
 namespace android {
 
 TextLayoutCache::TextLayoutCache() :
@@ -355,7 +359,9 @@
     shaperItem->item.pos = start;
     shaperItem->item.length = count;
     shaperItem->item.bidiLevel = isRTL;
-    shaperItem->item.script = isRTL ? HB_Script_Arabic : HB_Script_Common;
+
+    ssize_t iter = 0;
+    shaperItem->item.script = code_point_to_script(utf16_to_code_point(chars, count, &iter));
 
     shaperItem->string = chars;
     shaperItem->stringLength = contextCount;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 21c3f1e..57b686a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -63,7 +63,7 @@
     <protected-broadcast android:name="android.app.action.EXIT_CAR_MODE" />
     <protected-broadcast android:name="android.app.action.ENTER_DESK_MODE" />
     <protected-broadcast android:name="android.app.action.EXIT_DESK_MODE" />
-    
+
     <protected-broadcast android:name="android.backup.intent.RUN" />
     <protected-broadcast android:name="android.backup.intent.CLEAR" />
     <protected-broadcast android:name="android.backup.intent.INIT" />
@@ -292,16 +292,6 @@
         android:description="@string/permdesc_setAlarm"
         android:protectionLevel="normal" />
 
-   <!-- Allows an application to read/write the voicemails owned by its own
-        package. -->
-   <!--  TODO: delete this permission when dependent content provider &
-        application code has been migrated to use ADD_VOICEMAIL instead -->
-    <permission android:name="com.android.voicemail.permission.READ_WRITE_OWN_VOICEMAIL"
-        android:permissionGroup="android.permission-group.PERSONAL_INFO"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_readWriteOwnVoicemail"
-        android:description="@string/permdesc_readWriteOwnVoicemail" />
-
    <!-- Allows an application to add voicemails into the system. -->
     <permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL"
         android:permissionGroup="android.permission-group.PERSONAL_INFO"
@@ -402,14 +392,6 @@
         android:description="@string/permdesc_nfc"
         android:label="@string/permlab_nfc" />
 
-    <!-- Allows applications to provide VPN functionality.
-         @hide Pending API council approval -->
-    <permission android:name="android.permission.VPN"
-        android:permissionGroup="android.permission-group.NETWORK"
-        android:protectionLevel="dangerous"
-        android:description="@string/permdesc_vpn"
-        android:label="@string/permlab_vpn" />
-
     <!-- Allows an application to use SIP service -->
     <permission android:name="android.permission.USE_SIP"
         android:permissionGroup="android.permission-group.NETWORK"
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_holo.9.png
new file mode 100644
index 0000000..5e6a9d6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_holo.9.png
new file mode 100644
index 0000000..eb9d740
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_off_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_holo.9.png
new file mode 100644
index 0000000..869a330
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_holo.9.png
new file mode 100644
index 0000000..7ec33dd
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
new file mode 100644
index 0000000..72d63da
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
new file mode 100644
index 0000000..fcc5cac
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_light_normal_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_light_normal_holo.9.png
new file mode 100644
index 0000000..baff858
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_light_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_keyboard_key_light_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_keyboard_key_light_pressed_holo.9.png
new file mode 100644
index 0000000..5612c51
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_keyboard_key_light_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_camera_activated.png b/core/res/res/drawable-hdpi/ic_lockscreen_camera_activated.png
new file mode 100644
index 0000000..d510e1d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_camera_activated.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_camera_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_camera_normal.png
new file mode 100644
index 0000000..36d766d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_camera_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_silent_activated.png b/core/res/res/drawable-hdpi/ic_lockscreen_silent_activated.png
index fce4980..d1938b9 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_silent_activated.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_silent_activated.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_soundon_activated.png b/core/res/res/drawable-hdpi/ic_lockscreen_soundon_activated.png
index 73f01c9..f6ccbd2 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_soundon_activated.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_soundon_activated.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_text_activated.png b/core/res/res/drawable-hdpi/ic_lockscreen_text_activated.png
index d01bdb2..10b3268 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_text_activated.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_text_activated.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_unlock_activated.png b/core/res/res/drawable-hdpi/ic_lockscreen_unlock_activated.png
index d333946..d1f3015 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_unlock_activated.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_unlock_activated.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_activated_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_ab_activated_holo_dark.9.png
new file mode 100644
index 0000000..d471c30
--- /dev/null
+++ b/core/res/res/drawable-hdpi/spinner_ab_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_activated_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_ab_activated_holo_light.9.png
new file mode 100644
index 0000000..d471c30
--- /dev/null
+++ b/core/res/res/drawable-hdpi/spinner_ab_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark.9.png
new file mode 100644
index 0000000..001cfbb
--- /dev/null
+++ b/core/res/res/drawable-hdpi/spinner_ab_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_default_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_ab_default_holo_light.9.png
new file mode 100644
index 0000000..5e278c8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/spinner_ab_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark.9.png
new file mode 100644
index 0000000..cf2e149
--- /dev/null
+++ b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light.9.png
new file mode 100644
index 0000000..63f212d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/spinner_ab_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark.9.png
new file mode 100644
index 0000000..85663e6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light.9.png
new file mode 100644
index 0000000..85663e6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/spinner_ab_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png
new file mode 100644
index 0000000..afddbe8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png
new file mode 100644
index 0000000..0ad6476
--- /dev/null
+++ b/core/res/res/drawable-hdpi/spinner_ab_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_active_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_cab_active_holo_dark.9.png
deleted file mode 100644
index 7cad0c9..0000000
--- a/core/res/res/drawable-hdpi/spinner_cab_active_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_active_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_cab_active_holo_light.9.png
deleted file mode 100644
index 7cad0c9..0000000
--- a/core/res/res/drawable-hdpi/spinner_cab_active_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_default_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_cab_default_holo_dark.9.png
deleted file mode 100644
index b3f3cf7..0000000
--- a/core/res/res/drawable-hdpi/spinner_cab_default_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_default_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_cab_default_holo_light.9.png
deleted file mode 100644
index af46631..0000000
--- a/core/res/res/drawable-hdpi/spinner_cab_default_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_cab_disabled_holo_dark.9.png
deleted file mode 100644
index e672c95..0000000
--- a/core/res/res/drawable-hdpi/spinner_cab_disabled_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_cab_disabled_holo_light.9.png
deleted file mode 100644
index f499540..0000000
--- a/core/res/res/drawable-hdpi/spinner_cab_disabled_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_cab_focused_holo_dark.9.png
deleted file mode 100644
index f4900a5..0000000
--- a/core/res/res/drawable-hdpi/spinner_cab_focused_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_focused_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_cab_focused_holo_light.9.png
deleted file mode 100644
index 1286542..0000000
--- a/core/res/res/drawable-hdpi/spinner_cab_focused_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/spinner_cab_pressed_holo_dark.9.png
deleted file mode 100644
index 8b6f9dd..0000000
--- a/core/res/res/drawable-hdpi/spinner_cab_pressed_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_cab_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/spinner_cab_pressed_holo_light.9.png
deleted file mode 100644
index 4f0c476..0000000
--- a/core/res/res/drawable-hdpi/spinner_cab_pressed_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png
new file mode 100644
index 0000000..d449d76
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
new file mode 100644
index 0000000..80fe863
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_off_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png
new file mode 100644
index 0000000..196d6d9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
new file mode 100644
index 0000000..8f340d3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
new file mode 100644
index 0000000..b34b957
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
new file mode 100644
index 0000000..02f4b3d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png
new file mode 100644
index 0000000..976083f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_light_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png
new file mode 100644
index 0000000..c39dd4a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_camera_activated.png b/core/res/res/drawable-mdpi/ic_lockscreen_camera_activated.png
new file mode 100644
index 0000000..1437798
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_camera_activated.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_camera_normal.png b/core/res/res/drawable-mdpi/ic_lockscreen_camera_normal.png
new file mode 100644
index 0000000..b718258
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_camera_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_silent_activated.png b/core/res/res/drawable-mdpi/ic_lockscreen_silent_activated.png
index 3b2f3fc..2bc3f52 100644
--- a/core/res/res/drawable-mdpi/ic_lockscreen_silent_activated.png
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_silent_activated.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_soundon_activated.png b/core/res/res/drawable-mdpi/ic_lockscreen_soundon_activated.png
index 03f524d..637eec6 100644
--- a/core/res/res/drawable-mdpi/ic_lockscreen_soundon_activated.png
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_soundon_activated.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_text_activated.png b/core/res/res/drawable-mdpi/ic_lockscreen_text_activated.png
index dbfc5ba..878ff1f 100644
--- a/core/res/res/drawable-mdpi/ic_lockscreen_text_activated.png
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_text_activated.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_unlock_activated.png b/core/res/res/drawable-mdpi/ic_lockscreen_unlock_activated.png
index df47993..0d3f756 100644
--- a/core/res/res/drawable-mdpi/ic_lockscreen_unlock_activated.png
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_unlock_activated.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_activated_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_ab_activated_holo_dark.9.png
new file mode 100644
index 0000000..34c9188
--- /dev/null
+++ b/core/res/res/drawable-mdpi/spinner_ab_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_activated_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_ab_activated_holo_light.9.png
new file mode 100644
index 0000000..34c9188
--- /dev/null
+++ b/core/res/res/drawable-mdpi/spinner_ab_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark.9.png
new file mode 100644
index 0000000..b92abaf
--- /dev/null
+++ b/core/res/res/drawable-mdpi/spinner_ab_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_default_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_ab_default_holo_light.9.png
new file mode 100644
index 0000000..91f0e87
--- /dev/null
+++ b/core/res/res/drawable-mdpi/spinner_ab_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark.9.png
new file mode 100644
index 0000000..dab7eda
--- /dev/null
+++ b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light.9.png
new file mode 100644
index 0000000..bf14605
--- /dev/null
+++ b/core/res/res/drawable-mdpi/spinner_ab_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark.9.png
new file mode 100644
index 0000000..c733260
--- /dev/null
+++ b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light.9.png
new file mode 100644
index 0000000..c733260
--- /dev/null
+++ b/core/res/res/drawable-mdpi/spinner_ab_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png
new file mode 100644
index 0000000..6d290a6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png
new file mode 100644
index 0000000..6dae484
--- /dev/null
+++ b/core/res/res/drawable-mdpi/spinner_ab_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_active_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_cab_active_holo_dark.9.png
deleted file mode 100644
index 617c379..0000000
--- a/core/res/res/drawable-mdpi/spinner_cab_active_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_active_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_cab_active_holo_light.9.png
deleted file mode 100644
index 617c379..0000000
--- a/core/res/res/drawable-mdpi/spinner_cab_active_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_default_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_cab_default_holo_dark.9.png
deleted file mode 100644
index d76b123..0000000
--- a/core/res/res/drawable-mdpi/spinner_cab_default_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_default_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_cab_default_holo_light.9.png
deleted file mode 100644
index ee91044..0000000
--- a/core/res/res/drawable-mdpi/spinner_cab_default_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_cab_disabled_holo_dark.9.png
deleted file mode 100644
index fc9c109..0000000
--- a/core/res/res/drawable-mdpi/spinner_cab_disabled_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_cab_disabled_holo_light.9.png
deleted file mode 100644
index 7fc7cc1..0000000
--- a/core/res/res/drawable-mdpi/spinner_cab_disabled_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_cab_focused_holo_dark.9.png
deleted file mode 100644
index 0f49fe9..0000000
--- a/core/res/res/drawable-mdpi/spinner_cab_focused_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_focused_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_cab_focused_holo_light.9.png
deleted file mode 100644
index 032d5d3..0000000
--- a/core/res/res/drawable-mdpi/spinner_cab_focused_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/spinner_cab_pressed_holo_dark.9.png
deleted file mode 100644
index df0a935..0000000
--- a/core/res/res/drawable-mdpi/spinner_cab_pressed_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_cab_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/spinner_cab_pressed_holo_light.9.png
deleted file mode 100644
index b43177b..0000000
--- a/core/res/res/drawable-mdpi/spinner_cab_pressed_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_holo.9.png
new file mode 100644
index 0000000..d2cd029
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_holo.9.png
new file mode 100644
index 0000000..0f709eb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_off_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_holo.9.png
new file mode 100644
index 0000000..2f4de8e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_holo.9.png
new file mode 100644
index 0000000..3871689e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
new file mode 100644
index 0000000..836ea6e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
new file mode 100644
index 0000000..279db1f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_light_normal_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_light_normal_holo.9.png
new file mode 100644
index 0000000..b26f1d2
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_light_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_keyboard_key_light_pressed_holo.9.png b/core/res/res/drawable-xhdpi/btn_keyboard_key_light_pressed_holo.9.png
new file mode 100644
index 0000000..c23a4b2
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_keyboard_key_light_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_camera_activated.png b/core/res/res/drawable-xhdpi/ic_lockscreen_camera_activated.png
new file mode 100644
index 0000000..d545883
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_camera_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_camera_normal.png b/core/res/res/drawable-xhdpi/ic_lockscreen_camera_normal.png
new file mode 100644
index 0000000..8de7b84
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_camera_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_silent_activated.png b/core/res/res/drawable-xhdpi/ic_lockscreen_silent_activated.png
index fd81211..2900045 100644
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_silent_activated.png
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_silent_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_soundon_activated.png b/core/res/res/drawable-xhdpi/ic_lockscreen_soundon_activated.png
index 9edc70b..da2adc2 100644
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_soundon_activated.png
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_soundon_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_text_activated.png b/core/res/res/drawable-xhdpi/ic_lockscreen_text_activated.png
index 29c4572..ddebe3e 100644
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_text_activated.png
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_text_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_activated.png b/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_activated.png
index fa0be96..73d7af3 100644
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_activated.png
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_activated.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_activated_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_ab_activated_holo_dark.9.png
new file mode 100644
index 0000000..85d8540
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_ab_activated_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_activated_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_ab_activated_holo_light.9.png
new file mode 100644
index 0000000..85d8540
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_ab_activated_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark.9.png
new file mode 100644
index 0000000..31b39d7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light.9.png
new file mode 100644
index 0000000..1527c5c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_ab_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark.9.png
new file mode 100644
index 0000000..e4cef9a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light.9.png
new file mode 100644
index 0000000..1c37ece
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_ab_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark.9.png
new file mode 100644
index 0000000..6aae46b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light.9.png
new file mode 100644
index 0000000..6aae46b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_ab_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png
new file mode 100644
index 0000000..db2e034
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png
new file mode 100644
index 0000000..77bb433
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_ab_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_keyboard_key_ics.xml b/core/res/res/drawable/btn_keyboard_key_ics.xml
new file mode 100644
index 0000000..7335cc2
--- /dev/null
+++ b/core/res/res/drawable/btn_keyboard_key_ics.xml
@@ -0,0 +1,42 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!-- Functional keys. -->
+
+    <item android:state_single="true" android:state_pressed="true"
+          android:drawable="@drawable/btn_keyboard_key_dark_pressed_holo" />
+    <item android:state_single="true"
+          android:drawable="@drawable/btn_keyboard_key_dark_normal_holo" />
+
+    <!-- Toggle keys. Use checkable/checked state. -->
+
+    <item android:state_checkable="true" android:state_checked="true" android:state_pressed="true"
+          android:drawable="@drawable/btn_keyboard_key_dark_pressed_on_holo" />
+    <item android:state_checkable="true" android:state_pressed="true"
+          android:drawable="@drawable/btn_keyboard_key_dark_pressed_off_holo" />
+    <item android:state_checkable="true" android:state_checked="true"
+          android:drawable="@drawable/btn_keyboard_key_dark_normal_on_holo" />
+    <item android:state_checkable="true"
+          android:drawable="@drawable/btn_keyboard_key_dark_normal_off_holo" />
+
+    <!-- Normal keys -->
+
+    <item android:state_pressed="true"
+          android:drawable="@drawable/btn_keyboard_key_light_pressed_holo" />
+    <item android:drawable="@drawable/btn_keyboard_key_light_normal_holo" />
+</selector>
diff --git a/core/res/res/drawable/ic_lockscreen_camera.xml b/core/res/res/drawable/ic_lockscreen_camera.xml
new file mode 100644
index 0000000..0e3ef37
--- /dev/null
+++ b/core/res/res/drawable/ic_lockscreen_camera.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item
+        android:state_enabled="true"
+        android:state_active="false"
+        android:state_focused="false"
+        android:drawable="@drawable/ic_lockscreen_camera_normal" />
+
+    <item
+        android:state_enabled="true"
+        android:state_active="true"
+        android:state_focused="false"
+        android:drawable="@drawable/ic_lockscreen_camera_activated" />
+
+</selector>
diff --git a/core/res/res/drawable/spinner_cab_background_holo_dark.xml b/core/res/res/drawable/spinner_ab_holo_dark.xml
similarity index 66%
rename from core/res/res/drawable/spinner_cab_background_holo_dark.xml
rename to core/res/res/drawable/spinner_ab_holo_dark.xml
index 5572450..708b6ab 100644
--- a/core/res/res/drawable/spinner_cab_background_holo_dark.xml
+++ b/core/res/res/drawable/spinner_ab_holo_dark.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- 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.
@@ -16,10 +16,12 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_enabled="false"
-          android:drawable="@drawable/spinner_cab_disabled_holo_dark" />
+          android:drawable="@drawable/spinner_ab_disabled_holo_dark" />
     <item android:state_pressed="true"
-          android:drawable="@drawable/spinner_cab_pressed_holo_dark" />
+          android:drawable="@drawable/spinner_ab_pressed_holo_dark" />
     <item android:state_pressed="false" android:state_focused="true"
-          android:drawable="@drawable/spinner_cab_focused_holo_dark" />
-    <item android:drawable="@drawable/spinner_cab_default_holo_dark" />
+          android:drawable="@drawable/spinner_ab_focused_holo_dark" />
+    <item android:state_activated="true"
+          android:drawable="@drawable/spinner_ab_activated_holo_dark" />
+    <item android:drawable="@drawable/spinner_ab_default_holo_dark" />
 </selector>
diff --git a/core/res/res/drawable/spinner_cab_background_holo_light.xml b/core/res/res/drawable/spinner_ab_holo_light.xml
similarity index 70%
rename from core/res/res/drawable/spinner_cab_background_holo_light.xml
rename to core/res/res/drawable/spinner_ab_holo_light.xml
index 98ff48d..c4901ca 100644
--- a/core/res/res/drawable/spinner_cab_background_holo_light.xml
+++ b/core/res/res/drawable/spinner_ab_holo_light.xml
@@ -16,10 +16,12 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_enabled="false"
-          android:drawable="@drawable/spinner_cab_disabled_holo_light" />
+          android:drawable="@drawable/spinner_ab_disabled_holo_light" />
     <item android:state_pressed="true"
-          android:drawable="@drawable/spinner_cab_pressed_holo_light" />
+          android:drawable="@drawable/spinner_ab_pressed_holo_light" />
     <item android:state_pressed="false" android:state_focused="true"
-          android:drawable="@drawable/spinner_cab_focused_holo_light" />
-    <item android:drawable="@drawable/spinner_cab_default_holo_light" />
+          android:drawable="@drawable/spinner_ab_focused_holo_light" />
+    <item android:state_activated="true"
+          android:drawable="@drawable/spinner_ab_activated_holo_light" />
+    <item android:drawable="@drawable/spinner_ab_default_holo_light" />
 </selector>
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index 960907d..c2536b7 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -118,41 +118,36 @@
     />
 
     <!-- Column 1 -->
-    <Space android:layout_width="32dip" android:layout_rowSpan="7" />
+    <Space android:layout_width="16dip" android:layout_rowSpan="7" />
 
     <!-- Column 2 - password entry field and PIN keyboard -->
-    <LinearLayout
-        android:orientation="vertical"
-        android:layout_gravity="center|fill"
-        android:layout_rowSpan="7">
-
-        <EditText android:id="@+id/passwordEntry"
-            android:layout_height="wrap_content"
-            android:layout_width="wrap_content"
-            android:singleLine="true"
-            android:textStyle="normal"
-            android:inputType="textPassword"
-            android:layout_gravity="center"
-            android:textSize="24sp"
-            android:minEms="8"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:background="@drawable/lockscreen_password_field_dark"
-            android:textColor="?android:attr/textColorPrimary"
-            android:imeOptions="flagNoFullscreen"
-            />
-
-        <!-- Numeric keyboard -->
-        <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
-            android:layout_width="250dip"
-            android:layout_height="100dip"
-            android:layout_gravity="center"
-            android:background="#40000000"
-            android:layout_marginTop="5dip"
-            android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
-            android:visibility="gone"
+    <EditText android:id="@+id/passwordEntry"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_gravity="fill"
+        android:gravity="center"
+        android:singleLine="true"
+        android:textStyle="normal"
+        android:inputType="textPassword"
+        android:textSize="24sp"
+        android:minEms="8"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:background="@drawable/lockscreen_password_field_dark"
+        android:textColor="?android:attr/textColorPrimary"
+        android:imeOptions="flagNoFullscreen|actionDone"
         />
 
-    </LinearLayout>
+    <!-- Numeric keyboard -->
+    <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
+        android:layout_width="270dip"
+        android:layout_height="wrap_content"
+        android:layout_marginRight="4dip"
+        android:background="#40000000"
+        android:layout_marginTop="5dip"
+        android:keyBackground="@*android:drawable/btn_keyboard_key_ics"
+        android:visibility="gone"
+        android:layout_rowSpan="6"
+    />
 
     <!-- Music transport control -->
     <include android:id="@+id/transport"
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index 7a51035..cd33275 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -94,31 +94,32 @@
         android:drawablePadding="4dip"
         />
 
-    <Space android:layout_height="100dip"/>
-
     <!-- Password entry field -->
     <EditText android:id="@+id/passwordEntry"
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
+        android:layout_gravity="center_vertical|fill_horizontal"
+        android:gravity="center_horizontal"
         android:singleLine="true"
         android:textStyle="normal"
         android:inputType="textPassword"
-        android:gravity="center"
-        android:textSize="22sp"
+        android:textSize="36sp"
         android:layout_marginLeft="16dip"
         android:layout_marginRight="16dip"
         android:background="@drawable/lockscreen_password_field_dark"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textColor="#ffffffff"/>
-
-    <Space android:layout_gravity="fill" />
+        android:textColor="#ffffffff"
+        android:imeOptions="actionDone"/>
 
     <!-- Numeric keyboard -->
     <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
         android:layout_width="match_parent"
-        android:layout_height="260dip"
+        android:layout_height="wrap_content"
+        android:layout_marginRight="4dip"
+        android:paddingTop="4dip"
+        android:paddingBottom="4dip"
         android:background="#40000000"
-        android:keyBackground="@*android:drawable/btn_keyboard_key_fulltrans"
+        android:keyBackground="@*android:drawable/btn_keyboard_key_ics"
         android:visibility="gone"
     />
 
@@ -139,7 +140,6 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="4dip"
-        android:layout_marginRight="16dip"
         android:layout_gravity="center_horizontal"
         android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
         style="?android:attr/buttonBarButtonStyle"
@@ -153,7 +153,7 @@
         layout="@layout/keyguard_transport_control"
         android:layout_row="0"
         android:layout_column="0"
-        android:layout_rowSpan="4"
+        android:layout_rowSpan="3"
         android:layout_columnSpan="1"
         android:layout_gravity="fill"
         />
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 05c768d..6016d4e 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -129,7 +129,7 @@
             android:layout_height="match_parent"
             android:layout_alignParentBottom="true"
 
-            android:targetDrawables="@array/lockscreen_targets_when_silent"
+            android:targetDrawables="@array/lockscreen_targets_with_camera"
             android:handleDrawable="@drawable/ic_lockscreen_handle"
             android:waveDrawable="@drawable/ic_lockscreen_outerring"
             android:outerRadius="@dimen/multiwaveview_target_placement_radius"
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 6440726..168bd1a 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -131,7 +131,7 @@
         android:layout_height="match_parent"
         android:layout_rowSpan="7"
 
-        android:targetDrawables="@array/lockscreen_targets_when_silent"
+        android:targetDrawables="@array/lockscreen_targets_with_camera"
         android:handleDrawable="@drawable/ic_lockscreen_handle"
         android:waveDrawable="@drawable/ic_lockscreen_outerring"
         android:outerRadius="@dimen/multiwaveview_target_placement_radius"
diff --git a/core/res/res/values-land/arrays.xml b/core/res/res/values-land/arrays.xml
index 92d5a87..fd492ec 100644
--- a/core/res/res/values-land/arrays.xml
+++ b/core/res/res/values-land/arrays.xml
@@ -34,4 +34,11 @@
         <item>@drawable/ic_lockscreen_silent</item>
     </array>
 
+    <array name="lockscreen_targets_with_camera">
+        <item>@null</item>
+        <item>@drawable/ic_lockscreen_unlock</item>
+        <item>@null</item>
+        <item>@drawable/ic_lockscreen_camera</item>
+    </array>
+
 </resources>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index 388eb38..02bb3c8 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -22,7 +22,7 @@
     <!-- Default height of a key in the password keyboard for alpha -->
     <dimen name="password_keyboard_key_height_alpha">47dip</dimen>
     <!-- Default height of a key in the password keyboard for numeric -->
-    <dimen name="password_keyboard_key_height_numeric">60dip</dimen>
+    <dimen name="password_keyboard_key_height_numeric">50dip</dimen>
     <!-- Default correction for the space key in the password keyboard -->
     <dimen name="password_keyboard_spacebar_vertical_correction">2dip</dimen>
     <dimen name="preference_widget_width">72dp</dimen>
diff --git a/core/res/res/values-large/themes.xml b/core/res/res/values-large/themes.xml
index 9e3e0bb..871a131 100644
--- a/core/res/res/values-large/themes.xml
+++ b/core/res/res/values-large/themes.xml
@@ -16,6 +16,21 @@
 ** limitations under the License.
 */
 -->
+
+<!--
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Holo themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see themes_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+ -->
 <resources>
     <style name="Theme.Holo.DialogWhenLarge"
             parent="@android:style/Theme.Holo.Dialog.MinWidth">
diff --git a/core/res/res/values-large/themes_device_defaults.xml b/core/res/res/values-large/themes_device_defaults.xml
new file mode 100644
index 0000000..52fff5c
--- /dev/null
+++ b/core/res/res/values-large/themes_device_defaults.xml
@@ -0,0 +1,48 @@
+<?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.
+-->
+
+<!--
+===============================================================
+                        PLEASE READ
+===============================================================
+This file contains the themes that are the Device Defaults.
+If you want to edit themes to skin your device, do it here.
+We recommend that you do not edit themes.xml and instead edit
+this file.
+
+Editing this file instead of themes.xml will greatly simplify
+merges for future platform versions and CTS compliance will be
+easier.
+===============================================================
+                        PLEASE READ
+===============================================================
+ -->
+<resources>
+    <style name="Theme.DeviceDefault.DialogWhenLarge"
+            parent="@android:style/Theme.DeviceDefault.Dialog.MinWidth">
+        <item name="preferencePanelStyle">@style/PreferencePanel.Dialog</item>
+    </style>
+    <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar"
+            parent="@android:style/Theme.DeviceDefault.Dialog.NoActionBar.MinWidth">
+        <item name="preferencePanelStyle">@style/PreferencePanel.Dialog</item>
+    </style>
+    <style name="Theme.DeviceDefault.Light.DialogWhenLarge"
+            parent="@android:style/Theme.DeviceDefault.Light.Dialog.MinWidth">
+    </style>
+    <style name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar"
+            parent="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth">
+    </style>
+</resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 73103a6..753e4ac 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -217,14 +217,18 @@
        <item>@drawable/scrollbar_handle_vertical</item>
        <item>@drawable/spinner_background_holo_dark</item>
        <item>@drawable/spinner_background_holo_light</item>
-       <item>@drawable/spinner_cab_default_holo_dark</item>
-       <item>@drawable/spinner_cab_default_holo_light</item>
-       <item>@drawable/spinner_cab_disabled_holo_dark</item>
-       <item>@drawable/spinner_cab_disabled_holo_light</item>
-       <item>@drawable/spinner_cab_focused_holo_dark</item>
-       <item>@drawable/spinner_cab_focused_holo_light</item>
-       <item>@drawable/spinner_cab_pressed_holo_dark</item>
-       <item>@drawable/spinner_cab_pressed_holo_light</item>
+       <item>@drawable/spinner_ab_default_holo_dark</item>
+       <item>@drawable/spinner_ab_default_holo_light</item>
+       <item>@drawable/spinner_ab_disabled_holo_dark</item>
+       <item>@drawable/spinner_ab_disabled_holo_light</item>
+       <item>@drawable/spinner_ab_focused_holo_dark</item>
+       <item>@drawable/spinner_ab_focused_holo_light</item>
+       <item>@drawable/spinner_ab_pressed_holo_dark</item>
+       <item>@drawable/spinner_ab_pressed_holo_light</item>
+       <item>@drawable/spinner_ab_activated_holo_dark</item>
+       <item>@drawable/spinner_ab_activated_holo_light</item>
+       <item>@drawable/spinner_ab_holo_dark</item>
+       <item>@drawable/spinner_ab_holo_light</item>
        <item>@drawable/spinner_default_holo_dark</item>
        <item>@drawable/spinner_default_holo_light</item>
        <item>@drawable/spinner_disabled_holo_dark</item>
@@ -358,4 +362,11 @@
         <item>@null</item>"
     </array>
 
+    <array name="lockscreen_targets_with_camera">
+        <item>@drawable/ic_lockscreen_unlock</item>
+        <item>@null</item>
+        <item>@drawable/ic_lockscreen_camera</item>
+        <item>@null</item>"
+    </array>
+
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index b3e50ea..e534e9b 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -50,12 +50,17 @@
     <dimen name="fastscroll_thumb_height">52dp</dimen>
     <!-- Min width for a tablet device -->
     <dimen name="min_xlarge_screen_width">800dp</dimen>
-    <!-- Default height of a key in the password keyboard for alpha -->
+
+    <!-- Default height of a key in the password keyboard for alpha (used by keyguard) -->
     <dimen name="password_keyboard_key_height_alpha">56dip</dimen>
-    <!-- Default height of a key in the password keyboard for numeric -->
+    <!-- Default height of a key in the password keyboard for numeric (used by keyguard) -->
     <dimen name="password_keyboard_key_height_numeric">56dip</dimen>
-    <!-- Default correction for the space key in the password keyboard -->
+    <!-- Default correction for the space key in the password keyboard  (used by keyguard) -->
     <dimen name="password_keyboard_spacebar_vertical_correction">4dip</dimen>
+    <!-- Default horizontal gap between keys in the password keyboard (used by keyguard) -->
+    <dimen name="password_keyboard_horizontalGap">3dip</dimen>
+    <!-- Default vertical gap between keys in the password keyboard (used by keyguard) -->
+    <dimen name="password_keyboard_verticalGap">9dip</dimen>
 
     <!-- Default target placement radius for MultiWaveView -->
     <dimen name="multiwaveview_target_placement_radius">135dip</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 2dfe453..f85dd85 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1803,6 +1803,183 @@
   <public type="style" name="Widget.Holo.Light.ActionBar.TabText.Inverse" />
   <public type="style" name="Widget.Holo.Light.ActionMode.Inverse" />
 
+  <public type="style" name="Theme.DeviceDefault" />
+  <public type="style" name="Theme.DeviceDefault.NoActionBar" />
+  <public type="style" name="Theme.DeviceDefault.NoActionBar.Fullscreen" />
+  <public type="style" name="Theme.DeviceDefault.Light" />
+  <public type="style" name="Theme.DeviceDefault.Light.NoActionBar" />
+  <public type="style" name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" />
+  <public type="style" name="Theme.DeviceDefault.Dialog" />
+  <public type="style" name="Theme.DeviceDefault.Dialog.MinWidth" />
+  <public type="style" name="Theme.DeviceDefault.Dialog.NoActionBar" />
+  <public type="style" name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" />
+  <public type="style" name="Theme.DeviceDefault.Light.Dialog" />
+  <public type="style" name="Theme.DeviceDefault.Light.Dialog.MinWidth" />
+  <public type="style" name="Theme.DeviceDefault.Light.Dialog.NoActionBar" />
+  <public type="style" name="Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth" />
+  <public type="style" name="Theme.DeviceDefault.DialogWhenLarge" />
+  <public type="style" name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" />
+  <public type="style" name="Theme.DeviceDefault.Light.DialogWhenLarge" />
+  <public type="style" name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar" />
+  <public type="style" name="Theme.DeviceDefault.Panel" />
+  <public type="style" name="Theme.DeviceDefault.Light.Panel" />
+  <public type="style" name="Theme.DeviceDefault.Wallpaper" />
+  <public type="style" name="Theme.DeviceDefault.Wallpaper.NoTitleBar" />
+  <public type="style" name="Theme.DeviceDefault.InputMethod" />
+  <public type="style" name="Theme.DeviceDefault.Light.DarkActionBar" />
+
+  <public type="style" name="Widget.DeviceDefault" />
+  <public type="style" name="Widget.DeviceDefault.Button" />
+  <public type="style" name="Widget.DeviceDefault.Button.Small" />
+  <public type="style" name="Widget.DeviceDefault.Button.Inset" />
+  <public type="style" name="Widget.DeviceDefault.Button.Toggle" />
+  <public type="style" name="Widget.DeviceDefault.Button.Borderless.Small" />
+  <public type="style" name="Widget.DeviceDefault.TextView" />
+  <public type="style" name="Widget.DeviceDefault.AutoCompleteTextView" />
+  <public type="style" name="Widget.DeviceDefault.CompoundButton.CheckBox" />
+  <public type="style" name="Widget.DeviceDefault.ListView.DropDown" />
+  <public type="style" name="Widget.DeviceDefault.EditText" />
+  <public type="style" name="Widget.DeviceDefault.ExpandableListView" />
+  <public type="style" name="Widget.DeviceDefault.GridView" />
+  <public type="style" name="Widget.DeviceDefault.ImageButton" />
+  <public type="style" name="Widget.DeviceDefault.ListView" />
+  <public type="style" name="Widget.DeviceDefault.PopupWindow" />
+  <public type="style" name="Widget.DeviceDefault.ProgressBar" />
+  <public type="style" name="Widget.DeviceDefault.ProgressBar.Horizontal" />
+  <public type="style" name="Widget.DeviceDefault.ProgressBar.Small" />
+  <public type="style" name="Widget.DeviceDefault.ProgressBar.Small.Title" />
+  <public type="style" name="Widget.DeviceDefault.ProgressBar.Large" />
+  <public type="style" name="Widget.DeviceDefault.SeekBar" />
+  <public type="style" name="Widget.DeviceDefault.RatingBar" />
+  <public type="style" name="Widget.DeviceDefault.RatingBar.Indicator" />
+  <public type="style" name="Widget.DeviceDefault.RatingBar.Small" />
+  <public type="style" name="Widget.DeviceDefault.CompoundButton.RadioButton" />
+  <public type="style" name="Widget.DeviceDefault.ScrollView" />
+  <public type="style" name="Widget.DeviceDefault.HorizontalScrollView" />
+  <public type="style" name="Widget.DeviceDefault.Spinner" />
+  <public type="style" name="Widget.DeviceDefault.CompoundButton.Star" />
+  <public type="style" name="Widget.DeviceDefault.TabWidget" />
+  <public type="style" name="Widget.DeviceDefault.WebTextView" />
+  <public type="style" name="Widget.DeviceDefault.WebView" />
+  <public type="style" name="Widget.DeviceDefault.DropDownItem" />
+  <public type="style" name="Widget.DeviceDefault.DropDownItem.Spinner" />
+  <public type="style" name="Widget.DeviceDefault.TextView.SpinnerItem" />
+  <public type="style" name="Widget.DeviceDefault.ListPopupWindow" />
+  <public type="style" name="Widget.DeviceDefault.PopupMenu" />
+  <public type="style" name="Widget.DeviceDefault.ActionButton" />
+  <public type="style" name="Widget.DeviceDefault.ActionButton.Overflow" />
+  <public type="style" name="Widget.DeviceDefault.ActionButton.TextButton" />
+  <public type="style" name="Widget.DeviceDefault.ActionMode" />
+  <public type="style" name="Widget.DeviceDefault.ActionButton.CloseMode" />
+  <public type="style" name="Widget.DeviceDefault.ActionBar" />
+  <public type="style" name="Widget.DeviceDefault.Button.Borderless" />
+  <public type="style" name="Widget.DeviceDefault.Tab" />
+  <public type="style" name="Widget.DeviceDefault.CalendarView" />
+  <public type="style" name="Widget.DeviceDefault.DatePicker" />
+  <public type="style" name="Widget.DeviceDefault.ActionBar.TabView" />
+  <public type="style" name="Widget.DeviceDefault.ActionBar.TabText" />
+  <public type="style" name="Widget.DeviceDefault.ActionBar.TabBar" />
+  <public type="style" name="Widget.DeviceDefault.ActionBar.Solid" />
+  <public type="style" name="Widget.DeviceDefault.Light" />
+  <public type="style" name="Widget.DeviceDefault.Light.Button" />
+  <public type="style" name="Widget.DeviceDefault.Light.Button.Small" />
+  <public type="style" name="Widget.DeviceDefault.Light.Button.Inset" />
+  <public type="style" name="Widget.DeviceDefault.Light.Button.Toggle" />
+  <public type="style" name="Widget.DeviceDefault.Light.Button.Borderless.Small" />
+  <public type="style" name="Widget.DeviceDefault.Light.TextView" />
+  <public type="style" name="Widget.DeviceDefault.Light.AutoCompleteTextView" />
+  <public type="style" name="Widget.DeviceDefault.Light.CompoundButton.CheckBox" />
+  <public type="style" name="Widget.DeviceDefault.Light.ListView.DropDown" />
+  <public type="style" name="Widget.DeviceDefault.Light.EditText" />
+  <public type="style" name="Widget.DeviceDefault.Light.ExpandableListView" />
+  <public type="style" name="Widget.DeviceDefault.Light.GridView" />
+  <public type="style" name="Widget.DeviceDefault.Light.ImageButton" />
+  <public type="style" name="Widget.DeviceDefault.Light.ListView" />
+  <public type="style" name="Widget.DeviceDefault.Light.PopupWindow" />
+  <public type="style" name="Widget.DeviceDefault.Light.ProgressBar" />
+  <public type="style" name="Widget.DeviceDefault.Light.ProgressBar.Horizontal" />
+  <public type="style" name="Widget.DeviceDefault.Light.ProgressBar.Small" />
+  <public type="style" name="Widget.DeviceDefault.Light.ProgressBar.Small.Title" />
+  <public type="style" name="Widget.DeviceDefault.Light.ProgressBar.Large" />
+  <public type="style" name="Widget.DeviceDefault.Light.ProgressBar.Inverse" />
+  <public type="style" name="Widget.DeviceDefault.Light.ProgressBar.Small.Inverse" />
+  <public type="style" name="Widget.DeviceDefault.Light.ProgressBar.Large.Inverse" />
+  <public type="style" name="Widget.DeviceDefault.Light.SeekBar" />
+  <public type="style" name="Widget.DeviceDefault.Light.RatingBar" />
+  <public type="style" name="Widget.DeviceDefault.Light.RatingBar.Indicator" />
+  <public type="style" name="Widget.DeviceDefault.Light.RatingBar.Small" />
+  <public type="style" name="Widget.DeviceDefault.Light.CompoundButton.RadioButton" />
+  <public type="style" name="Widget.DeviceDefault.Light.ScrollView" />
+  <public type="style" name="Widget.DeviceDefault.Light.HorizontalScrollView" />
+  <public type="style" name="Widget.DeviceDefault.Light.Spinner" />
+  <public type="style" name="Widget.DeviceDefault.Light.CompoundButton.Star" />
+  <public type="style" name="Widget.DeviceDefault.Light.TabWidget" />
+  <public type="style" name="Widget.DeviceDefault.Light.WebTextView" />
+  <public type="style" name="Widget.DeviceDefault.Light.WebView" />
+  <public type="style" name="Widget.DeviceDefault.Light.DropDownItem" />
+  <public type="style" name="Widget.DeviceDefault.Light.DropDownItem.Spinner" />
+  <public type="style" name="Widget.DeviceDefault.Light.TextView.SpinnerItem" />
+  <public type="style" name="Widget.DeviceDefault.Light.ListPopupWindow" />
+  <public type="style" name="Widget.DeviceDefault.Light.PopupMenu" />
+  <public type="style" name="Widget.DeviceDefault.Light.Tab" />
+  <public type="style" name="Widget.DeviceDefault.Light.CalendarView" />
+  <public type="style" name="Widget.DeviceDefault.Light.ActionButton" />
+  <public type="style" name="Widget.DeviceDefault.Light.ActionButton.Overflow" />
+  <public type="style" name="Widget.DeviceDefault.Light.ActionMode" />
+  <public type="style" name="Widget.DeviceDefault.Light.ActionButton.CloseMode" />
+  <public type="style" name="Widget.DeviceDefault.Light.ActionBar" />
+  <public type="style" name="Widget.DeviceDefault.Light.ActionBar.TabView" />
+  <public type="style" name="Widget.DeviceDefault.Light.ActionBar.TabText" />
+  <public type="style" name="Widget.DeviceDefault.Light.ActionBar.TabBar" />
+  <public type="style" name="Widget.DeviceDefault.Light.ActionBar.Solid" />
+  <public type="style" name="Widget.DeviceDefault.Light.ActionBar.Solid.Inverse" />
+  <public type="style" name="Widget.DeviceDefault.Light.ActionBar.TabBar.Inverse" />
+  <public type="style" name="Widget.DeviceDefault.Light.ActionBar.TabView.Inverse" />
+  <public type="style" name="Widget.DeviceDefault.Light.ActionBar.TabText.Inverse" />
+  <public type="style" name="Widget.DeviceDefault.Light.ActionMode.Inverse" />
+
+  <public type="style" name="TextAppearance.DeviceDefault" />
+  <public type="style" name="TextAppearance.DeviceDefault.Inverse" />
+  <public type="style" name="TextAppearance.DeviceDefault.Large" />
+  <public type="style" name="TextAppearance.DeviceDefault.Large.Inverse" />
+  <public type="style" name="TextAppearance.DeviceDefault.Medium" />
+  <public type="style" name="TextAppearance.DeviceDefault.Medium.Inverse" />
+  <public type="style" name="TextAppearance.DeviceDefault.Small" />
+  <public type="style" name="TextAppearance.DeviceDefault.Small.Inverse" />
+  <public type="style" name="TextAppearance.DeviceDefault.SearchResult.Title" />
+  <public type="style" name="TextAppearance.DeviceDefault.SearchResult.Subtitle" />
+  <public type="style" name="TextAppearance.DeviceDefault.WindowTitle" />
+  <public type="style" name="TextAppearance.DeviceDefault.DialogWindowTitle" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.Button" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.IconMenu.Item" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.TabWidget" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.TextView" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.TextView.PopupMenu" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.DropDownHint" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.DropDownItem" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.TextView.SpinnerItem" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.EditText" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.PopupMenu" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.PopupMenu.Large" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.PopupMenu.Small" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.ActionBar.Title" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.ActionMode.Title" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.ActionBar.Title.Inverse" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle.Inverse" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.ActionMode.Title.Inverse" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle.Inverse" />
+  <public type="style" name="TextAppearance.DeviceDefault.Widget.ActionBar.Menu" />
+
+  <public type="style" name="DeviceDefault.ButtonBar" />
+  <public type="style" name="DeviceDefault.ButtonBar.AlertDialog" />
+  <public type="style" name="DeviceDefault.SegmentedButton" />
+  <public type="style" name="DeviceDefault.Light.ButtonBar" />
+  <public type="style" name="DeviceDefault.Light.ButtonBar.AlertDialog" />
+  <public type="style" name="DeviceDefault.Light.SegmentedButton" />
+
   <public type="integer" name="status_bar_notification_info_maxnum" />
   <public type="string" name="status_bar_notification_info_overflow" />
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a6c92f2..afd8908 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -212,8 +212,8 @@
     <!-- android.net.http Error strings --> <skip />
     <!-- Displayed when a web request was successful. -->
     <string name="httpErrorOk">OK</string>
-    <!-- Displayed when a web request failed because we don't know the exact reason. -->
-    <string name="httpError">The Web page contains an error.</string>
+    <!-- Displayed when a web request failed with a generic network error. -->
+    <string name="httpError">A network error occurred.</string>
     <!-- Displayed when a web request failed because the URL could not be found. -->
     <string name="httpErrorLookup">The URL could not be found.</string>
     <!-- Displayed when a web request failed because the site's authentication scheme is not supported by us. -->
@@ -1358,14 +1358,6 @@
       with Near Field Communication (NFC) tags, cards, and readers.</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_vpn">intercept and modify all network traffic</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_vpn">Allows an application to intercept and
-      inspect all network traffic to establish a VPN connection.
-      Malicious applications may monitor, redirect, or modify network packets
-      without your knowledge.</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_disableKeyguard">disable keylock</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_disableKeyguard">Allows an application to disable
@@ -2159,14 +2151,6 @@
 
     <!-- Title of an application permission, listed so the user can choose whether
         they want to allow the application to do this. [CHAR LIMIT=NONE] -->
-    <string name="permlab_readWriteOwnVoicemail">Access voicemails managed by this application</string>
-    <!-- Description of an application permission, listed so the user can choose whether
-        they want to allow the application to do this. [CHAR LIMIT=NONE] -->
-    <string name="permdesc_readWriteOwnVoicemail">Allows the application to store and retrieve only
-      voicemails that its associated service can access.</string>
-
-    <!-- Title of an application permission, listed so the user can choose whether
-        they want to allow the application to do this. [CHAR LIMIT=NONE] -->
     <string name="permlab_addVoicemail">add voicemail</string>
     <!-- Description of an application permission, listed so the user can choose whether
         they want to allow the application to do this. [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index ed2d3b0..0c6e20f 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -14,6 +14,20 @@
      limitations under the License.
 -->
 
+<!--
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Holo themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+ -->
 <resources>
     <!-- Global Theme Styles -->
     <eat-comment />
@@ -1730,6 +1744,7 @@
     </style>
 
     <style name="Widget.Holo.Spinner.DropDown.ActionBar">
+        <item name="android:background">@android:drawable/spinner_ab_holo_dark</item>
     </style>
 
     <style name="Widget.Holo.CompoundButton.Star" parent="Widget.CompoundButton.Star">
@@ -2117,6 +2132,7 @@
     </style>
 
     <style name="Widget.Holo.Light.Spinner.DropDown.ActionBar">
+        <item name="android:background">@android:drawable/spinner_ab_holo_light</item>
     </style>
 
     <style name="Widget.Holo.Light.CompoundButton.Star" parent="Widget.CompoundButton.Star">
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
new file mode 100644
index 0000000..7f1891e
--- /dev/null
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -0,0 +1,741 @@
+<?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.
+-->
+
+<!--
+===============================================================
+                        PLEASE READ
+===============================================================
+This file contains the themes that are the Device Defaults.
+If you want to edit styles to skin your device, do it here.
+We recommend that you do not edit styles.xml and instead edit
+this file.
+
+Editing this file instead of styles.xml will greatly simplify
+merges for future platform versions and CTS compliance will be
+easier.
+===============================================================
+                        PLEASE READ
+===============================================================
+ -->
+<resources>
+    <!-- Widget Styles -->
+    <style name="Widget.DeviceDefault" parent="Widget.Holo" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Button" parent="Widget.Holo.Button" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Button.Small" parent="Widget.Holo.Button.Small" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Button.Inset" parent="Widget.Holo.Button.Inset" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Button.Toggle" parent="Widget.Holo.Button.Toggle" >
+
+    </style>
+    <style name="Widget.DeviceDefault.TextView" parent="Widget.Holo.TextView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.AutoCompleteTextView" parent="Widget.Holo.AutoCompleteTextView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.CompoundButton.CheckBox" parent="Widget.Holo.CompoundButton.CheckBox" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ListView.DropDown" parent="Widget.Holo.ListView.DropDown" >
+
+    </style>
+    <style name="Widget.DeviceDefault.EditText" parent="Widget.Holo.EditText" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ExpandableListView" parent="Widget.Holo.ExpandableListView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.GridView" parent="Widget.Holo.GridView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ImageButton" parent="Widget.Holo.ImageButton" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ListView" parent="Widget.Holo.ListView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.PopupWindow" parent="Widget.Holo.PopupWindow" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ProgressBar" parent="Widget.Holo.ProgressBar" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ProgressBar.Horizontal" parent="Widget.Holo.ProgressBar.Horizontal" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ProgressBar.Small" parent="Widget.Holo.ProgressBar.Small" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ProgressBar.Small.Title" parent="Widget.Holo.ProgressBar.Small.Title" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ProgressBar.Large" parent="Widget.Holo.ProgressBar.Large" >
+
+    </style>
+    <style name="Widget.DeviceDefault.SeekBar" parent="Widget.Holo.SeekBar" >
+
+    </style>
+    <style name="Widget.DeviceDefault.RatingBar" parent="Widget.Holo.RatingBar" >
+
+    </style>
+    <style name="Widget.DeviceDefault.RatingBar.Indicator" parent="Widget.Holo.RatingBar.Indicator" >
+
+    </style>
+    <style name="Widget.DeviceDefault.RatingBar.Small" parent="Widget.Holo.RatingBar.Small" >
+
+    </style>
+    <style name="Widget.DeviceDefault.CompoundButton.RadioButton" parent="Widget.Holo.CompoundButton.RadioButton" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ScrollView" parent="Widget.Holo.ScrollView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.HorizontalScrollView" parent="Widget.Holo.HorizontalScrollView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Spinner" parent="Widget.Holo.Spinner" >
+
+    </style>
+    <style name="Widget.DeviceDefault.CompoundButton.Star" parent="Widget.Holo.CompoundButton.Star" >
+
+    </style>
+    <style name="Widget.DeviceDefault.TabWidget" parent="Widget.Holo.TabWidget" >
+
+    </style>
+    <style name="Widget.DeviceDefault.WebTextView" parent="Widget.Holo.WebTextView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.WebView" parent="Widget.Holo.WebView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.DropDownItem" parent="Widget.Holo.DropDownItem" >
+
+    </style>
+    <style name="Widget.DeviceDefault.DropDownItem.Spinner" parent="Widget.Holo.DropDownItem.Spinner" >
+
+    </style>
+    <style name="Widget.DeviceDefault.TextView.SpinnerItem" parent="Widget.Holo.TextView.SpinnerItem" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ListPopupWindow" parent="Widget.Holo.ListPopupWindow" >
+
+    </style>
+    <style name="Widget.DeviceDefault.PopupMenu" parent="Widget.Holo.PopupMenu" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ActionButton" parent="Widget.Holo.ActionButton" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ActionButton.Overflow" parent="Widget.Holo.ActionButton.Overflow" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ActionButton.TextButton" parent="Widget.Holo.ActionButton.TextButton" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ActionMode" parent="Widget.Holo.ActionMode" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ActionButton.CloseMode" parent="Widget.Holo.ActionButton.CloseMode" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ActionBar" parent="Widget.Holo.ActionBar" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Button.Borderless" parent="Widget.Holo.Button.Borderless" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Tab" parent="Widget.Holo.Tab" >
+
+    </style>
+    <style name="Widget.DeviceDefault.CalendarView" parent="Widget.Holo.CalendarView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.DatePicker" parent="Widget.Holo.DatePicker" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ActionBar.TabView" parent="Widget.Holo.ActionBar.TabView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ActionBar.TabText" parent="Widget.Holo.ActionBar.TabText" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ActionBar.TabBar" parent="Widget.Holo.ActionBar.TabBar" >
+
+    </style>
+    <style name="Widget.DeviceDefault.ActionBar.Solid" parent="Widget.Holo.ActionBar.Solid" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Button.Borderless.Small" parent="Widget.Holo.Button.Borderless.Small" >
+
+    </style>
+    <style name="Widget.DeviceDefault.AbsListView" parent="Widget.Holo.AbsListView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Spinner.DropDown.ActionBar" parent="Widget.Holo.Spinner.DropDown.ActionBar" >
+
+    </style>
+    <style name="Widget.DeviceDefault.PopupWindow.ActionMode" parent="Widget.Holo.PopupWindow.ActionMode" >
+
+    </style>
+    <style name="Widget.DeviceDefault.CompoundButton.Switch" parent="Widget.Holo.CompoundButton.Switch">
+
+    </style>
+    <style name="Widget.DeviceDefault.EditText.NumberPickerInputText" parent="Widget.Holo.EditText.NumberPickerInputText">
+
+    </style>
+    <style name="Widget.DeviceDefault.ExpandableListView.White" parent="Widget.Holo.ExpandableListView.White">
+
+    </style>
+    <style name="Widget.DeviceDefault.Gallery" parent="Widget.Holo.Gallery">
+
+    </style>
+    <style name="Widget.DeviceDefault.GestureOverlayView" parent="Widget.Holo.GestureOverlayView">
+
+    </style>
+    <style name="Widget.DeviceDefault.ImageButton.NumberPickerDownButton" parent="Widget.Holo.ImageButton.NumberPickerDownButton">
+
+    </style>
+    <style name="Widget.DeviceDefault.ImageButton.NumberPickerUpButton" parent="Widget.Holo.ImageButton.NumberPickerUpButton">
+
+    </style>
+    <style name="Widget.DeviceDefault.ImageWell" parent="Widget.Holo.ImageWell">
+
+    </style>
+    <style name="Widget.DeviceDefault.KeyboardView" parent="Widget.Holo.KeyboardView">
+
+    </style>
+    <style name="Widget.DeviceDefault.ListView.White" parent="Widget.Holo.ListView.White">
+
+    </style>
+    <style name="Widget.DeviceDefault.NumberPicker" parent="Widget.Holo.NumberPicker">
+
+    </style>
+    <style name="Widget.DeviceDefault.PreferenceFrameLayout" parent="Widget.Holo.PreferenceFrameLayout">
+
+    </style>
+    <style name="Widget.DeviceDefault.ProgressBar.Inverse" parent="Widget.Holo.ProgressBar.Inverse">
+
+
+    </style>
+    <style name="Widget.DeviceDefault.ProgressBar.Large.Inverse" parent="Widget.Holo.ProgressBar.Large.Inverse">
+
+    </style>
+    <style name="Widget.DeviceDefault.ProgressBar.Small.Inverse" parent="Widget.Holo.ProgressBar.Small.Inverse">
+
+    </style>
+    <style name="Widget.DeviceDefault.QuickContactBadge.WindowLarge" parent="Widget.Holo.QuickContactBadge.WindowLarge">
+
+    </style>
+    <style name="Widget.DeviceDefault.QuickContactBadge.WindowMedium" parent="Widget.Holo.QuickContactBadge.WindowMedium">
+
+    </style>
+    <style name="Widget.DeviceDefault.QuickContactBadge.WindowSmall" parent="Widget.Holo.QuickContactBadge.WindowSmall">
+
+    </style>
+    <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowLarge" parent="Widget.Holo.QuickContactBadgeSmall.WindowLarge">
+
+    </style>
+    <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowMedium" parent="Widget.Holo.QuickContactBadgeSmall.WindowMedium">
+
+    </style>
+    <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowSmall" parent="Widget.Holo.QuickContactBadgeSmall.WindowSmall">
+
+    </style>
+    <style name="Widget.DeviceDefault.Spinner.DropDown" parent="Widget.Holo.Spinner.DropDown">
+
+    </style>
+    <style name="Widget.DeviceDefault.StackView" parent="Widget.Holo.StackView">
+
+    </style>
+    <style name="Widget.DeviceDefault.TextSelectHandle" parent="Widget.Holo.TextSelectHandle">
+
+    </style>
+    <style name="Widget.DeviceDefault.TextSuggestionsPopupWindow" parent="Widget.Holo.TextSuggestionsPopupWindow">
+
+    </style>
+    <style name="Widget.DeviceDefault.TextView.ListSeparator" parent="Widget.Holo.TextView.ListSeparator">
+
+    </style>
+    <style name="Widget.DeviceDefault.TimePicker" parent="Widget.Holo.TimePicker">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light" parent="Widget.Holo.Light" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.Button" parent="Widget.Holo.Light.Button" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.Button.Small" parent="Widget.Holo.Light.Button.Small" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.Button.Inset" parent="Widget.Holo.Light.Button.Inset" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.Button.Toggle" parent="Widget.Holo.Light.Button.Toggle" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.TextView" parent="Widget.Holo.Light.TextView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.AutoCompleteTextView" parent="Widget.Holo.Light.AutoCompleteTextView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.CompoundButton.CheckBox" parent="Widget.Holo.Light.CompoundButton.CheckBox" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ListView.DropDown" parent="Widget.Holo.Light.ListView.DropDown" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.EditText" parent="Widget.Holo.Light.EditText" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ExpandableListView" parent="Widget.Holo.Light.ExpandableListView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.GridView" parent="Widget.Holo.Light.GridView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ImageButton" parent="Widget.Holo.Light.ImageButton" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ListView" parent="Widget.Holo.Light.ListView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.PopupWindow" parent="Widget.Holo.Light.PopupWindow" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ProgressBar" parent="Widget.Holo.Light.ProgressBar" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ProgressBar.Horizontal" parent="Widget.Holo.Light.ProgressBar.Horizontal" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ProgressBar.Small" parent="Widget.Holo.Light.ProgressBar.Small" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ProgressBar.Small.Title" parent="Widget.Holo.Light.ProgressBar.Small.Title" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ProgressBar.Large" parent="Widget.Holo.Light.ProgressBar.Large" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ProgressBar.Inverse" parent="Widget.Holo.Light.ProgressBar.Inverse" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ProgressBar.Small.Inverse" parent="Widget.Holo.Light.ProgressBar.Small.Inverse" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ProgressBar.Large.Inverse" parent="Widget.Holo.Light.ProgressBar.Large.Inverse" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.SeekBar" parent="Widget.Holo.Light.SeekBar" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.RatingBar" parent="Widget.Holo.Light.RatingBar" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.RatingBar.Indicator" parent="Widget.Holo.Light.RatingBar.Indicator" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.RatingBar.Small" parent="Widget.Holo.Light.RatingBar.Small" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.CompoundButton.RadioButton" parent="Widget.Holo.Light.CompoundButton.RadioButton" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ScrollView" parent="Widget.Holo.Light.ScrollView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.HorizontalScrollView" parent="Widget.Holo.Light.HorizontalScrollView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.Spinner" parent="Widget.Holo.Light.Spinner" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.CompoundButton.Star" parent="Widget.Holo.Light.CompoundButton.Star" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.TabWidget" parent="Widget.Holo.Light.TabWidget" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.WebTextView" parent="Widget.Holo.Light.WebTextView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.WebView" parent="Widget.Holo.Light.WebView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.DropDownItem" parent="Widget.Holo.Light.DropDownItem" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.DropDownItem.Spinner" parent="Widget.Holo.Light.DropDownItem.Spinner" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.TextView.SpinnerItem" parent="Widget.Holo.Light.TextView.SpinnerItem" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ListPopupWindow" parent="Widget.Holo.Light.ListPopupWindow" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.PopupMenu" parent="Widget.Holo.Light.PopupMenu" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.Tab" parent="Widget.Holo.Light.Tab" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.CalendarView" parent="Widget.Holo.Light.CalendarView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.Button.Borderless.Small" parent="Widget.Holo.Light.Button.Borderless.Small" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ActionButton" parent="Widget.Holo.Light.ActionButton" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ActionButton.Overflow" parent="Widget.Holo.Light.ActionButton.Overflow" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ActionMode" parent="Widget.Holo.Light.ActionMode" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ActionButton.CloseMode" parent="Widget.Holo.Light.ActionButton.CloseMode" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ActionBar" parent="Widget.Holo.Light.ActionBar" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ActionBar.TabView" parent="Widget.Holo.Light.ActionBar.TabView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ActionBar.TabText" parent="Widget.Holo.Light.ActionBar.TabText" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ActionBar.TabBar" parent="Widget.Holo.Light.ActionBar.TabBar" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ActionBar.Solid" parent="Widget.Holo.Light.ActionBar.Solid" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ActionBar.Solid.Inverse" parent="Widget.Holo.Light.ActionBar.Solid.Inverse" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ActionBar.TabBar.Inverse" parent="Widget.Holo.Light.ActionBar.TabBar.Inverse" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ActionBar.TabView.Inverse" parent="Widget.Holo.Light.ActionBar.TabView.Inverse" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ActionBar.TabText.Inverse" parent="Widget.Holo.Light.ActionBar.TabText.Inverse" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ActionMode.Inverse" parent="Widget.Holo.Light.ActionMode.Inverse" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.AbsListView" parent="Widget.Holo.Light.AbsListView" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.Spinner.DropDown.ActionBar" parent="Widget.Holo.Light.Spinner.DropDown.ActionBar" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.PopupWindow.ActionMode" parent="Widget.Holo.Light.PopupWindow.ActionMode" >
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.Button.Borderless" parent="Widget.Holo.Light.Button.Borderless">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.DatePicker" parent="Widget.Holo.Light.DatePicker">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.EditText.NumberPickerInputText" parent="Widget.Holo.Light.EditText.NumberPickerInputText">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ExpandableListView.White" parent="Widget.Holo.Light.ExpandableListView.White">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.Gallery" parent="Widget.Holo.Light.Gallery">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.GestureOverlayView" parent="Widget.Holo.Light.GestureOverlayView">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ImageButton.NumberPickerDownButton" parent="Widget.Holo.Light.ImageButton.NumberPickerDownButton">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ImageButton.NumberPickerUpButton" parent="Widget.Holo.Light.ImageButton.NumberPickerUpButton">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ImageWell" parent="Widget.Holo.Light.ImageWell">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.ListView.White" parent="Widget.Holo.Light.ListView.White">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.NumberPicker" parent="Widget.Holo.Light.NumberPicker">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.Spinner.DropDown" parent="Widget.Holo.Light.Spinner.DropDown">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.TextView.ListSeparator" parent="Widget.Holo.Light.TextView.ListSeparator">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.TimePicker" parent="Widget.Holo.Light.TimePicker">
+
+    </style>
+    <style name="Widget.DeviceDefault.Light.TextSuggestionsPopupWindow" parent="Widget.Holo.Light.TextSuggestionsPopupWindow">
+
+    </style>
+
+
+    <!-- Text Appearance Styles -->
+    <style name="TextAppearance.DeviceDefault" parent="TextAppearance.Holo" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Inverse" parent="TextAppearance.Holo.Inverse" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Large" parent="TextAppearance.Holo.Large" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Large.Inverse" parent="TextAppearance.Holo.Large.Inverse" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Medium" parent="TextAppearance.Holo.Medium" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Medium.Inverse" parent="TextAppearance.Holo.Medium.Inverse" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Small" parent="TextAppearance.Holo.Small" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Small.Inverse" parent="TextAppearance.Holo.Small.Inverse" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.SearchResult.Title" parent="TextAppearance.Holo.SearchResult.Title" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.SearchResult.Subtitle" parent="TextAppearance.Holo.SearchResult.Subtitle" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget" parent="TextAppearance.Holo.Widget" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.Button" parent="TextAppearance.Holo.Widget.Button" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.IconMenu.Item" parent="TextAppearance.Holo.Widget.IconMenu.Item" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.TabWidget" parent="TextAppearance.Holo.Widget.TabWidget" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.TextView" parent="TextAppearance.Holo.Widget.TextView" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.TextView.PopupMenu" parent="TextAppearance.Holo.Widget.TextView.PopupMenu" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.DropDownHint" parent="TextAppearance.Holo.Widget.DropDownHint" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.DropDownItem" parent="TextAppearance.Holo.Widget.DropDownItem" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.TextView.SpinnerItem" parent="TextAppearance.Holo.Widget.TextView.SpinnerItem" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.EditText" parent="TextAppearance.Holo.Widget.EditText" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.PopupMenu" parent="TextAppearance.Holo.Widget.PopupMenu" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.PopupMenu.Large" parent="TextAppearance.Holo.Widget.PopupMenu.Large" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.PopupMenu.Small" parent="TextAppearance.Holo.Widget.PopupMenu.Small" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Title" parent="TextAppearance.Holo.Widget.ActionBar.Title" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle" parent="TextAppearance.Holo.Widget.ActionBar.Subtitle" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Title" parent="TextAppearance.Holo.Widget.ActionMode.Title" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle" parent="TextAppearance.Holo.Widget.ActionMode.Subtitle" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.WindowTitle" parent="TextAppearance.Holo.WindowTitle" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.DialogWindowTitle" parent="TextAppearance.Holo.DialogWindowTitle" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Title.Inverse" parent="TextAppearance.Holo.Widget.ActionBar.Title.Inverse" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle.Inverse" parent="TextAppearance.Holo.Widget.ActionBar.Subtitle.Inverse" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Title.Inverse" parent="TextAppearance.Holo.Widget.ActionMode.Title.Inverse" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Holo.Widget.ActionMode.Subtitle.Inverse" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Menu" parent="TextAppearance.Holo.Widget.ActionBar.Menu" >
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Light" parent="TextAppearance.Holo.Light">
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Light.Inverse" parent="TextAppearance.Holo.Light.Inverse">
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Light.Large" parent="TextAppearance.Holo.Light.Large">
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Light.Large.Inverse" parent="TextAppearance.Holo.Light.Large.Inverse">
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Light.Medium" parent="TextAppearance.Holo.Light.Medium">
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Light.Medium.Inverse" parent="TextAppearance.Holo.Light.Medium.Inverse">
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Light.SearchResult.Subtitle" parent="TextAppearance.Holo.Light.SearchResult.Subtitle">
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Light.SearchResult.Title" parent="TextAppearance.Holo.Light.SearchResult.Title">
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Light.Small" parent="TextAppearance.Holo.Light.Small">
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Light.Small.Inverse" parent="TextAppearance.Holo.Light.Small.Inverse">
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Light.Widget.Button" parent="TextAppearance.Holo.Light.Widget.Button">
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Large" parent="TextAppearance.Holo.Light.Widget.PopupMenu.Large">
+
+    </style>
+    <style name="TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Small" parent="TextAppearance.Holo.Light.Widget.PopupMenu.Small">
+
+    </style>
+
+
+    <!-- Preference Styles -->
+    <style name="Preference.DeviceDefault" parent="Preference.Holo">
+
+    </style>
+    <style name="Preference.DeviceDefault.Category" parent="Preference.Holo.Category">
+
+    </style>
+    <style name="Preference.DeviceDefault.CheckBoxPreference" parent="Preference.Holo.CheckBoxPreference">
+
+    </style>
+    <style name="Preference.DeviceDefault.DialogPreference" parent="Preference.Holo.DialogPreference">
+
+    </style>
+    <style name="Preference.DeviceDefault.DialogPreference.EditTextPreference" parent="Preference.Holo.DialogPreference.EditTextPreference">
+
+    </style>
+    <style name="Preference.DeviceDefault.DialogPreference.YesNoPreference" parent="Preference.Holo.DialogPreference.YesNoPreference">
+
+    </style>
+    <style name="Preference.DeviceDefault.Information" parent="Preference.Holo.Information">
+
+    </style>
+    <style name="Preference.DeviceDefault.PreferenceScreen" parent="Preference.Holo.PreferenceScreen">
+
+    </style>
+    <style name="Preference.DeviceDefault.RingtonePreference" parent="Preference.Holo.RingtonePreference">
+
+    </style>
+    <style name="Preference.DeviceDefault.SwitchPreference" parent="Preference.Holo.SwitchPreference">
+
+    </style>
+
+
+    <!-- AlertDialog Styles -->
+    <style name="AlertDialog.DeviceDefault" parent="AlertDialog.Holo">
+
+    </style>
+    <style name="AlertDialog.DeviceDefault.Light" parent="AlertDialog.DeviceDefault.Light" >
+
+    </style>
+
+
+    <!-- Animation Styles -->
+    <style name="Animation.DeviceDefault.Activity" parent="Animation.Holo.Activity">
+
+    </style>
+    <style name="Animation.DeviceDefault.Dialog" parent="Animation.Holo.Dialog">
+
+    </style>
+
+
+    <!-- DialogWindowTitle Styles -->
+    <style name="DialogWindowTitle.DeviceDefault" parent="DialogWindowTitle.Holo">
+
+    </style>
+    <style name="DialogWindowTitle.DeviceDefault.Light" parent="DialogWindowTitle.Holo.Light">
+
+    </style>
+
+
+    <!-- WindowTitle Styles -->
+    <style name="WindowTitle.DeviceDefault" parent="WindowTitle.Holo">
+
+    </style>
+    <style name="WindowTitleBackground.DeviceDefault" parent="WindowTitleBackground.Holo">
+
+    </style>
+
+
+    <!-- Other Styles -->
+    <style name="DeviceDefault.ButtonBar" parent="Holo.ButtonBar" >
+
+    </style>
+    <style name="DeviceDefault.ButtonBar.AlertDialog" parent="Holo.ButtonBar.AlertDialog" >
+
+    </style>
+    <style name="DeviceDefault.SegmentedButton" parent="Holo.SegmentedButton" >
+
+    </style>
+    <style name="DeviceDefault.Light.ButtonBar" parent="Holo.Light.ButtonBar" >
+
+    </style>
+    <style name="DeviceDefault.Light.ButtonBar.AlertDialog" parent="Holo.Light.ButtonBar.AlertDialog" >
+
+    </style>
+    <style name="DeviceDefault.Light.SegmentedButton" parent="Holo.Light.SegmentedButton" >
+
+    </style>
+</resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 2b1b693..615a37d 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -14,6 +14,20 @@
      limitations under the License.
 -->
 
+<!--
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Holo themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see themes_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+ -->
 <resources>
     <!-- The default system theme. This is the theme used for activities
          that have not explicitly set their own theme.
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
new file mode 100644
index 0000000..bf6329d
--- /dev/null
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -0,0 +1,423 @@
+<?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.
+-->
+
+<!--
+===============================================================
+                        PLEASE READ
+===============================================================
+This file contains the themes that are the Device Defaults.
+If you want to edit themes to skin your device, do it here.
+We recommend that you do not edit themes.xml and instead edit
+this file.
+
+Editing this file instead of themes.xml will greatly simplify
+merges for future platform versions and CTS compliance will be
+easier.
+===============================================================
+                        PLEASE READ
+===============================================================
+ -->
+<resources>
+    <style name="Theme.DeviceDefault" parent="Theme.Holo" >
+        <!-- Text styles -->
+        <item name="textAppearance">@android:style/TextAppearance.DeviceDefault</item>
+        <item name="textAppearanceInverse">@android:style/TextAppearance.DeviceDefault.Inverse</item>
+
+        <item name="textAppearanceLarge">@android:style/TextAppearance.DeviceDefault.Large</item>
+        <item name="textAppearanceMedium">@android:style/TextAppearance.DeviceDefault.Medium</item>
+        <item name="textAppearanceSmall">@android:style/TextAppearance.DeviceDefault.Small</item>
+        <item name="textAppearanceLargeInverse">@android:style/TextAppearance.DeviceDefault.Large.Inverse</item>
+        <item name="textAppearanceMediumInverse">@android:style/TextAppearance.DeviceDefault.Medium.Inverse</item>
+        <item name="textAppearanceSmallInverse">@android:style/TextAppearance.DeviceDefault.Small.Inverse</item>
+        <item name="textAppearanceSearchResultTitle">@android:style/TextAppearance.DeviceDefault.SearchResult.Title</item>
+        <item name="textAppearanceSearchResultSubtitle">@android:style/TextAppearance.DeviceDefault.SearchResult.Subtitle</item>
+
+        <item name="textAppearanceButton">@android:style/TextAppearance.DeviceDefault.Widget.Button</item>
+
+        <item name="textAppearanceLargePopupMenu">@android:style/TextAppearance.DeviceDefault.Widget.PopupMenu.Large</item>
+        <item name="textAppearanceSmallPopupMenu">@android:style/TextAppearance.DeviceDefault.Widget.PopupMenu.Small</item>
+
+        <!-- Button styles -->
+        <item name="buttonStyle">@android:style/Widget.DeviceDefault.Button</item>
+
+        <item name="buttonStyleSmall">@android:style/Widget.DeviceDefault.Button.Small</item>
+        <item name="buttonStyleInset">@android:style/Widget.DeviceDefault.Button.Inset</item>
+
+        <item name="buttonStyleToggle">@android:style/Widget.DeviceDefault.Button.Toggle</item>
+        <item name="switchStyle">@android:style/Widget.DeviceDefault.CompoundButton.Switch</item>
+
+        <item name="borderlessButtonStyle">@android:style/Widget.DeviceDefault.Button.Borderless</item>
+
+        <item name="listSeparatorTextViewStyle">@android:style/Widget.DeviceDefault.TextView.ListSeparator</item>
+
+        <!-- Window attributes -->
+        <item name="windowTitleStyle">@android:style/WindowTitle.DeviceDefault</item>
+        <item name="windowTitleBackgroundStyle">@android:style/WindowTitleBackground.DeviceDefault</item>
+        <item name="android:windowAnimationStyle">@android:style/Animation.DeviceDefault.Activity</item>
+
+        <!-- Dialog attributes -->
+        <item name="alertDialogStyle">@android:style/AlertDialog.DeviceDefault</item>
+        <item name="dialogTheme">@android:style/Theme.DeviceDefault.Dialog</item>
+        <item name="alertDialogTheme">@android:style/Theme.DeviceDefault.Dialog.Alert</item>
+
+        <!-- Text selection handle attributes -->
+        <item name="textSelectHandleWindowStyle">@android:style/Widget.DeviceDefault.TextSelectHandle</item>
+        <item name="textSuggestionsWindowStyle">@android:style/Widget.DeviceDefault.TextSuggestionsPopupWindow</item>
+
+        <!-- Widget styles -->
+        <item name="absListViewStyle">@android:style/Widget.DeviceDefault.AbsListView</item>
+        <item name="autoCompleteTextViewStyle">@android:style/Widget.DeviceDefault.AutoCompleteTextView</item>
+        <item name="checkboxStyle">@android:style/Widget.DeviceDefault.CompoundButton.CheckBox</item>
+        <item name="dropDownListViewStyle">@android:style/Widget.DeviceDefault.ListView.DropDown</item>
+        <item name="editTextStyle">@android:style/Widget.DeviceDefault.EditText</item>
+        <item name="expandableListViewStyle">@android:style/Widget.DeviceDefault.ExpandableListView</item>
+        <item name="expandableListViewWhiteStyle">@android:style/Widget.DeviceDefault.ExpandableListView.White</item>
+        <item name="galleryStyle">@android:style/Widget.DeviceDefault.Gallery</item>
+        <item name="gestureOverlayViewStyle">@android:style/Widget.DeviceDefault.GestureOverlayView</item>
+        <item name="gridViewStyle">@android:style/Widget.DeviceDefault.GridView</item>
+        <item name="imageButtonStyle">@android:style/Widget.DeviceDefault.ImageButton</item>
+        <item name="imageWellStyle">@android:style/Widget.DeviceDefault.ImageWell</item>
+        <item name="listViewStyle">@android:style/Widget.DeviceDefault.ListView</item>
+        <item name="listViewWhiteStyle">@android:style/Widget.DeviceDefault.ListView.White</item>
+        <item name="popupWindowStyle">@android:style/Widget.DeviceDefault.PopupWindow</item>
+        <item name="progressBarStyle">@android:style/Widget.DeviceDefault.ProgressBar</item>
+        <item name="progressBarStyleHorizontal">@android:style/Widget.DeviceDefault.ProgressBar.Horizontal</item>
+        <item name="progressBarStyleSmall">@android:style/Widget.DeviceDefault.ProgressBar.Small</item>
+        <item name="progressBarStyleSmallTitle">@android:style/Widget.DeviceDefault.ProgressBar.Small.Title</item>
+        <item name="progressBarStyleLarge">@android:style/Widget.DeviceDefault.ProgressBar.Large</item>
+        <item name="progressBarStyleInverse">@android:style/Widget.DeviceDefault.ProgressBar.Inverse</item>
+        <item name="progressBarStyleSmallInverse">@android:style/Widget.DeviceDefault.ProgressBar.Small.Inverse</item>
+        <item name="progressBarStyleLargeInverse">@android:style/Widget.DeviceDefault.ProgressBar.Large.Inverse</item>
+        <item name="seekBarStyle">@android:style/Widget.DeviceDefault.SeekBar</item>
+        <item name="ratingBarStyle">@android:style/Widget.DeviceDefault.RatingBar</item>
+        <item name="ratingBarStyleIndicator">@android:style/Widget.DeviceDefault.RatingBar.Indicator</item>
+        <item name="ratingBarStyleSmall">@android:style/Widget.DeviceDefault.RatingBar.Small</item>
+        <item name="radioButtonStyle">@android:style/Widget.DeviceDefault.CompoundButton.RadioButton</item>
+        <item name="scrollViewStyle">@android:style/Widget.DeviceDefault.ScrollView</item>
+        <item name="horizontalScrollViewStyle">@android:style/Widget.DeviceDefault.HorizontalScrollView</item>
+        <item name="dropDownSpinnerStyle">@android:style/Widget.DeviceDefault.Spinner.DropDown</item>
+        <item name="starStyle">@android:style/Widget.DeviceDefault.CompoundButton.Star</item>
+        <item name="tabWidgetStyle">@android:style/Widget.DeviceDefault.TabWidget</item>
+        <item name="textViewStyle">@android:style/Widget.DeviceDefault.TextView</item>
+        <item name="webTextViewStyle">@android:style/Widget.DeviceDefault.WebTextView</item>
+        <item name="webViewStyle">@android:style/Widget.DeviceDefault.WebView</item>
+        <item name="dropDownItemStyle">@android:style/Widget.DeviceDefault.DropDownItem</item>
+        <item name="spinnerDropDownItemStyle">@android:style/Widget.DeviceDefault.DropDownItem.Spinner</item>
+        <item name="spinnerItemStyle">@android:style/Widget.DeviceDefault.TextView.SpinnerItem</item>
+        <item name="dropDownHintAppearance">@android:style/TextAppearance.DeviceDefault.Widget.DropDownHint</item>
+        <item name="keyboardViewStyle">@android:style/Widget.DeviceDefault.KeyboardView</item>
+        <item name="quickContactBadgeStyleWindowSmall">@android:style/Widget.DeviceDefault.QuickContactBadge.WindowSmall</item>
+        <item name="quickContactBadgeStyleWindowMedium">@android:style/Widget.DeviceDefault.QuickContactBadge.WindowMedium</item>
+        <item name="quickContactBadgeStyleWindowLarge">@android:style/Widget.DeviceDefault.QuickContactBadge.WindowLarge</item>
+        <item name="quickContactBadgeStyleSmallWindowSmall">@android:style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowSmall</item>
+        <item name="quickContactBadgeStyleSmallWindowMedium">@android:style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowMedium</item>
+        <item name="quickContactBadgeStyleSmallWindowLarge">@android:style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowLarge</item>
+        <item name="listPopupWindowStyle">@android:style/Widget.DeviceDefault.ListPopupWindow</item>
+        <item name="popupMenuStyle">@android:style/Widget.DeviceDefault.PopupMenu</item>
+        <item name="stackViewStyle">@android:style/Widget.DeviceDefault.StackView</item>
+
+        <!-- Preference styles -->
+        <item name="preferenceScreenStyle">@android:style/Preference.DeviceDefault.PreferenceScreen</item>
+        <item name="preferenceCategoryStyle">@android:style/Preference.DeviceDefault.Category</item>
+        <item name="preferenceStyle">@android:style/Preference.DeviceDefault</item>
+        <item name="preferenceInformationStyle">@android:style/Preference.DeviceDefault.Information</item>
+        <item name="checkBoxPreferenceStyle">@android:style/Preference.DeviceDefault.CheckBoxPreference</item>
+        <item name="switchPreferenceStyle">@android:style/Preference.DeviceDefault.SwitchPreference</item>
+        <item name="yesNoPreferenceStyle">@android:style/Preference.DeviceDefault.DialogPreference.YesNoPreference</item>
+        <item name="dialogPreferenceStyle">@android:style/Preference.DeviceDefault.DialogPreference</item>
+        <item name="editTextPreferenceStyle">@android:style/Preference.DeviceDefault.DialogPreference.EditTextPreference</item>
+        <item name="ringtonePreferenceStyle">@android:style/Preference.DeviceDefault.RingtonePreference</item>
+
+        <!-- Action bar styles -->
+        <item name="actionDropDownStyle">@android:style/Widget.DeviceDefault.Spinner.DropDown.ActionBar</item>
+        <item name="actionButtonStyle">@android:style/Widget.DeviceDefault.ActionButton</item>
+        <item name="actionOverflowButtonStyle">@android:style/Widget.DeviceDefault.ActionButton.Overflow</item>
+        <item name="actionBarTabStyle">@style/Widget.DeviceDefault.ActionBar.TabView</item>
+        <item name="actionBarTabBarStyle">@style/Widget.DeviceDefault.ActionBar.TabBar</item>
+        <item name="actionBarTabTextStyle">@style/Widget.DeviceDefault.ActionBar.TabText</item>
+        <item name="actionModeStyle">@style/Widget.DeviceDefault.ActionMode</item>
+        <item name="actionModeCloseButtonStyle">@style/Widget.DeviceDefault.ActionButton.CloseMode</item>
+        <item name="actionBarStyle">@android:style/Widget.DeviceDefault.ActionBar</item>
+        <item name="actionModePopupWindowStyle">@android:style/Widget.DeviceDefault.PopupWindow.ActionMode</item>
+
+        <item name="buttonBarStyle">@android:style/DeviceDefault.ButtonBar</item>
+        <item name="segmentedButtonStyle">@android:style/DeviceDefault.SegmentedButton</item>
+
+        <item name="searchDialogTheme">@style/Theme.DeviceDefault.SearchBar</item>
+
+        <!-- PreferenceFrameLayout attributes -->
+        <item name="preferenceFrameLayoutStyle">@android:style/Widget.DeviceDefault.PreferenceFrameLayout</item>
+
+        <!-- NumberPicker styles-->
+        <item name="numberPickerUpButtonStyle">@style/Widget.DeviceDefault.ImageButton.NumberPickerUpButton</item>
+        <item name="numberPickerDownButtonStyle">@style/Widget.DeviceDefault.ImageButton.NumberPickerDownButton</item>
+        <item name="numberPickerInputTextStyle">@style/Widget.DeviceDefault.EditText.NumberPickerInputText</item>
+        <item name="numberPickerStyle">@style/Widget.DeviceDefault.NumberPicker</item>
+
+        <!-- CalendarView style-->
+        <item name="calendarViewStyle">@style/Widget.DeviceDefault.CalendarView</item>
+
+        <!-- TimePicker style -->
+        <item name="timePickerStyle">@style/Widget.DeviceDefault.TimePicker</item>
+
+        <!-- DatePicker style -->
+        <item name="datePickerStyle">@style/Widget.DeviceDefault.DatePicker</item>
+    </style>
+    <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Holo.NoActionBar" >
+
+    </style>
+    <style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Holo.NoActionBar.Fullscreen" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Light" parent="Theme.Holo.Light" >
+        <!-- Text styles -->
+        <item name="textAppearance">@android:style/TextAppearance.DeviceDefault.Light</item>
+        <item name="textAppearanceInverse">@android:style/TextAppearance.DeviceDefault.Light.Inverse</item>
+
+        <item name="textAppearanceLarge">@android:style/TextAppearance.DeviceDefault.Light.Large</item>
+        <item name="textAppearanceMedium">@android:style/TextAppearance.DeviceDefault.Light.Medium</item>
+        <item name="textAppearanceSmall">@android:style/TextAppearance.DeviceDefault.Light.Small</item>
+        <item name="textAppearanceLargeInverse">@android:style/TextAppearance.DeviceDefault.Light.Large.Inverse</item>
+        <item name="textAppearanceMediumInverse">@android:style/TextAppearance.DeviceDefault.Light.Medium.Inverse</item>
+        <item name="textAppearanceSmallInverse">@android:style/TextAppearance.DeviceDefault.Light.Small.Inverse</item>
+        <item name="textAppearanceSearchResultTitle">@android:style/TextAppearance.DeviceDefault.Light.SearchResult.Title</item>
+        <item name="textAppearanceSearchResultSubtitle">@android:style/TextAppearance.DeviceDefault.Light.SearchResult.Subtitle</item>
+
+        <item name="textAppearanceButton">@android:style/TextAppearance.DeviceDefault.Light.Widget.Button</item>
+
+        <item name="textAppearanceLargePopupMenu">@android:style/TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Large</item>
+        <item name="textAppearanceSmallPopupMenu">@android:style/TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Small</item>
+
+        <!-- Button styles -->
+        <item name="buttonStyle">@android:style/Widget.DeviceDefault.Light.Button</item>
+
+        <item name="buttonStyleSmall">@android:style/Widget.DeviceDefault.Light.Button.Small</item>
+        <item name="buttonStyleInset">@android:style/Widget.DeviceDefault.Light.Button.Inset</item>
+
+        <item name="buttonStyleToggle">@android:style/Widget.DeviceDefault.Light.Button.Toggle</item>
+
+        <item name="borderlessButtonStyle">@android:style/Widget.DeviceDefault.Light.Button.Borderless</item>
+
+        <item name="listSeparatorTextViewStyle">@android:style/Widget.DeviceDefault.Light.TextView.ListSeparator</item>
+
+        <item name="windowTitleStyle">@android:style/WindowTitle.DeviceDefault</item>
+        <item name="windowTitleBackgroundStyle">@android:style/WindowTitleBackground.DeviceDefault</item>
+        <item name="android:windowAnimationStyle">@android:style/Animation.DeviceDefault.Activity</item>
+
+        <!-- Dialog attributes -->
+        <item name="alertDialogStyle">@android:style/AlertDialog.DeviceDefault.Light</item>
+        <item name="dialogTheme">@android:style/Theme.DeviceDefault.Light.Dialog</item>
+        <item name="alertDialogTheme">@android:style/Theme.DeviceDefault.Light.Dialog.Alert</item>
+
+        <!-- Text selection handle attributes -->
+        <item name="textSelectHandleWindowStyle">@android:style/Widget.DeviceDefault.TextSelectHandle</item>
+        <item name="textSuggestionsWindowStyle">@android:style/Widget.DeviceDefault.Light.TextSuggestionsPopupWindow</item>
+
+        <!-- Widget styles -->
+        <item name="absListViewStyle">@android:style/Widget.DeviceDefault.Light.AbsListView</item>
+        <item name="autoCompleteTextViewStyle">@android:style/Widget.DeviceDefault.Light.AutoCompleteTextView</item>
+        <item name="checkboxStyle">@android:style/Widget.DeviceDefault.Light.CompoundButton.CheckBox</item>
+        <item name="dropDownListViewStyle">@android:style/Widget.DeviceDefault.ListView.DropDown</item>
+        <item name="editTextStyle">@android:style/Widget.DeviceDefault.Light.EditText</item>
+        <item name="expandableListViewStyle">@android:style/Widget.DeviceDefault.Light.ExpandableListView</item>
+        <item name="expandableListViewWhiteStyle">@android:style/Widget.DeviceDefault.Light.ExpandableListView.White</item>
+        <item name="galleryStyle">@android:style/Widget.DeviceDefault.Light.Gallery</item>
+        <item name="gestureOverlayViewStyle">@android:style/Widget.DeviceDefault.Light.GestureOverlayView</item>
+        <item name="gridViewStyle">@android:style/Widget.DeviceDefault.Light.GridView</item>
+        <item name="imageButtonStyle">@android:style/Widget.DeviceDefault.Light.ImageButton</item>
+        <item name="imageWellStyle">@android:style/Widget.DeviceDefault.Light.ImageWell</item>
+        <item name="listViewStyle">@android:style/Widget.DeviceDefault.Light.ListView</item>
+        <item name="listViewWhiteStyle">@android:style/Widget.DeviceDefault.Light.ListView.White</item>
+        <item name="popupWindowStyle">@android:style/Widget.DeviceDefault.Light.PopupWindow</item>
+        <item name="progressBarStyle">@android:style/Widget.DeviceDefault.Light.ProgressBar</item>
+        <item name="progressBarStyleHorizontal">@android:style/Widget.DeviceDefault.Light.ProgressBar.Horizontal</item>
+        <item name="progressBarStyleSmall">@android:style/Widget.DeviceDefault.Light.ProgressBar.Small</item>
+        <item name="progressBarStyleSmallTitle">@android:style/Widget.DeviceDefault.Light.ProgressBar.Small.Title</item>
+        <item name="progressBarStyleLarge">@android:style/Widget.DeviceDefault.Light.ProgressBar.Large</item>
+        <item name="progressBarStyleInverse">@android:style/Widget.DeviceDefault.Light.ProgressBar.Inverse</item>
+        <item name="progressBarStyleSmallInverse">@android:style/Widget.DeviceDefault.Light.ProgressBar.Small.Inverse</item>
+        <item name="progressBarStyleLargeInverse">@android:style/Widget.DeviceDefault.Light.ProgressBar.Large.Inverse</item>
+        <item name="seekBarStyle">@android:style/Widget.DeviceDefault.Light.SeekBar</item>
+        <item name="ratingBarStyle">@android:style/Widget.DeviceDefault.Light.RatingBar</item>
+        <item name="ratingBarStyleIndicator">@android:style/Widget.DeviceDefault.Light.RatingBar.Indicator</item>
+        <item name="ratingBarStyleSmall">@android:style/Widget.DeviceDefault.Light.RatingBar.Small</item>
+        <item name="radioButtonStyle">@android:style/Widget.DeviceDefault.Light.CompoundButton.RadioButton</item>
+        <item name="scrollViewStyle">@android:style/Widget.DeviceDefault.Light.ScrollView</item>
+        <item name="horizontalScrollViewStyle">@android:style/Widget.DeviceDefault.Light.HorizontalScrollView</item>
+        <item name="dropDownSpinnerStyle">@android:style/Widget.DeviceDefault.Light.Spinner.DropDown</item>
+        <item name="starStyle">@android:style/Widget.DeviceDefault.Light.CompoundButton.Star</item>
+        <item name="tabWidgetStyle">@android:style/Widget.DeviceDefault.Light.TabWidget</item>
+        <item name="textViewStyle">@android:style/Widget.DeviceDefault.Light.TextView</item>
+        <item name="webTextViewStyle">@android:style/Widget.DeviceDefault.Light.WebTextView</item>
+        <item name="webViewStyle">@android:style/Widget.DeviceDefault.Light.WebView</item>
+        <item name="dropDownItemStyle">@android:style/Widget.DeviceDefault.Light.DropDownItem</item>
+        <item name="spinnerDropDownItemStyle">@android:style/Widget.DeviceDefault.Light.DropDownItem.Spinner</item>
+        <item name="spinnerItemStyle">@android:style/Widget.DeviceDefault.TextView.SpinnerItem</item>
+        <item name="dropDownHintAppearance">@android:style/TextAppearance.DeviceDefault.Widget.DropDownHint</item>
+        <item name="keyboardViewStyle">@android:style/Widget.DeviceDefault.KeyboardView</item>
+        <item name="quickContactBadgeStyleWindowSmall">@android:style/Widget.DeviceDefault.QuickContactBadge.WindowSmall</item>
+        <item name="quickContactBadgeStyleWindowMedium">@android:style/Widget.DeviceDefault.QuickContactBadge.WindowMedium</item>
+        <item name="quickContactBadgeStyleWindowLarge">@android:style/Widget.DeviceDefault.QuickContactBadge.WindowLarge</item>
+        <item name="quickContactBadgeStyleSmallWindowSmall">@android:style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowSmall</item>
+        <item name="quickContactBadgeStyleSmallWindowMedium">@android:style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowMedium</item>
+        <item name="quickContactBadgeStyleSmallWindowLarge">@android:style/Widget.DeviceDefault.QuickContactBadgeSmall.WindowLarge</item>
+        <item name="listPopupWindowStyle">@android:style/Widget.DeviceDefault.Light.ListPopupWindow</item>
+        <item name="popupMenuStyle">@android:style/Widget.DeviceDefault.Light.PopupMenu</item>
+        <item name="stackViewStyle">@android:style/Widget.DeviceDefault.StackView</item>
+
+        <!-- Preference styles -->
+        <item name="preferenceScreenStyle">@android:style/Preference.DeviceDefault.PreferenceScreen</item>
+        <item name="preferenceCategoryStyle">@android:style/Preference.DeviceDefault.Category</item>
+        <item name="preferenceStyle">@android:style/Preference.DeviceDefault</item>
+        <item name="preferenceInformationStyle">@android:style/Preference.DeviceDefault.Information</item>
+        <item name="checkBoxPreferenceStyle">@android:style/Preference.DeviceDefault.CheckBoxPreference</item>
+        <item name="switchPreferenceStyle">@android:style/Preference.DeviceDefault.SwitchPreference</item>
+        <item name="yesNoPreferenceStyle">@android:style/Preference.DeviceDefault.DialogPreference.YesNoPreference</item>
+        <item name="dialogPreferenceStyle">@android:style/Preference.DeviceDefault.DialogPreference</item>
+        <item name="editTextPreferenceStyle">@android:style/Preference.DeviceDefault.DialogPreference.EditTextPreference</item>
+        <item name="ringtonePreferenceStyle">@android:style/Preference.DeviceDefault.RingtonePreference</item>
+
+        <!-- Action bar styles -->
+        <item name="actionDropDownStyle">@android:style/Widget.DeviceDefault.Light.Spinner.DropDown.ActionBar</item>
+        <item name="actionButtonStyle">@android:style/Widget.DeviceDefault.Light.ActionButton</item>
+        <item name="actionOverflowButtonStyle">@android:style/Widget.DeviceDefault.Light.ActionButton.Overflow</item>
+        <item name="actionBarTabStyle">@style/Widget.DeviceDefault.Light.ActionBar.TabView</item>
+        <item name="actionBarTabBarStyle">@style/Widget.DeviceDefault.Light.ActionBar.TabBar</item>
+        <item name="actionBarTabTextStyle">@style/Widget.DeviceDefault.Light.ActionBar.TabText</item>
+        <item name="actionModeStyle">@style/Widget.DeviceDefault.Light.ActionMode</item>
+        <item name="actionModeCloseButtonStyle">@style/Widget.DeviceDefault.Light.ActionButton.CloseMode</item>
+        <item name="actionBarStyle">@android:style/Widget.DeviceDefault.Light.ActionBar</item>
+        <item name="actionModePopupWindowStyle">@android:style/Widget.DeviceDefault.Light.PopupWindow.ActionMode</item>
+
+        <item name="buttonBarStyle">@android:style/DeviceDefault.Light.ButtonBar</item>
+        <item name="segmentedButtonStyle">@android:style/DeviceDefault.Light.SegmentedButton</item>
+
+        <item name="searchDialogTheme">@style/Theme.DeviceDefault.Light.SearchBar</item>
+
+        <!-- NumberPicker attributes and styles-->
+        <item name="numberPickerUpButtonStyle">@style/Widget.DeviceDefault.Light.ImageButton.NumberPickerUpButton</item>
+        <item name="numberPickerDownButtonStyle">@style/Widget.DeviceDefault.Light.ImageButton.NumberPickerDownButton</item>
+        <item name="numberPickerInputTextStyle">@style/Widget.DeviceDefault.Light.EditText.NumberPickerInputText</item>
+        <item name="numberPickerStyle">@style/Widget.DeviceDefault.Light.NumberPicker</item>
+
+        <!-- CalendarView style-->
+        <item name="calendarViewStyle">@style/Widget.DeviceDefault.Light.CalendarView</item>
+
+        <!-- TimePicker style -->
+        <item name="timePickerStyle">@style/Widget.DeviceDefault.Light.TimePicker</item>
+
+        <!-- DatePicker style -->
+        <item name="datePickerStyle">@style/Widget.DeviceDefault.Light.DatePicker</item>
+    </style>
+    <style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Holo.Light.NoActionBar" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" parent="Theme.Holo.Light.NoActionBar.Fullscreen" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Dialog" parent="Theme.Holo.Dialog" >
+        <item name="android:windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault</item>
+        <item name="android:windowAnimationStyle">@android:style/Animation.DeviceDefault.Dialog</item>
+
+        <item name="android:buttonBarStyle">@android:style/DeviceDefault.ButtonBar.AlertDialog</item>
+        <item name="borderlessButtonStyle">@android:style/Widget.DeviceDefault.Button.Borderless.Small</item>
+
+        <item name="textAppearance">@android:style/TextAppearance.DeviceDefault</item>
+        <item name="textAppearanceInverse">@android:style/TextAppearance.DeviceDefault.Inverse</item>
+    </style>
+    <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Holo.Dialog.MinWidth" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Holo.Dialog.NoActionBar" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Holo.Dialog.NoActionBar.MinWidth" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Light.Dialog" parent="Theme.Holo.Light.Dialog" >
+        <item name="android:windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault.Light</item>
+        <item name="android:windowAnimationStyle">@android:style/Animation.DeviceDefault.Dialog</item>
+
+        <item name="android:buttonBarStyle">@android:style/DeviceDefault.Light.ButtonBar.AlertDialog</item>
+        <item name="borderlessButtonStyle">@android:style/Widget.DeviceDefault.Light.Button.Borderless.Small</item>
+
+        <item name="textAppearance">@android:style/TextAppearance.DeviceDefault.Light</item>
+        <item name="textAppearanceInverse">@android:style/TextAppearance.DeviceDefault.Light.Inverse</item>
+    </style>
+    <style name="Theme.DeviceDefault.Light.Dialog.MinWidth" parent="Theme.Holo.Light.Dialog.MinWidth" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar" parent="Theme.Holo.Light.Dialog.NoActionBar" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth" parent="Theme.Holo.Light.Dialog.NoActionBar.MinWidth" >
+
+    </style>
+    <style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Holo.DialogWhenLarge" >
+
+    </style>
+    <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Holo.DialogWhenLarge.NoActionBar" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Light.DialogWhenLarge" parent="Theme.Holo.Light.DialogWhenLarge" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar" parent="Theme.Holo.Light.DialogWhenLarge.NoActionBar" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Panel" parent="Theme.Holo.Panel" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Light.Panel" parent="Theme.Holo.Light.Panel" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Holo.Wallpaper" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Holo.Wallpaper.NoTitleBar" >
+
+    </style>
+    <style name="Theme.DeviceDefault.InputMethod" parent="Theme.Holo.InputMethod" >
+
+    </style>
+    <style name="Theme.DeviceDefault.Light.DarkActionBar" parent="Theme.Holo.Light.DarkActionBar" >
+        <item name="android:actionBarStyle">@android:style/Widget.DeviceDefault.Light.ActionBar.Solid.Inverse</item>
+
+        <item name="actionDropDownStyle">@android:style/Widget.DeviceDefault.Spinner.DropDown.ActionBar</item>
+        <item name="actionButtonStyle">@android:style/Widget.DeviceDefault.ActionButton</item>
+        <item name="actionOverflowButtonStyle">@android:style/Widget.DeviceDefault.ActionButton.Overflow</item>
+        <item name="actionBarTabStyle">@style/Widget.DeviceDefault.Light.ActionBar.TabView.Inverse</item>
+        <item name="actionBarTabBarStyle">@style/Widget.DeviceDefault.Light.ActionBar.TabBar.Inverse</item>
+        <item name="actionBarTabTextStyle">@style/Widget.DeviceDefault.Light.ActionBar.TabText.Inverse</item>
+        <item name="actionModeStyle">@style/Widget.DeviceDefault.Light.ActionMode.Inverse</item>
+        <item name="actionModeCloseButtonStyle">@style/Widget.DeviceDefault.ActionButton.CloseMode</item>
+        <item name="actionModePopupWindowStyle">@android:style/Widget.DeviceDefault.PopupWindow.ActionMode</item>
+
+    </style>
+
+    <style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Holo.Dialog.Alert">
+        <item name="windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault</item>
+    </style>
+    <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.DeviceDefault.Light.Dialog.Alert">
+        <item name="windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault.Light</item>
+    </style>
+    <style name="Theme.DeviceDefault.SearchBar" parent="Theme.DeviceDefault.SearchBar">
+
+    </style>
+    <style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.DeviceDefault.Light.SearchBar">
+
+    </style>
+</resources>
diff --git a/core/res/res/xml-land/password_kbd_qwerty.xml b/core/res/res/xml-land/password_kbd_qwerty.xml
index fd8bd49..988f9ff 100755
--- a/core/res/res/xml-land/password_kbd_qwerty.xml
+++ b/core/res/res/xml-land/password_kbd_qwerty.xml
@@ -20,8 +20,8 @@
 
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
     android:keyWidth="10%p"
-    android:horizontalGap="0px"
-    android:verticalGap="0px"
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
     >
 
diff --git a/core/res/res/xml-land/password_kbd_qwerty_shifted.xml b/core/res/res/xml-land/password_kbd_qwerty_shifted.xml
index 9ff6fd7..4941946d 100755
--- a/core/res/res/xml-land/password_kbd_qwerty_shifted.xml
+++ b/core/res/res/xml-land/password_kbd_qwerty_shifted.xml
@@ -20,8 +20,8 @@
 
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
     android:keyWidth="10%p"
-    android:horizontalGap="0px"
-    android:verticalGap="0px"
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
     >
 
diff --git a/core/res/res/xml-mdpi/password_kbd_qwerty.xml b/core/res/res/xml-mdpi/password_kbd_qwerty.xml
index 82a7c75..265d7dc 100755
--- a/core/res/res/xml-mdpi/password_kbd_qwerty.xml
+++ b/core/res/res/xml-mdpi/password_kbd_qwerty.xml
@@ -20,8 +20,8 @@
 
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
     android:keyWidth="10%p"
-    android:horizontalGap="0px"
-    android:verticalGap="0px"
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
     >
 
diff --git a/core/res/res/xml-mdpi/password_kbd_qwerty_shifted.xml b/core/res/res/xml-mdpi/password_kbd_qwerty_shifted.xml
index 9fff3cc..7379f69 100755
--- a/core/res/res/xml-mdpi/password_kbd_qwerty_shifted.xml
+++ b/core/res/res/xml-mdpi/password_kbd_qwerty_shifted.xml
@@ -20,8 +20,8 @@
 
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
     android:keyWidth="10%p"
-    android:horizontalGap="0px"
-    android:verticalGap="0px"
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
     >
 
diff --git a/core/res/res/xml-xlarge/password_kbd_numeric.xml b/core/res/res/xml-xlarge/password_kbd_numeric.xml
index 0253122..3745672 100755
--- a/core/res/res/xml-xlarge/password_kbd_numeric.xml
+++ b/core/res/res/xml-xlarge/password_kbd_numeric.xml
@@ -19,7 +19,8 @@
 -->
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
     android:keyWidth="33.33%p"
-    android:verticalGap="0px"
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap"
     android:keyHeight="@dimen/password_keyboard_key_height_numeric"
     >
 
diff --git a/core/res/res/xml-xlarge/password_kbd_qwerty.xml b/core/res/res/xml-xlarge/password_kbd_qwerty.xml
index 1009c9a..76b6019 100755
--- a/core/res/res/xml-xlarge/password_kbd_qwerty.xml
+++ b/core/res/res/xml-xlarge/password_kbd_qwerty.xml
@@ -22,8 +22,8 @@
     android:keyWidth="8.272%p"
     keyboardHeight="@dimen/password_keyboard_height"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
-    android:horizontalGap="0px"
-    android:verticalGap="0px">
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap">
 
     <Row android:keyWidth="8.272%p">
         <Key android:keyLabel="Tab"
diff --git a/core/res/res/xml-xlarge/password_kbd_qwerty_shifted.xml b/core/res/res/xml-xlarge/password_kbd_qwerty_shifted.xml
index cbf17c3..35c3142 100755
--- a/core/res/res/xml-xlarge/password_kbd_qwerty_shifted.xml
+++ b/core/res/res/xml-xlarge/password_kbd_qwerty_shifted.xml
@@ -22,8 +22,8 @@
     android:keyWidth="8.272%p"
     keyboardHeight="@dimen/password_keyboard_height"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
-    android:horizontalGap="0px"
-    android:verticalGap="0px">
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap">
 
     <Row android:keyWidth="8.272%p">
         <Key android:keyLabel="Tab"
diff --git a/core/res/res/xml-xlarge/password_kbd_symbols.xml b/core/res/res/xml-xlarge/password_kbd_symbols.xml
index a58a023..106dd6e 100755
--- a/core/res/res/xml-xlarge/password_kbd_symbols.xml
+++ b/core/res/res/xml-xlarge/password_kbd_symbols.xml
@@ -22,8 +22,8 @@
     android:keyWidth="8.272%p"
     keyboardHeight="@dimen/password_keyboard_height"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
-    android:horizontalGap="0px"
-    android:verticalGap="0px">
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap">
 
     <Row android:keyWidth="8.272%p">
         <Key android:keyLabel="Tab"
diff --git a/core/res/res/xml-xlarge/password_kbd_symbols_shift.xml b/core/res/res/xml-xlarge/password_kbd_symbols_shift.xml
index 9d9acf5..1233f78 100755
--- a/core/res/res/xml-xlarge/password_kbd_symbols_shift.xml
+++ b/core/res/res/xml-xlarge/password_kbd_symbols_shift.xml
@@ -20,8 +20,8 @@
 
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
     android:keyWidth="10%p"
-    android:horizontalGap="0px"
-    android:verticalGap="0px"
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha">
 
     <Row android:keyWidth="8.272%p"
diff --git a/core/res/res/xml/password_kbd_extension.xml b/core/res/res/xml/password_kbd_extension.xml
index f3fa57b..e8d61fe 100755
--- a/core/res/res/xml/password_kbd_extension.xml
+++ b/core/res/res/xml/password_kbd_extension.xml
@@ -20,8 +20,8 @@
 
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
     android:keyWidth="10%p"
-    android:horizontalGap="0px"
-    android:verticalGap="0px"
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
     >
 
diff --git a/core/res/res/xml/password_kbd_numeric.xml b/core/res/res/xml/password_kbd_numeric.xml
index 2270b8a..2fd5aa0 100755
--- a/core/res/res/xml/password_kbd_numeric.xml
+++ b/core/res/res/xml/password_kbd_numeric.xml
@@ -19,7 +19,8 @@
 -->
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
     android:keyWidth="33.33%p"
-    android:verticalGap="0px"
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap"
     android:keyHeight="@dimen/password_keyboard_key_height_numeric"
     >
 
diff --git a/core/res/res/xml/password_kbd_popup_template.xml b/core/res/res/xml/password_kbd_popup_template.xml
index 9b853e2..9fcac2c 100644
--- a/core/res/res/xml/password_kbd_popup_template.xml
+++ b/core/res/res/xml/password_kbd_popup_template.xml
@@ -20,8 +20,8 @@
 
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
     android:keyWidth="10%p"
-    android:horizontalGap="0px"
-    android:verticalGap="0px"
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
     >
 </Keyboard>
diff --git a/core/res/res/xml/password_kbd_qwerty.xml b/core/res/res/xml/password_kbd_qwerty.xml
index 0a35040..dfe581e 100755
--- a/core/res/res/xml/password_kbd_qwerty.xml
+++ b/core/res/res/xml/password_kbd_qwerty.xml
@@ -20,8 +20,8 @@
 
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
     android:keyWidth="10%p"
-    android:horizontalGap="0px"
-    android:verticalGap="0px"
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
     >
 
diff --git a/core/res/res/xml/password_kbd_qwerty_shifted.xml b/core/res/res/xml/password_kbd_qwerty_shifted.xml
index 9e9db81..1366c58 100755
--- a/core/res/res/xml/password_kbd_qwerty_shifted.xml
+++ b/core/res/res/xml/password_kbd_qwerty_shifted.xml
@@ -20,8 +20,8 @@
 
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
     android:keyWidth="10%p"
-    android:horizontalGap="0px"
-    android:verticalGap="0px"
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
     >
 
diff --git a/core/res/res/xml/password_kbd_symbols.xml b/core/res/res/xml/password_kbd_symbols.xml
index 9a94930..5876b0d 100755
--- a/core/res/res/xml/password_kbd_symbols.xml
+++ b/core/res/res/xml/password_kbd_symbols.xml
@@ -20,8 +20,8 @@
 
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
     android:keyWidth="10%p"
-    android:horizontalGap="0px"
-    android:verticalGap="0px"
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
     >
 
diff --git a/core/res/res/xml/password_kbd_symbols_shift.xml b/core/res/res/xml/password_kbd_symbols_shift.xml
index a972eb2..ee83544 100755
--- a/core/res/res/xml/password_kbd_symbols_shift.xml
+++ b/core/res/res/xml/password_kbd_symbols_shift.xml
@@ -20,8 +20,8 @@
 
 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
     android:keyWidth="10%p"
-    android:horizontalGap="0px"
-    android:verticalGap="0px"
+    android:horizontalGap="@dimen/password_keyboard_horizontalGap"
+    android:verticalGap="@dimen/password_keyboard_verticalGap"
     android:keyHeight="@dimen/password_keyboard_key_height_alpha"
     >
 
diff --git a/core/tests/bandwidthtests/Android.mk b/core/tests/bandwidthtests/Android.mk
new file mode 100644
index 0000000..3d56141
--- /dev/null
+++ b/core/tests/bandwidthtests/Android.mk
@@ -0,0 +1,30 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := \
+	$(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_PACKAGE_NAME := BandwidthTests
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/tests/bandwidthtests/AndroidManifest.xml b/core/tests/bandwidthtests/AndroidManifest.xml
new file mode 100644
index 0000000..24221bc
--- /dev/null
+++ b/core/tests/bandwidthtests/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.bandwidth.tests" >
+
+    <application >
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="com.android.bandwidthtest.BandwidthTestRunner"
+        android:targetPackage="com.android.bandwidth.tests"
+        android:label="Bandwidth Tests" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.DEVICE_POWER" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+</manifest>
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
new file mode 100644
index 0000000..73c92b0
--- /dev/null
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
@@ -0,0 +1,217 @@
+/*
+ * 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.bandwidthtest;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo.State;
+import android.net.NetworkStats;
+import android.net.TrafficStats;
+import android.net.wifi.WifiManager;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Process;
+import android.os.SystemClock;
+import android.telephony.TelephonyManager;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import com.android.bandwidthtest.util.BandwidthTestUtil;
+import com.android.bandwidthtest.util.ConnectionUtil;
+
+import java.io.File;
+
+/**
+ * Test that downloads files from a test server and reports the bandwidth metrics collected.
+ */
+public class BandwidthTest extends InstrumentationTestCase {
+
+    private static final String LOG_TAG = "BandwidthTest";
+    private final static String PROF_LABEL = "PROF_";
+    private final static String PROC_LABEL = "PROC_";
+    private final static int INSTRUMENTATION_IN_PROGRESS = 2;
+
+    private final static String BASE_DIR =
+            Environment.getExternalStorageDirectory().getAbsolutePath();
+    private final static String TMP_FILENAME = "tmp.dat";
+    // Download 10.486 * 106 bytes (+ headers) from app engine test server.
+    private final int FILE_SIZE = 10485613;
+    private Context mContext;
+    private ConnectionUtil mConnectionUtil;
+    private TelephonyManager mTManager;
+    private int mUid;
+    private String mSsid;
+    private String mTestServer;
+    private String mDeviceId;
+    private BandwidthTestRunner mRunner;
+
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mRunner = (BandwidthTestRunner) getInstrumentation();
+        mSsid = mRunner.mSsid;
+        mTestServer = mRunner.mTestServer;
+        mContext = mRunner.getTargetContext();
+        mConnectionUtil = new ConnectionUtil(mContext);
+        mConnectionUtil.initialize();
+        Log.v(LOG_TAG, "Initialized mConnectionUtil");
+        mUid = Process.myUid();
+        mTManager = (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
+        mDeviceId = mTManager.getDeviceId();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mConnectionUtil.cleanUp();
+        super.tearDown();
+    }
+
+    /**
+     * Ensure that downloading on wifi reports reasonable stats.
+     */
+    @LargeTest
+    public void testWifiDownload() {
+        assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
+        NetworkStats pre_test_stats = fetchDataFromProc(mUid);
+        String ts = Long.toString(System.currentTimeMillis());
+
+        String targetUrl = BandwidthTestUtil.buildDownloadUrl(
+                mTestServer, FILE_SIZE, mDeviceId, ts);
+        TrafficStats.startDataProfiling(mContext);
+        File tmpSaveFile = new File(BASE_DIR + File.separator + TMP_FILENAME);
+        assertTrue(BandwidthTestUtil.DownloadFromUrl(targetUrl, tmpSaveFile));
+        NetworkStats prof_stats = TrafficStats.stopDataProfiling(mContext);
+
+        NetworkStats post_test_stats = fetchDataFromProc(mUid);
+        NetworkStats proc_stats = post_test_stats.subtract(pre_test_stats);
+
+        // Output measurements to instrumentation out, so that it can be compared to that of
+        // the server.
+        Bundle results = new Bundle();
+        results.putString("device_id", mDeviceId);
+        results.putString("timestamp", ts);
+        results.putInt("size", FILE_SIZE);
+        AddStatsToResults(PROF_LABEL, prof_stats, results);
+        AddStatsToResults(PROC_LABEL, proc_stats, results);
+        getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results);
+
+        // Clean up.
+        assertTrue(cleanUpFile(tmpSaveFile));
+    }
+
+    /**
+     * We want to make sure that if we use the Download Manager to download stuff,
+     * accounting still goes to the app making the call and that the numbers still make sense.
+     */
+    @LargeTest
+    public void testWifiDownloadWithDownloadManager() {
+        assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
+        // If we are using the download manager, then the data that is written to /proc/uid_stat/
+        // is accounted against download manager's uid, since it uses pre-ICS API.
+        int downloadManagerUid = mConnectionUtil.downloadManagerUid();
+        assertTrue(downloadManagerUid >= 0);
+        NetworkStats pre_test_stats = fetchDataFromProc(downloadManagerUid);
+        // start profiling
+        TrafficStats.startDataProfiling(mContext);
+        String ts = Long.toString(System.currentTimeMillis());
+        String targetUrl = BandwidthTestUtil.buildDownloadUrl(
+                mTestServer, FILE_SIZE, mDeviceId, ts);
+        Log.v(LOG_TAG, "Download url: " + targetUrl);
+        File tmpSaveFile = new File(BASE_DIR + File.separator + TMP_FILENAME);
+        assertTrue(mConnectionUtil.startDownloadAndWait(targetUrl, 500000));
+        NetworkStats prof_stats = TrafficStats.stopDataProfiling(mContext);
+        NetworkStats post_test_stats = fetchDataFromProc(downloadManagerUid);
+        NetworkStats proc_stats = post_test_stats.subtract(pre_test_stats);
+
+        // Output measurements to instrumentation out, so that it can be compared to that of
+        // the server.
+        Bundle results = new Bundle();
+        results.putString("device_id", mDeviceId);
+        results.putString("timestamp", ts);
+        results.putInt("size", FILE_SIZE);
+        AddStatsToResults(PROF_LABEL, prof_stats, results);
+        AddStatsToResults(PROC_LABEL, proc_stats, results);
+        getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results);
+
+        // Clean up.
+        assertTrue(cleanUpFile(tmpSaveFile));
+    }
+
+    /**
+     * Fetch network data from /proc/uid_stat/uid
+     * @return populated {@link NetworkStats}
+     */
+    public NetworkStats fetchDataFromProc(int uid) {
+        String root_filepath = "/proc/uid_stat/" + uid + "/";
+        File rcv_stat = new File (root_filepath + "tcp_rcv");
+        int rx = BandwidthTestUtil.parseIntValueFromFile(rcv_stat);
+        File snd_stat = new File (root_filepath + "tcp_snd");
+        int tx = BandwidthTestUtil.parseIntValueFromFile(snd_stat);
+        NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
+        stats.addValues(NetworkStats.IFACE_ALL, uid, NetworkStats.TAG_NONE, rx, 0, tx, 0);
+        return stats;
+    }
+
+    /**
+     * Turn on Airplane mode and connect to the wifi
+     * @param ssid of the wifi to connect to
+     * @return true if we successfully connected to a given network.
+     */
+    public boolean setDeviceWifiAndAirplaneMode(String ssid) {
+        mConnectionUtil.setAirplaneMode(mContext, true);
+        assertTrue(mConnectionUtil.connectToWifi(ssid));
+        assertTrue(mConnectionUtil.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+                ConnectionUtil.LONG_TIMEOUT));
+        return mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                ConnectionUtil.LONG_TIMEOUT);
+    }
+
+    /**
+     * Output the {@link NetworkStats} to Instrumentation out.
+     * @param label to attach to this given stats.
+     * @param stats {@link NetworkStats} to add.
+     * @param results {@link Bundle} to be added to.
+     */
+    public void AddStatsToResults(String label, NetworkStats stats, Bundle results){
+        if (results == null || results.isEmpty()) {
+            Log.e(LOG_TAG, "Empty bundle provided.");
+            return;
+        }
+        for (int i = 0; i < stats.size(); ++i) {
+            android.net.NetworkStats.Entry entry = stats.getValues(i, null);
+            results.putInt(label + "uid", entry.uid);
+            results.putString(label + "iface", entry.iface);
+            results.putInt(label + "tag", entry.tag);
+            results.putLong(label + "tx", entry.txBytes);
+            results.putLong(label + "rx", entry.rxBytes);
+        }
+    }
+
+    /**
+     * Remove file if it exists.
+     * @param file {@link File} to delete.
+     * @return true if successfully deleted the file.
+     */
+    private boolean cleanUpFile(File file) {
+        if (file.exists()) {
+            return file.delete();
+        }
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTestRunner.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTestRunner.java
new file mode 100644
index 0000000..290ccee
--- /dev/null
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTestRunner.java
@@ -0,0 +1,38 @@
+/*
+ * 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.bandwidthtest;
+
+import android.os.Bundle;
+import android.test.InstrumentationTestRunner;
+
+public class BandwidthTestRunner extends InstrumentationTestRunner {
+    public String mSsid = "wifi-ssid";
+    public String mTestServer = "http://www.sometestserver.com";
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        String ssidStr= (String) icicle.get("ssid");
+        if (ssidStr != null) {
+            mSsid = ssidStr;
+        }
+        String serverStr = (String) icicle.get("server");
+        if (serverStr != null) {
+            mTestServer = serverStr;
+        }
+    }
+}
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/NetworkState.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/NetworkState.java
new file mode 100644
index 0000000..fae0e76
--- /dev/null
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/NetworkState.java
@@ -0,0 +1,257 @@
+/*
+ * 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.bandwidthtest;
+
+import android.net.NetworkInfo.State;
+import android.util.Log;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Data structure to keep track of the network state transitions.
+ */
+public class NetworkState {
+    /**
+     * Desired direction of state transition.
+     */
+    public enum StateTransitionDirection {
+        TO_DISCONNECTION, TO_CONNECTION, DO_NOTHING
+    }
+    private final String LOG_TAG = "NetworkState";
+    private List<State> mStateDepository;
+    private State mTransitionTarget;
+    private StateTransitionDirection mTransitionDirection;
+    private String mReason = null;         // record mReason of state transition failure
+
+    public NetworkState() {
+        mStateDepository = new ArrayList<State>();
+        mTransitionDirection = StateTransitionDirection.DO_NOTHING;
+        mTransitionTarget = State.UNKNOWN;
+    }
+
+    public NetworkState(State currentState) {
+        mStateDepository = new ArrayList<State>();
+        mStateDepository.add(currentState);
+        mTransitionDirection = StateTransitionDirection.DO_NOTHING;
+        mTransitionTarget = State.UNKNOWN;
+    }
+
+    /**
+     * Reinitialize the network state
+     */
+    public void resetNetworkState() {
+        mStateDepository.clear();
+        mTransitionDirection = StateTransitionDirection.DO_NOTHING;
+        mTransitionTarget = State.UNKNOWN;
+    }
+
+    /**
+     * Set the transition criteria
+     * @param initState initial {@link State}
+     * @param transitionDir explicit {@link StateTransitionDirection}
+     * @param targetState desired {@link State}
+     */
+    public void setStateTransitionCriteria(State initState, StateTransitionDirection transitionDir,
+            State targetState) {
+        if (!mStateDepository.isEmpty()) {
+            mStateDepository.clear();
+        }
+        mStateDepository.add(initState);
+        mTransitionDirection = transitionDir;
+        mTransitionTarget = targetState;
+        Log.v(LOG_TAG, "setStateTransitionCriteria: " + printStates());
+    }
+
+    /**
+     * Record the current state of the network
+     * @param currentState  the current {@link State}
+     */
+    public void recordState(State currentState) {
+        mStateDepository.add(currentState);
+    }
+
+    /**
+     * Verify the state transition
+     * @return true if the requested transition completed successfully.
+     */
+    public boolean validateStateTransition() {
+        Log.v(LOG_TAG, String.format("Print state depository: %s", printStates()));
+        switch (mTransitionDirection) {
+            case DO_NOTHING:
+                Log.v(LOG_TAG, "No direction requested, verifying network states");
+                return validateNetworkStates();
+            case TO_CONNECTION:
+                Log.v(LOG_TAG, "Transition to CONNECTED");
+                return validateNetworkConnection();
+            case TO_DISCONNECTION:
+                Log.v(LOG_TAG, "Transition to DISCONNECTED");
+                return validateNetworkDisconnection();
+            default:
+                Log.e(LOG_TAG, "Invalid transition direction.");
+                return false;
+        }
+    }
+
+    /**
+     * Verify that network states are valid
+     * @return false if any of the states are invalid
+     */
+    private boolean validateNetworkStates() {
+        if (mStateDepository.isEmpty()) {
+            Log.v(LOG_TAG, "no state is recorded");
+            mReason = "no state is recorded.";
+            return false;
+        } else if (mStateDepository.size() > 1) {
+            Log.v(LOG_TAG, "no broadcast is expected, instead broadcast is probably received");
+            mReason = "no broadcast is expected, instead broadcast is probably received";
+            return false;
+        } else if (mStateDepository.get(0) != mTransitionTarget) {
+            Log.v(LOG_TAG, String.format("%s is expected, but it is %s",
+                    mTransitionTarget.toString(),
+                    mStateDepository.get(0).toString()));
+            mReason = String.format("%s is expected, but it is %s",
+                    mTransitionTarget.toString(),
+                    mStateDepository.get(0).toString());
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Verify the network state to disconnection
+     * @return false if any of the state transitions were not valid
+     */
+    private boolean validateNetworkDisconnection() {
+        // Transition from CONNECTED -> DISCONNECTED: CONNECTED->DISCONNECTING->DISCONNECTED
+        StringBuffer str = new StringBuffer ("States: ");
+        str.append(printStates());
+        if (mStateDepository.get(0) != State.CONNECTED) {
+            str.append(String.format(" Initial state should be CONNECTED, but it is %s.",
+                    mStateDepository.get(0)));
+            mReason = str.toString();
+            return false;
+        }
+        State lastState = mStateDepository.get(mStateDepository.size() - 1);
+        if ( lastState != mTransitionTarget) {
+            str.append(String.format(" Last state should be DISCONNECTED, but it is %s",
+                    lastState));
+            mReason = str.toString();
+            return false;
+        }
+        for (int i = 1; i < mStateDepository.size() - 1; i++) {
+            State preState = mStateDepository.get(i-1);
+            State curState = mStateDepository.get(i);
+            if ((preState == State.CONNECTED) && ((curState == State.DISCONNECTING) ||
+                    (curState == State.DISCONNECTED))) {
+                continue;
+            } else if ((preState == State.DISCONNECTING) && (curState == State.DISCONNECTED)) {
+                continue;
+            } else if ((preState == State.DISCONNECTED) && (curState == State.DISCONNECTED)) {
+                continue;
+            } else {
+                str.append(String.format(" Transition state from %s to %s is not valid",
+                        preState.toString(), curState.toString()));
+                mReason = str.toString();
+                return false;
+            }
+        }
+        mReason = str.toString();
+        return true;
+    }
+
+    /**
+     * Verify the network state to connection
+     * @return false if any of the state transitions were not valid
+     */
+    private boolean validateNetworkConnection() {
+        StringBuffer str = new StringBuffer("States ");
+        str.append(printStates());
+        if (mStateDepository.get(0) != State.DISCONNECTED) {
+            str.append(String.format(" Initial state should be DISCONNECTED, but it is %s.",
+                    mStateDepository.get(0)));
+            mReason = str.toString();
+            return false;
+        }
+        State lastState = mStateDepository.get(mStateDepository.size() - 1);
+        if ( lastState != mTransitionTarget) {
+            str.append(String.format(" Last state should be %s, but it is %s", mTransitionTarget,
+                    lastState));
+            mReason = str.toString();
+            return false;
+        }
+        for (int i = 1; i < mStateDepository.size(); i++) {
+            State preState = mStateDepository.get(i-1);
+            State curState = mStateDepository.get(i);
+            if ((preState == State.DISCONNECTED) && ((curState == State.CONNECTING) ||
+                    (curState == State.CONNECTED) || (curState == State.DISCONNECTED))) {
+                continue;
+            } else if ((preState == State.CONNECTING) && (curState == State.CONNECTED)) {
+                continue;
+            } else if ((preState == State.CONNECTED) && (curState == State.CONNECTED)) {
+                continue;
+            } else {
+                str.append(String.format(" Transition state from %s to %s is not valid.",
+                        preState.toString(), curState.toString()));
+                mReason = str.toString();
+                return false;
+            }
+        }
+        mReason = str.toString();
+        return true;
+    }
+
+    /**
+     * Fetch the different network state transitions
+     * @return {@link List} of {@link State}
+     */
+    public List<State> getTransitionStates() {
+        return mStateDepository;
+    }
+
+    /**
+     * Fetch the reason for network state transition failure
+     * @return the {@link String} for the failure
+     */
+    public String getFailureReason() {
+        return mReason;
+    }
+
+    /**
+     * Print the network state
+     * @return {@link String} representation of the network state
+     */
+    public String printStates() {
+        StringBuilder stateBuilder = new StringBuilder();
+        for (int i = 0; i < mStateDepository.size(); i++) {
+            stateBuilder.append(" ").append(mStateDepository.get(i).toString()).append("->");
+        }
+        return stateBuilder.toString();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("mTransitionDirection: ").append(mTransitionDirection.toString()).
+        append("; ").append("states:").
+        append(printStates()).append("; ");
+        return builder.toString();
+    }
+}
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/BandwidthTestUtil.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/BandwidthTestUtil.java
new file mode 100644
index 0000000..d850169
--- /dev/null
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/BandwidthTestUtil.java
@@ -0,0 +1,109 @@
+/*
+ * 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.bandwidthtest.util;
+
+import android.util.Log;
+
+import org.apache.http.util.ByteArrayBuffer;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLConnection;
+
+public class BandwidthTestUtil {
+    private static final String LOG_TAG = "BandwidthTestUtil";
+    /**
+     * Parses the first line in a file if exists.
+     *
+     * @param file {@link File} the input
+     * @return the integer value of the first line of the file.
+     */
+    public static int parseIntValueFromFile(File file) {
+        int value = 0;
+        if (file.exists()) {
+            try {
+                FileInputStream fstream = new FileInputStream(file);
+                DataInputStream in = new DataInputStream(fstream);
+                BufferedReader br = new BufferedReader(new InputStreamReader(in));
+                String strLine = br.readLine();
+                if (strLine != null) {
+                    value = Integer.parseInt(strLine);
+                }
+                // Close the input stream
+                in.close();
+            } catch (Exception e) {
+                System.err.println("Error: " + e.getMessage());
+            }
+        }
+        return value;
+    }
+
+    /**
+     * Creates the Download string for the test server.
+     *
+     * @param server url of the test server
+     * @param size in bytes of the file to download
+     * @param deviceId the device id that is downloading
+     * @param timestamp
+     * @return download url
+     */
+    public static String buildDownloadUrl(String server, int size, String deviceId,
+            String timestamp) {
+        String downloadUrl = server + "/download?size=" + size + "&device_id=" + deviceId +
+                "&timestamp=" + timestamp;
+        return downloadUrl;
+    }
+
+    /**
+     * Download a given file from a target url to a given destination file.
+     * @param targetUrl the url to download
+     * @param file the {@link File} location where to save to
+     * @return true if it succeeded.
+     */
+    public static boolean DownloadFromUrl(String targetUrl, File file) {
+        try {
+            URL url = new URL(targetUrl);
+            Log.d(LOG_TAG, "Download begining");
+            Log.d(LOG_TAG, "Download url:" + url);
+            Log.d(LOG_TAG, "Downloaded file name:" + file.getAbsolutePath());
+            URLConnection ucon = url.openConnection();
+            InputStream is = ucon.getInputStream();
+            BufferedInputStream bis = new BufferedInputStream(is);
+            ByteArrayBuffer baf = new ByteArrayBuffer(50);
+            int current = 0;
+            while ((current = bis.read()) != -1) {
+                baf.append((byte) current);
+            }
+            FileOutputStream fos = new FileOutputStream(file);
+            fos.write(baf.toByteArray());
+            fos.close();
+        } catch (IOException e) {
+            Log.d(LOG_TAG, "Failed to download file with error: " + e);
+            return false;
+        }
+        return true;
+    }
+
+}
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
new file mode 100644
index 0000000..d663aad
--- /dev/null
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
@@ -0,0 +1,684 @@
+/*
+ * 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.bandwidthtest.util;
+
+import android.app.DownloadManager;
+import android.app.DownloadManager.Query;
+import android.app.DownloadManager.Request;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.Cursor;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.State;
+import android.net.Uri;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.bandwidthtest.NetworkState;
+import com.android.bandwidthtest.NetworkState.StateTransitionDirection;
+import com.android.internal.util.AsyncChannel;
+
+import java.util.List;
+
+/*
+ * Utility class used to set the connectivity of the device and to download files.
+ */
+public class ConnectionUtil {
+    private static final String LOG_TAG = "ConnectionUtil";
+    private static final String DOWNLOAD_MANAGER_PKG_NAME = "com.android.providers.downloads";
+    private static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; // 10 seconds
+    private static final int WIFI_SCAN_TIMEOUT = 50 * 1000;
+    public static final int SHORT_TIMEOUT = 5 * 1000;
+    public static final int LONG_TIMEOUT = 10 * 1000;
+    private ConnectivityReceiver mConnectivityReceiver = null;
+    private WifiReceiver mWifiReceiver = null;
+    private DownloadReceiver mDownloadReceiver = null;
+    private DownloadManager mDownloadManager;
+    private NetworkInfo mNetworkInfo;
+    private NetworkInfo mOtherNetworkInfo;
+    private boolean mScanResultIsAvailable = false;
+    private ConnectivityManager mCM;
+    private Object mWifiMonitor = new Object();
+    private Object mConnectivityMonitor = new Object();
+    private Object mDownloadMonitor = new Object();
+    private int mWifiState;
+    private NetworkInfo mWifiNetworkInfo;
+    private WifiManager mWifiManager;
+    private Context mContext;
+    // Verify connectivity state
+    private static final int NUM_NETWORK_TYPES = ConnectivityManager.MAX_NETWORK_TYPE + 1;
+    private NetworkState[] mConnectivityState = new NetworkState[NUM_NETWORK_TYPES];
+
+    public ConnectionUtil(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Initialize the class. Needs to be called before any other methods in {@link ConnectionUtil}
+     *
+     * @throws Exception
+     */
+    public void initialize() throws Exception {
+        // Register a connectivity receiver for CONNECTIVITY_ACTION
+        mConnectivityReceiver = new ConnectivityReceiver();
+        mContext.registerReceiver(mConnectivityReceiver,
+                new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
+
+        // Register a download receiver for ACTION_DOWNLOAD_COMPLETE
+        mDownloadReceiver = new DownloadReceiver();
+        mContext.registerReceiver(mDownloadReceiver,
+                new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
+
+        // Register a wifi receiver
+        mWifiReceiver = new WifiReceiver();
+        IntentFilter mIntentFilter = new IntentFilter();
+        mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+        mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
+        mIntentFilter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
+        mContext.registerReceiver(mWifiReceiver, mIntentFilter);
+
+        // Get an instance of ConnectivityManager
+        mCM = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+
+        // Get an instance of WifiManager
+        mWifiManager =(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
+        mWifiManager.asyncConnect(mContext, new WifiServiceHandler());
+
+        mDownloadManager = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE);
+
+        initializeNetworkStates();
+
+        mWifiManager.setWifiEnabled(true);
+
+        Log.v(LOG_TAG, "Clear Wifi before we start the test.");
+        sleep(SHORT_TIMEOUT);
+        removeConfiguredNetworksAndDisableWifi();
+    }
+
+
+    /**
+     * A wrapper of a broadcast receiver which provides network connectivity information
+     * for all kinds of network: wifi, mobile, etc.
+     */
+    private class ConnectivityReceiver extends BroadcastReceiver {
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (isInitialStickyBroadcast()) {
+                Log.d(LOG_TAG, "This is a sticky broadcast don't do anything.");
+                return;
+            }
+            Log.v(LOG_TAG, "ConnectivityReceiver: onReceive() is called with " + intent);
+            String action = intent.getAction();
+            if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+                Log.v("ConnectivityReceiver", "onReceive() called with " + intent);
+                return;
+            }
+            if (intent.hasExtra(ConnectivityManager.EXTRA_NETWORK_INFO)) {
+                mNetworkInfo = (NetworkInfo)
+                        intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
+            }
+
+            if (intent.hasExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO)) {
+                mOtherNetworkInfo = (NetworkInfo)
+                        intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
+            }
+
+            Log.v(LOG_TAG, "mNetworkInfo: " + mNetworkInfo.toString());
+            recordNetworkState(mNetworkInfo.getType(), mNetworkInfo.getState());
+            if (mOtherNetworkInfo != null) {
+                Log.v(LOG_TAG, "mOtherNetworkInfo: " + mOtherNetworkInfo.toString());
+                recordNetworkState(mOtherNetworkInfo.getType(), mOtherNetworkInfo.getState());
+            }
+            notifyNetworkConnectivityChange();
+        }
+    }
+
+    /**
+     * A wrapper of a broadcast receiver which provides wifi information.
+     */
+    private class WifiReceiver extends BroadcastReceiver {
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            Log.v("WifiReceiver", "onReceive() is calleld with " + intent);
+            if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+                Log.v(LOG_TAG, "Scan results are available");
+                notifyScanResult();
+            } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+                mWifiNetworkInfo =
+                        (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+                Log.v(LOG_TAG, "mWifiNetworkInfo: " + mWifiNetworkInfo.toString());
+                if (mWifiNetworkInfo.getState() == State.CONNECTED) {
+                    intent.getStringExtra(WifiManager.EXTRA_BSSID);
+                }
+                notifyWifiState();
+            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+                mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+                        WifiManager.WIFI_STATE_UNKNOWN);
+                notifyWifiState();
+            } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
+                notifyWifiAPState();
+            } else {
+                return;
+            }
+        }
+    }
+
+    /**
+     * A wrapper of a broadcast receiver which provides download manager information.
+     */
+    private class DownloadReceiver extends BroadcastReceiver {
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            Log.v("DownloadReceiver", "onReceive() is called with " + intent);
+            // Download complete
+            if (action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
+                notifiyDownloadState();
+            }
+        }
+    }
+
+    private class WifiServiceHandler extends Handler {
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+                        // AsyncChannel in msg.obj
+                    } else {
+                        Log.v(LOG_TAG, "Failed to establish AsyncChannel connection");
+                    }
+                    break;
+                default:
+                    // Ignore
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Initialize all the network states.
+     */
+    public void initializeNetworkStates() {
+        // For each network type, initialize network states to UNKNOWN, and no verification
+        // flag is set.
+        for (int networkType = NUM_NETWORK_TYPES - 1; networkType >= 0; networkType--) {
+            mConnectivityState[networkType] =  new NetworkState();
+            Log.v(LOG_TAG, "Initialize network state for " + networkType + ": " +
+                    mConnectivityState[networkType].toString());
+        }
+    }
+
+    public void recordNetworkState(int networkType, State networkState) {
+        // deposit a network state
+        Log.v(LOG_TAG, "record network state for network " +  networkType +
+                ", state is " + networkState);
+        mConnectivityState[networkType].recordState(networkState);
+    }
+
+   /**
+    * Set the state transition criteria
+    *
+    * @param networkType
+    * @param initState
+    * @param transitionDir
+    * @param targetState
+    */
+    public void setStateTransitionCriteria(int networkType, State initState,
+            StateTransitionDirection transitionDir, State targetState) {
+        mConnectivityState[networkType].setStateTransitionCriteria(
+                initState, transitionDir, targetState);
+    }
+
+    /**
+     * Validate the states recorded.
+     * @param networkType
+     * @return
+     */
+    public boolean validateNetworkStates(int networkType) {
+        Log.v(LOG_TAG, "validate network state for " + networkType + ": ");
+        return mConnectivityState[networkType].validateStateTransition();
+    }
+
+    /**
+     * Fetch the failure reason for the transition.
+     * @param networkType
+     * @return result from network state validation
+     */
+    public String getTransitionFailureReason(int networkType) {
+        Log.v(LOG_TAG, "get network state transition failure reason for " + networkType + ": " +
+                mConnectivityState[networkType].toString());
+        return mConnectivityState[networkType].getFailureReason();
+    }
+
+    /**
+     * Send a notification via the mConnectivityMonitor when the network connectivity changes.
+     */
+    private void notifyNetworkConnectivityChange() {
+        synchronized(mConnectivityMonitor) {
+            Log.v(LOG_TAG, "notify network connectivity changed");
+            mConnectivityMonitor.notifyAll();
+        }
+    }
+
+    /**
+     * Send a notification when a scan for the wifi network is done.
+     */
+    private void notifyScanResult() {
+        synchronized (this) {
+            Log.v(LOG_TAG, "notify that scan results are available");
+            this.notify();
+        }
+    }
+
+    /**
+     * Send a notification via the mWifiMonitor when the wifi state changes.
+     */
+    private void notifyWifiState() {
+        synchronized (mWifiMonitor) {
+            Log.v(LOG_TAG, "notify wifi state changed.");
+            mWifiMonitor.notify();
+        }
+    }
+
+    /**
+     * Send a notification via the mDownloadMonitor when a download is complete.
+     */
+    private void notifiyDownloadState() {
+        synchronized (mDownloadMonitor) {
+            Log.v(LOG_TAG, "notifiy download manager state changed.");
+            mDownloadMonitor.notify();
+        }
+    }
+
+    /**
+     * Send a notification when the wifi ap state changes.
+     */
+    private void notifyWifiAPState() {
+        synchronized (this) {
+            Log.v(LOG_TAG, "notify wifi AP state changed.");
+            this.notify();
+        }
+    }
+
+    /**
+     * Start a download on a given url and wait for completion.
+     *
+     * @param targetUrl the target to download.x
+     * @param timeout to wait for download to finish
+     * @return true if we successfully downloaded the requestedUrl, false otherwise.
+     */
+    public boolean startDownloadAndWait(String targetUrl, long timeout) {
+        if (targetUrl.length() == 0 || targetUrl == null) {
+            Log.v(LOG_TAG, "Empty or Null target url requested to DownloadManager");
+            return true;
+        }
+        Request request = new Request(Uri.parse(targetUrl));
+        long enqueue = mDownloadManager.enqueue(request);
+        Log.v(LOG_TAG, "Sending download request of " + targetUrl + " to DownloadManager");
+        long startTime = System.currentTimeMillis();
+        while (true) {
+            if ((System.currentTimeMillis() - startTime) > timeout) {
+                Log.v(LOG_TAG, "startDownloadAndWait timed out, failed to fetch " + targetUrl +
+                        " within " + timeout);
+                return downloadSuccessful(enqueue);
+            }
+            Log.v(LOG_TAG, "Waiting for the download to finish " + targetUrl);
+            synchronized (mDownloadMonitor) {
+                try {
+                    mDownloadMonitor.wait(SHORT_TIMEOUT);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+                if (!downloadSuccessful(enqueue)) {
+                    continue;
+                }
+                return true;
+            }
+        }
+    }
+
+    /**
+     * Fetch the Download Manager's UID.
+     * @return the Download Manager's UID
+     */
+    public int downloadManagerUid() {
+        try {
+            PackageManager pm = mContext.getPackageManager();
+            ApplicationInfo appInfo = pm.getApplicationInfo(DOWNLOAD_MANAGER_PKG_NAME,
+                    PackageManager.GET_META_DATA);
+            return appInfo.uid;
+        } catch (NameNotFoundException e) {
+            Log.d(LOG_TAG, "Did not find the package for the download service.");
+            return -1;
+        }
+    }
+
+    /**
+     * Determines if a given download was successful by querying the DownloadManager.
+     *
+     * @param enqueue the id used to identify/query the DownloadManager with.
+     * @return true if download was successful, false otherwise.
+     */
+    private boolean downloadSuccessful(long enqueue) {
+        Query query = new Query();
+        query.setFilterById(enqueue);
+        Cursor c = mDownloadManager.query(query);
+        if (c.moveToFirst()) {
+            int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
+            if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
+                Log.v(LOG_TAG, "Successfully downloaded file!");
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Wait for network connectivity state.
+     * @param networkType the network to check for
+     * @param expectedState the desired state
+     * @param timeout in milliseconds
+     * @return true if the network connectivity state matched what was expected
+     */
+    public boolean waitForNetworkState(int networkType, State expectedState, long timeout) {
+        long startTime = System.currentTimeMillis();
+        while (true) {
+            if ((System.currentTimeMillis() - startTime) > timeout) {
+                Log.v(LOG_TAG, "waitForNetworkState time out, the state of network type " + networkType +
+                        " is: " + mCM.getNetworkInfo(networkType).getState());
+                if (mCM.getNetworkInfo(networkType).getState() != expectedState) {
+                    return false;
+                } else {
+                    // the broadcast has been sent out. the state has been changed.
+                    Log.v(LOG_TAG, "networktype: " + networkType + " state: " +
+                            mCM.getNetworkInfo(networkType));
+                    return true;
+                }
+            }
+            Log.v(LOG_TAG, "Wait for the connectivity state for network: " + networkType +
+                    " to be " + expectedState.toString());
+            synchronized (mConnectivityMonitor) {
+                try {
+                    mConnectivityMonitor.wait(SHORT_TIMEOUT);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+                if ((mNetworkInfo.getType() != networkType) ||
+                        (mNetworkInfo.getState() != expectedState)) {
+                    Log.v(LOG_TAG, "network state for " + mNetworkInfo.getType() +
+                            "is: " + mNetworkInfo.getState());
+                    continue;
+                }
+                return true;
+            }
+        }
+    }
+
+    /**
+     * Wait for a given wifi state to occur within a given timeout.
+     * @param expectedState the expected wifi state.
+     * @param timeout for the state to be set in milliseconds.
+     * @return true if the state was achieved within the timeout, false otherwise.
+     */
+    public boolean waitForWifiState(int expectedState, long timeout) {
+        // Wait for Wifi state: WIFI_STATE_DISABLED, WIFI_STATE_DISABLING, WIFI_STATE_ENABLED,
+        //                      WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN
+        long startTime = System.currentTimeMillis();
+        while (true) {
+            if ((System.currentTimeMillis() - startTime) > timeout) {
+                if (mWifiState != expectedState) {
+                    return false;
+                } else {
+                    return true;
+                }
+            }
+            Log.v(LOG_TAG, "Wait for wifi state to be: " + expectedState);
+            synchronized (mWifiMonitor) {
+                try {
+                    mWifiMonitor.wait(SHORT_TIMEOUT);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+                if (mWifiState != expectedState) {
+                    Log.v(LOG_TAG, "Wifi state is: " + mWifiState);
+                    continue;
+                }
+                return true;
+            }
+        }
+    }
+
+    /**
+     * Convenience method to determine if we are connected to a mobile network.
+     * @return true if connected to a mobile network, false otherwise.
+     */
+    public boolean isConnectedToMobile() {
+        return (mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE);
+    }
+
+    /**
+     * Convenience method to determine if we are connected to wifi.
+     * @return true if connected to wifi, false otherwise.
+     */
+    public boolean isConnectedToWifi() {
+        return (mNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI);
+    }
+
+
+    /**
+     * Associate the device to given SSID
+     * If the device is already associated with a WiFi, disconnect and forget it,
+     * We don't verify whether the connection is successful or not, leave this to the test
+     */
+    public boolean connectToWifi(String knownSSID) {
+        WifiConfiguration config = new WifiConfiguration();
+        config.SSID = knownSSID;
+        config.allowedKeyManagement.set(KeyMgmt.NONE);
+        return connectToWifiWithConfiguration(config);
+    }
+
+    /**
+     * Connect to Wi-Fi with the given configuration.
+     * @param config
+     * @return true if we ar connected to a given
+     */
+    public boolean connectToWifiWithConfiguration(WifiConfiguration config) {
+        //  The SSID in the configuration is a pure string, need to convert it to a quoted string.
+        String ssid = config.SSID;
+        config.SSID = convertToQuotedString(ssid);
+
+        // If wifi is not enabled, enable it
+        if (!mWifiManager.isWifiEnabled()) {
+            Log.v(LOG_TAG, "Wifi is not enabled, enable it");
+            mWifiManager.setWifiEnabled(true);
+            // wait for the wifi state change before start scanning.
+            if (!waitForWifiState(WifiManager.WIFI_STATE_ENABLED, 2 * SHORT_TIMEOUT)) {
+                Log.v(LOG_TAG, "Wait for WIFI_STATE_ENABLED failed");
+                return false;
+            }
+        }
+
+        boolean foundApInScanResults = false;
+        for (int retry = 0; retry < 5; retry++) {
+            List<ScanResult> netList = mWifiManager.getScanResults();
+            if (netList != null) {
+                Log.v(LOG_TAG, "size of scan result list: " + netList.size());
+                for (int i = 0; i < netList.size(); i++) {
+                    ScanResult sr= netList.get(i);
+                    if (sr.SSID.equals(ssid)) {
+                        Log.v(LOG_TAG, "Found " + ssid + " in the scan result list.");
+                        Log.v(LOG_TAG, "Retry: " + retry);
+                        foundApInScanResults = true;
+                        mWifiManager.connectNetwork(config);
+                        break;
+                    }
+                }
+            }
+            if (foundApInScanResults) {
+                return true;
+            } else {
+                // Start an active scan
+                mWifiManager.startScanActive();
+                mScanResultIsAvailable = false;
+                long startTime = System.currentTimeMillis();
+                while (!mScanResultIsAvailable) {
+                    if ((System.currentTimeMillis() - startTime) > WIFI_SCAN_TIMEOUT) {
+                        Log.v(LOG_TAG, "wait for scan results timeout");
+                        return false;
+                    }
+                    // wait for the scan results to be available
+                    synchronized (this) {
+                        // wait for the scan result to be available
+                        try {
+                            this.wait(WAIT_FOR_SCAN_RESULT);
+                        } catch (InterruptedException e) {
+                            e.printStackTrace();
+                        }
+                        if ((mWifiManager.getScanResults() == null) ||
+                                (mWifiManager.getScanResults().size() <= 0)) {
+                            continue;
+                        }
+                        mScanResultIsAvailable = true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    /*
+     * Disconnect from the current AP and remove configured networks.
+     */
+    public boolean disconnectAP() {
+        // remove saved networks
+        List<WifiConfiguration> wifiConfigList = mWifiManager.getConfiguredNetworks();
+        Log.v(LOG_TAG, "size of wifiConfigList: " + wifiConfigList.size());
+        for (WifiConfiguration wifiConfig: wifiConfigList) {
+            Log.v(LOG_TAG, "Remove wifi configuration: " + wifiConfig.networkId);
+            int netId = wifiConfig.networkId;
+            mWifiManager.forgetNetwork(netId);
+        }
+        return true;
+    }
+
+    /**
+     * Enable Wifi
+     * @return true if Wifi is enabled successfully
+     */
+    public boolean enableWifi() {
+        return mWifiManager.setWifiEnabled(true);
+    }
+
+    /**
+     * Disable Wifi
+     * @return true if Wifi is disabled successfully
+     */
+    public boolean disableWifi() {
+        return mWifiManager.setWifiEnabled(false);
+    }
+
+    /**
+     * Remove configured networks and disable wifi
+     */
+    public boolean removeConfiguredNetworksAndDisableWifi() {
+        if (!disconnectAP()) {
+            return false;
+        }
+        sleep(SHORT_TIMEOUT);
+        if (!mWifiManager.setWifiEnabled(false)) {
+            return false;
+        }
+        sleep(SHORT_TIMEOUT);
+        return true;
+    }
+
+    /**
+     * Make the current thread sleep.
+     * @param sleeptime the time to sleep in milliseconds
+     */
+    private void sleep(long sleeptime) {
+        try {
+            Thread.sleep(sleeptime);
+        } catch (InterruptedException e) {}
+    }
+
+    /**
+     * Set airplane mode on device, caller is responsible to ensuring correct state.
+     * @param context {@link Context}
+     * @param enableAM to enable or disable airplane mode.
+     */
+    public void setAirplaneMode(Context context, boolean enableAM) {
+        //set the airplane mode
+        Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
+                enableAM ? 1 : 0);
+        // Post the intent
+        Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+        intent.putExtra("state", enableAM);
+        context.sendBroadcast(intent);
+    }
+
+    /**
+     * Add quotes around the string.
+     * @param string to convert
+     * @return string with quotes around it
+     */
+    protected static String convertToQuotedString(String string) {
+        return "\"" + string + "\"";
+    }
+
+    public void cleanUp() {
+        // Unregister receivers if defined.
+        if (mConnectivityReceiver != null) {
+            mContext.unregisterReceiver(mConnectivityReceiver);
+        }
+        if (mWifiReceiver != null) {
+            mContext.unregisterReceiver(mWifiReceiver);
+        }
+        if (mDownloadReceiver != null) {
+            mContext.unregisterReceiver(mDownloadReceiver);
+        }
+        Log.v(LOG_TAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
+    }
+}
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/animation/EventsTest.java b/core/tests/coretests/src/android/animation/EventsTest.java
index f970ffc..6ea2845 100644
--- a/core/tests/coretests/src/android/animation/EventsTest.java
+++ b/core/tests/coretests/src/android/animation/EventsTest.java
@@ -21,6 +21,8 @@
 import android.test.suitebuilder.annotation.MediumTest;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import java.util.concurrent.TimeUnit;
+
 /**
  * Tests for the various lifecycle events of Animators. This abstract class is subclassed by
  * concrete implementations that provide the actual Animator objects being tested. All of the
@@ -40,7 +42,10 @@
     private static final int ANIM_DELAY = 100;
     private static final int ANIM_MID_DURATION = ANIM_DURATION / 2;
     private static final int ANIM_MID_DELAY = ANIM_DELAY / 2;
+    private static final int FUTURE_RELEASE_DELAY = 50;
+    private static final int TIMEOUT = ANIM_DURATION + ANIM_DELAY + FUTURE_RELEASE_DELAY;
 
+    private boolean mStarted;  // tracks whether we've received the onAnimationStart() callback
     private boolean mRunning;  // tracks whether we've started the animator
     private boolean mCanceled; // trackes whether we've canceled the animator
     private Animator.AnimatorListener mFutureListener; // mechanism for delaying the end of the test
@@ -51,17 +56,44 @@
                                   // setup() method prior to calling the superclass setup()
 
     /**
-     * Cancels the given animator. Used to delay cancelation until some later time (after the
+     * Cancels the given animator. Used to delay cancellation until some later time (after the
      * animator has started playing).
      */
     static class Canceler implements Runnable {
         Animator mAnim;
-        public Canceler(Animator anim) {
+        FutureWaiter mFuture;
+        public Canceler(Animator anim, FutureWaiter future) {
             mAnim = anim;
+            mFuture = future;
         }
         @Override
         public void run() {
-            mAnim.cancel();
+            try {
+                mAnim.cancel();
+            } catch (junit.framework.AssertionFailedError e) {
+                mFuture.setException(new RuntimeException(e));
+            }
+        }
+    };
+
+    /**
+     * Ends the given animator. Used to delay ending until some later time (after the
+     * animator has started playing).
+     */
+    static class Ender implements Runnable {
+        Animator mAnim;
+        FutureWaiter mFuture;
+        public Ender(Animator anim, FutureWaiter future) {
+            mAnim = anim;
+            mFuture = future;
+        }
+        @Override
+        public void run() {
+            try {
+                mAnim.end();
+            } catch (junit.framework.AssertionFailedError e) {
+                mFuture.setException(new RuntimeException(e));
+            }
         }
     };
 
@@ -76,6 +108,23 @@
         public FutureReleaseListener(FutureWaiter future) {
             mFuture = future;
         }
+
+        /**
+         * Variant constructor that auto-releases the FutureWaiter after the specified timeout.
+         * @param future
+         * @param timeout
+         */
+        public FutureReleaseListener(FutureWaiter future, long timeout) {
+            mFuture = future;
+            Handler handler = new Handler();
+            handler.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    mFuture.release();
+                }
+            }, timeout);
+        }
+
         @Override
         public void onAnimationEnd(Animator animation) {
             Handler handler = new Handler();
@@ -84,7 +133,7 @@
                 public void run() {
                     mFuture.release();
                 }
-            }, ANIM_MID_DURATION);
+            }, FUTURE_RELEASE_DELAY);
         }
     };
 
@@ -92,7 +141,6 @@
         super(BasicAnimatorActivity.class);
     }
 
-
     /**
      * Sets up the fields used by each test. Subclasses must override this method to create
      * the protected mAnimator object used in all tests. Overrides must create that animator
@@ -107,11 +155,20 @@
         // are embedded in the listener callbacks that it implements.
         mListener = new AnimatorListenerAdapter() {
             @Override
+            public void onAnimationStart(Animator animation) {
+                // This should only be called on an animation that has not yet been started
+                assertFalse(mStarted);
+                assertTrue(mRunning);
+                mStarted = true;
+            }
+
+            @Override
             public void onAnimationCancel(Animator animation) {
                 // This should only be called on an animation that has been started and not
                 // yet canceled or ended
                 assertFalse(mCanceled);
                 assertTrue(mRunning);
+                assertTrue(mStarted);
                 mCanceled = true;
             }
 
@@ -120,7 +177,9 @@
                 // This should only be called on an animation that has been started and not
                 // yet ended
                 assertTrue(mRunning);
+                assertTrue(mStarted);
                 mRunning = false;
+                mStarted = false;
                 super.onAnimationEnd(animation);
             }
         };
@@ -132,6 +191,7 @@
 
         mRunning = false;
         mCanceled = false;
+        mStarted = false;
     }
 
     /**
@@ -144,26 +204,104 @@
     }
 
     /**
+     * Verify that calling end on an unstarted animator does nothing.
+     */
+    @UiThreadTest
+    @SmallTest
+    public void testEnd() throws Exception {
+        mAnimator.end();
+    }
+
+    /**
      * Verify that calling cancel on a started animator does the right thing.
      */
     @UiThreadTest
     @SmallTest
     public void testStartCancel() throws Exception {
-        mRunning = true;
-        mAnimator.start();
-        mAnimator.cancel();
+        mFutureListener = new FutureReleaseListener(mFuture);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    mRunning = true;
+                    mAnimator.start();
+                    mAnimator.cancel();
+                    mFuture.release();
+                } catch (junit.framework.AssertionFailedError e) {
+                    mFuture.setException(new RuntimeException(e));
+                }
+            }
+        });
+        mFuture.get(TIMEOUT, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * Verify that calling end on a started animator does the right thing.
+     */
+    @UiThreadTest
+    @SmallTest
+    public void testStartEnd() throws Exception {
+        mFutureListener = new FutureReleaseListener(mFuture);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    mRunning = true;
+                    mAnimator.start();
+                    mAnimator.end();
+                    mFuture.release();
+                } catch (junit.framework.AssertionFailedError e) {
+                    mFuture.setException(new RuntimeException(e));
+                }
+            }
+        });
+        mFuture.get(TIMEOUT, TimeUnit.MILLISECONDS);
     }
 
     /**
      * Same as testStartCancel, but with a startDelayed animator
      */
-    @UiThreadTest
     @SmallTest
     public void testStartDelayedCancel() throws Exception {
+        mFutureListener = new FutureReleaseListener(mFuture);
         mAnimator.setStartDelay(ANIM_DELAY);
-        mRunning = true;
-        mAnimator.start();
-        mAnimator.cancel();
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    mRunning = true;
+                    mAnimator.start();
+                    mAnimator.cancel();
+                    mFuture.release();
+                } catch (junit.framework.AssertionFailedError e) {
+                    mFuture.setException(new RuntimeException(e));
+                }
+            }
+        });
+        mFuture.get(TIMEOUT, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * Same as testStartEnd, but with a startDelayed animator
+     */
+    @SmallTest
+    public void testStartDelayedEnd() throws Exception {
+        mFutureListener = new FutureReleaseListener(mFuture);
+        mAnimator.setStartDelay(ANIM_DELAY);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    mRunning = true;
+                    mAnimator.start();
+                    mAnimator.end();
+                    mFuture.release();
+                } catch (junit.framework.AssertionFailedError e) {
+                    mFuture.setException(new RuntimeException(e));
+                }
+            }
+        });
+        mFuture.get(TIMEOUT, TimeUnit.MILLISECONDS);
     }
 
     /**
@@ -180,13 +318,36 @@
                     mAnimator.addListener(mFutureListener);
                     mRunning = true;
                     mAnimator.start();
-                    handler.postDelayed(new Canceler(mAnimator), ANIM_MID_DURATION);
+                    handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DURATION);
                 } catch (junit.framework.AssertionFailedError e) {
                     mFuture.setException(new RuntimeException(e));
                 }
             }
         });
-        mFuture.get();
+        mFuture.get(TIMEOUT, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * Verify that ending an animator that is playing does the right thing.
+     */
+    @MediumTest
+    public void testPlayingEnd() throws Exception {
+        mFutureListener = new FutureReleaseListener(mFuture);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Handler handler = new Handler();
+                    mAnimator.addListener(mFutureListener);
+                    mRunning = true;
+                    mAnimator.start();
+                    handler.postDelayed(new Ender(mAnimator, mFuture), ANIM_MID_DURATION);
+                } catch (junit.framework.AssertionFailedError e) {
+                    mFuture.setException(new RuntimeException(e));
+                }
+            }
+        });
+        mFuture.get(TIMEOUT, TimeUnit.MILLISECONDS);
     }
 
     /**
@@ -204,13 +365,91 @@
                     mAnimator.addListener(mFutureListener);
                     mRunning = true;
                     mAnimator.start();
-                    handler.postDelayed(new Canceler(mAnimator), ANIM_MID_DURATION);
+                    handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DURATION);
                 } catch (junit.framework.AssertionFailedError e) {
                     mFuture.setException(new RuntimeException(e));
                 }
             }
         });
-        mFuture.get();
+        mFuture.get(TIMEOUT,  TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * Same as testPlayingEnd, but with a startDelayed animator
+     */
+    @MediumTest
+    public void testPlayingDelayedEnd() throws Exception {
+        mAnimator.setStartDelay(ANIM_DELAY);
+        mFutureListener = new FutureReleaseListener(mFuture);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    Handler handler = new Handler();
+                    mAnimator.addListener(mFutureListener);
+                    mRunning = true;
+                    mAnimator.start();
+                    handler.postDelayed(new Ender(mAnimator, mFuture), ANIM_MID_DURATION);
+                } catch (junit.framework.AssertionFailedError e) {
+                    mFuture.setException(new RuntimeException(e));
+                }
+            }
+        });
+        mFuture.get(TIMEOUT,  TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * Same as testPlayingDelayedCancel, but cancel during the startDelay period
+     */
+    @MediumTest
+    public void testPlayingDelayedCancelMidDelay() throws Exception {
+        mAnimator.setStartDelay(ANIM_DELAY);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    // Set the listener to automatically timeout after an uncanceled animation
+                    // would have finished. This tests to make sure that we're not calling
+                    // the listeners with cancel/end callbacks since they won't be called
+                    // with the start event.
+                    mFutureListener = new FutureReleaseListener(mFuture, TIMEOUT);
+                    Handler handler = new Handler();
+                    mRunning = true;
+                    mAnimator.start();
+                    handler.postDelayed(new Canceler(mAnimator, mFuture), ANIM_MID_DELAY);
+                } catch (junit.framework.AssertionFailedError e) {
+                    mFuture.setException(new RuntimeException(e));
+                }
+            }
+        });
+        mFuture.get(TIMEOUT + 100,  TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * Same as testPlayingDelayedEnd, but end during the startDelay period
+     */
+    @MediumTest
+    public void testPlayingDelayedEndMidDelay() throws Exception {
+        mAnimator.setStartDelay(ANIM_DELAY);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    // Set the listener to automatically timeout after an uncanceled animation
+                    // would have finished. This tests to make sure that we're not calling
+                    // the listeners with cancel/end callbacks since they won't be called
+                    // with the start event.
+                    mFutureListener = new FutureReleaseListener(mFuture, TIMEOUT);
+                    Handler handler = new Handler();
+                    mRunning = true;
+                    mAnimator.start();
+                    handler.postDelayed(new Ender(mAnimator, mFuture), ANIM_MID_DELAY);
+                } catch (junit.framework.AssertionFailedError e) {
+                    mFuture.setException(new RuntimeException(e));
+                }
+            }
+        });
+        mFuture.get(TIMEOUT + 100,  TimeUnit.MILLISECONDS);
     }
 
     /**
@@ -234,7 +473,31 @@
                 }
             }
         });
-        mFuture.get();
+        mFuture.get(TIMEOUT,  TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * Verifies that ending a started animation after it has already been ended
+     * does nothing.
+     */
+    @MediumTest
+    public void testStartDoubleEnd() throws Exception {
+        mFutureListener = new FutureReleaseListener(mFuture);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    mRunning = true;
+                    mAnimator.start();
+                    mAnimator.end();
+                    mAnimator.end();
+                    mFuture.release();
+                } catch (junit.framework.AssertionFailedError e) {
+                    mFuture.setException(new RuntimeException(e));
+                }
+            }
+        });
+        mFuture.get(TIMEOUT,  TimeUnit.MILLISECONDS);
     }
 
     /**
@@ -258,8 +521,31 @@
                 }
             }
         });
-        mFuture.get();
-    }
+        mFuture.get(TIMEOUT,  TimeUnit.MILLISECONDS);
+     }
 
+    /**
+     * Same as testStartDoubleEnd, but with a startDelayed animator
+     */
+    @MediumTest
+    public void testStartDelayedDoubleEnd() throws Exception {
+        mAnimator.setStartDelay(ANIM_DELAY);
+        mFutureListener = new FutureReleaseListener(mFuture);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    mRunning = true;
+                    mAnimator.start();
+                    mAnimator.end();
+                    mAnimator.end();
+                    mFuture.release();
+                } catch (junit.framework.AssertionFailedError e) {
+                    mFuture.setException(new RuntimeException(e));
+                }
+            }
+        });
+        mFuture.get(TIMEOUT,  TimeUnit.MILLISECONDS);
+     }
 
 }
diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
index 242057c..4db4ea5 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
@@ -16,6 +16,14 @@
 
 package android.net;
 
+import static android.net.NetworkStatsHistory.FIELD_ALL;
+import static android.net.NetworkStatsHistory.FIELD_OPERATIONS;
+import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
+import static android.net.NetworkStatsHistory.FIELD_RX_PACKETS;
+import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
+import static android.net.NetworkStatsHistory.DataStreamUtils.readVarLong;
+import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLong;
+import static android.net.NetworkStatsHistory.Entry.UNKNOWN;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
@@ -30,7 +38,10 @@
 
 import com.android.frameworks.coretests.R;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
+import java.io.DataOutputStream;
 import java.util.Random;
 
 @SmallTest
@@ -39,6 +50,10 @@
 
     private static final long TEST_START = 1194220800000L;
 
+    private static final long KB_IN_BYTES = 1024;
+    private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
+    private static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
+
     private NetworkStatsHistory stats;
 
     @Override
@@ -80,10 +95,11 @@
         stats = new NetworkStatsHistory(BUCKET_SIZE);
 
         // record data into narrow window to get single bucket
-        stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 1024L, 2048L);
+        stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS,
+                new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L));
 
         assertEquals(1, stats.size());
-        assertValues(stats, 0, 1024L, 2048L);
+        assertValues(stats, 0, 1024L, 10L, 2048L, 20L, 2L);
     }
 
     public void testRecordEqualBuckets() throws Exception {
@@ -92,11 +108,12 @@
 
         // split equally across two buckets
         final long recordStart = TEST_START + (bucketDuration / 2);
-        stats.recordData(recordStart, recordStart + bucketDuration, 1024L, 128L);
+        stats.recordData(recordStart, recordStart + bucketDuration,
+                new NetworkStats.Entry(1024L, 10L, 128L, 2L, 2L));
 
         assertEquals(2, stats.size());
-        assertValues(stats, 0, 512L, 64L);
-        assertValues(stats, 1, 512L, 64L);
+        assertValues(stats, 0, 512L, 5L, 64L, 1L, 1L);
+        assertValues(stats, 1, 512L, 5L, 64L, 1L, 1L);
     }
 
     public void testRecordTouchingBuckets() throws Exception {
@@ -107,15 +124,16 @@
         // overlap into neighboring buckets. total record is 20 minutes.
         final long recordStart = (TEST_START + BUCKET_SIZE) - MINUTE_IN_MILLIS;
         final long recordEnd = (TEST_START + (BUCKET_SIZE * 2)) + (MINUTE_IN_MILLIS * 4);
-        stats.recordData(recordStart, recordEnd, 1000L, 5000L);
+        stats.recordData(recordStart, recordEnd,
+                new NetworkStats.Entry(1000L, 2000L, 5000L, 10000L, 100L));
 
         assertEquals(3, stats.size());
         // first bucket should have (1/20 of value)
-        assertValues(stats, 0, 50L, 250L);
+        assertValues(stats, 0, 50L, 100L, 250L, 500L, 5L);
         // second bucket should have (15/20 of value)
-        assertValues(stats, 1, 750L, 3750L);
+        assertValues(stats, 1, 750L, 1500L, 3750L, 7500L, 75L);
         // final bucket should have (4/20 of value)
-        assertValues(stats, 2, 200L, 1000L);
+        assertValues(stats, 2, 200L, 400L, 1000L, 2000L, 20L);
     }
 
     public void testRecordGapBuckets() throws Exception {
@@ -125,25 +143,28 @@
         // record some data today and next week with large gap
         final long firstStart = TEST_START;
         final long lastStart = TEST_START + WEEK_IN_MILLIS;
-        stats.recordData(firstStart, firstStart + SECOND_IN_MILLIS, 128L, 256L);
-        stats.recordData(lastStart, lastStart + SECOND_IN_MILLIS, 64L, 512L);
+        stats.recordData(firstStart, firstStart + SECOND_IN_MILLIS,
+                new NetworkStats.Entry(128L, 2L, 256L, 4L, 1L));
+        stats.recordData(lastStart, lastStart + SECOND_IN_MILLIS,
+                new NetworkStats.Entry(64L, 1L, 512L, 8L, 2L));
 
         // we should have two buckets, far apart from each other
         assertEquals(2, stats.size());
-        assertValues(stats, 0, 128L, 256L);
-        assertValues(stats, 1, 64L, 512L);
+        assertValues(stats, 0, 128L, 2L, 256L, 4L, 1L);
+        assertValues(stats, 1, 64L, 1L, 512L, 8L, 2L);
 
         // now record something in middle, spread across two buckets
         final long middleStart = TEST_START + DAY_IN_MILLIS;
         final long middleEnd = middleStart + (HOUR_IN_MILLIS * 2);
-        stats.recordData(middleStart, middleEnd, 2048L, 2048L);
+        stats.recordData(middleStart, middleEnd,
+                new NetworkStats.Entry(2048L, 4L, 2048L, 4L, 2L));
 
         // now should have four buckets, with new record in middle two buckets
         assertEquals(4, stats.size());
-        assertValues(stats, 0, 128L, 256L);
-        assertValues(stats, 1, 1024L, 1024L);
-        assertValues(stats, 2, 1024L, 1024L);
-        assertValues(stats, 3, 64L, 512L);
+        assertValues(stats, 0, 128L, 2L, 256L, 4L, 1L);
+        assertValues(stats, 1, 1024L, 2L, 1024L, 2L, 1L);
+        assertValues(stats, 2, 1024L, 2L, 1024L, 2L, 1L);
+        assertValues(stats, 3, 64L, 1L, 512L, 8L, 2L);
     }
 
     public void testRecordOverlapBuckets() throws Exception {
@@ -151,14 +172,16 @@
         stats = new NetworkStatsHistory(BUCKET_SIZE);
 
         // record some data in one bucket, and another overlapping buckets
-        stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 256L, 256L);
+        stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS,
+                new NetworkStats.Entry(256L, 2L, 256L, 2L, 1L));
         final long midStart = TEST_START + (HOUR_IN_MILLIS / 2);
-        stats.recordData(midStart, midStart + HOUR_IN_MILLIS, 1024L, 1024L);
+        stats.recordData(midStart, midStart + HOUR_IN_MILLIS,
+                new NetworkStats.Entry(1024L, 10L, 1024L, 10L, 10L));
 
         // should have two buckets, with some data mixed together
         assertEquals(2, stats.size());
-        assertValues(stats, 0, 768L, 768L);
-        assertValues(stats, 1, 512L, 512L);
+        assertValues(stats, 0, 768L, 7L, 768L, 7L, 6L);
+        assertValues(stats, 1, 512L, 5L, 512L, 5L, 5L);
     }
 
     public void testRecordEntireGapIdentical() throws Exception {
@@ -283,6 +306,7 @@
     public void testFuzzing() throws Exception {
         try {
             // fuzzing with random events, looking for crashes
+            final NetworkStats.Entry entry = new NetworkStats.Entry();
             final Random r = new Random();
             for (int i = 0; i < 500; i++) {
                 stats = new NetworkStatsHistory(r.nextLong());
@@ -291,7 +315,12 @@
                         // add range
                         final long start = r.nextLong();
                         final long end = start + r.nextInt();
-                        stats.recordData(start, end, r.nextLong(), r.nextLong());
+                        entry.rxBytes = nextPositiveLong(r);
+                        entry.rxPackets = nextPositiveLong(r);
+                        entry.txBytes = nextPositiveLong(r);
+                        entry.txPackets = nextPositiveLong(r);
+                        entry.operations = nextPositiveLong(r);
+                        stats.recordData(start, end, entry);
                     } else {
                         // trim something
                         stats.removeBucketsBefore(r.nextLong());
@@ -305,6 +334,88 @@
         }
     }
 
+    private static long nextPositiveLong(Random r) {
+        final long value = r.nextLong();
+        return value < 0 ? -value : value;
+    }
+
+    public void testIgnoreFields() throws Exception {
+        final NetworkStatsHistory history = new NetworkStatsHistory(
+                MINUTE_IN_MILLIS, 0, FIELD_RX_BYTES | FIELD_TX_BYTES);
+
+        history.recordData(0, MINUTE_IN_MILLIS,
+                new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
+        history.recordData(0, MINUTE_IN_MILLIS * 2,
+                new NetworkStats.Entry(2L, 2L, 2L, 2L, 2L));
+
+        assertValues(
+                history, Long.MIN_VALUE, Long.MAX_VALUE, 1026L, UNKNOWN, 2050L, UNKNOWN, UNKNOWN);
+    }
+
+    public void testIgnoreFieldsRecordIn() throws Exception {
+        final NetworkStatsHistory full = new NetworkStatsHistory(MINUTE_IN_MILLIS, 0, FIELD_ALL);
+        final NetworkStatsHistory partial = new NetworkStatsHistory(
+                MINUTE_IN_MILLIS, 0, FIELD_RX_PACKETS | FIELD_OPERATIONS);
+
+        full.recordData(0, MINUTE_IN_MILLIS,
+                new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
+        partial.recordEntireHistory(full);
+
+        assertValues(partial, Long.MIN_VALUE, Long.MAX_VALUE, UNKNOWN, 10L, UNKNOWN, UNKNOWN, 4L);
+    }
+
+    public void testIgnoreFieldsRecordOut() throws Exception {
+        final NetworkStatsHistory full = new NetworkStatsHistory(MINUTE_IN_MILLIS, 0, FIELD_ALL);
+        final NetworkStatsHistory partial = new NetworkStatsHistory(
+                MINUTE_IN_MILLIS, 0, FIELD_RX_PACKETS | FIELD_OPERATIONS);
+
+        partial.recordData(0, MINUTE_IN_MILLIS,
+                new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
+        full.recordEntireHistory(partial);
+
+        assertValues(full, Long.MIN_VALUE, Long.MAX_VALUE, 0L, 10L, 0L, 0L, 4L);
+    }
+
+    public void testSerialize() throws Exception {
+        final NetworkStatsHistory before = new NetworkStatsHistory(MINUTE_IN_MILLIS, 40, FIELD_ALL);
+        before.recordData(0, MINUTE_IN_MILLIS * 4,
+                new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
+        before.recordData(DAY_IN_MILLIS, DAY_IN_MILLIS + MINUTE_IN_MILLIS,
+                new NetworkStats.Entry(10L, 20L, 30L, 40L, 50L));
+
+        final ByteArrayOutputStream out = new ByteArrayOutputStream();
+        before.writeToStream(new DataOutputStream(out));
+        out.close();
+
+        final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+        final NetworkStatsHistory after = new NetworkStatsHistory(new DataInputStream(in));
+
+        // must have identical totals before and after
+        assertValues(before, Long.MIN_VALUE, Long.MAX_VALUE, 1034L, 30L, 2078L, 60L, 54L);
+        assertValues(after, Long.MIN_VALUE, Long.MAX_VALUE, 1034L, 30L, 2078L, 60L, 54L);
+    }
+
+    public void testVarLong() throws Exception {
+        assertEquals(0L, performVarLong(0L));
+        assertEquals(-1L, performVarLong(-1L));
+        assertEquals(1024L, performVarLong(1024L));
+        assertEquals(-1024L, performVarLong(-1024L));
+        assertEquals(40 * MB_IN_BYTES, performVarLong(40 * MB_IN_BYTES));
+        assertEquals(512 * GB_IN_BYTES, performVarLong(512 * GB_IN_BYTES));
+        assertEquals(Long.MIN_VALUE, performVarLong(Long.MIN_VALUE));
+        assertEquals(Long.MAX_VALUE, performVarLong(Long.MAX_VALUE));
+        assertEquals(Long.MIN_VALUE + 40, performVarLong(Long.MIN_VALUE + 40));
+        assertEquals(Long.MAX_VALUE - 40, performVarLong(Long.MAX_VALUE - 40));
+    }
+
+    private static long performVarLong(long before) throws Exception {
+        final ByteArrayOutputStream out = new ByteArrayOutputStream();
+        writeVarLong(new DataOutputStream(out), before);
+
+        final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+        return readVarLong(new DataInputStream(in));
+    }
+
     private static void assertConsistent(NetworkStatsHistory stats) {
         // verify timestamps are monotonic
         long lastStart = Long.MIN_VALUE;
@@ -330,4 +441,23 @@
         assertEquals("unexpected txBytes", txBytes, entry.txBytes);
     }
 
+    private static void assertValues(NetworkStatsHistory stats, int index, long rxBytes,
+            long rxPackets, long txBytes, long txPackets, long operations) {
+        final NetworkStatsHistory.Entry entry = stats.getValues(index, null);
+        assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
+        assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
+        assertEquals("unexpected txBytes", txBytes, entry.txBytes);
+        assertEquals("unexpected txPackets", txPackets, entry.txPackets);
+        assertEquals("unexpected operations", operations, entry.operations);
+    }
+
+    private static void assertValues(NetworkStatsHistory stats, long start, long end, long rxBytes,
+            long rxPackets, long txBytes, long txPackets, long operations) {
+        final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null);
+        assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
+        assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
+        assertEquals("unexpected txBytes", txBytes, entry.txBytes);
+        assertEquals("unexpected txPackets", txPackets, entry.txPackets);
+        assertEquals("unexpected operations", operations, entry.operations);
+    }
 }
diff --git a/docs/html/guide/developing/tools/draw9patch.jd b/docs/html/guide/developing/tools/draw9patch.jd
index 1d9de4f..7cf0e4b 100644
--- a/docs/html/guide/developing/tools/draw9patch.jd
+++ b/docs/html/guide/developing/tools/draw9patch.jd
@@ -41,7 +41,7 @@
      A previously saved 9-patch file (<code>*.9.png</code>) will be loaded as-is, 
      with no drawing area added, because it already exists.</p>
 
-<img src="{@docRoot}images/draw9patch-bad.png" style="float:right" alt="" height="300" width="341"
+<img src="{@docRoot}images/draw9patch-bad.png" style="float:right;clear:both" alt="" height="300" width="341"
 />
 
 <p>Optional controls include:</p>
diff --git a/drm/libdrmframework/plugins/common/util/include/SessionMap.h b/drm/libdrmframework/plugins/common/util/include/SessionMap.h
index 3dff58c..e563894 100644
--- a/drm/libdrmframework/plugins/common/util/include/SessionMap.h
+++ b/drm/libdrmframework/plugins/common/util/include/SessionMap.h
@@ -13,141 +13,175 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #ifndef __SESSIONMAP_H__
 #define __SESSIONMAP_H__
 
 #include <utils/KeyedVector.h>
+#include <utils/threads.h>
 
 namespace android {
 
 /**
- * A wrapper template class for handling DRM Engine sessions.
+ * A thread safe wrapper template class for session handlings for Drm Engines. It wraps a
+ * pointer type over KeyedVector. It keeps pointer as data in the vector and free up memory
+ * allocated pointer can be of any type of structure/class meant for keeping session data.
+ * so session object here means pointer to the session data.
  */
-template <typename NODE>
+template <typename TValue>
 class SessionMap {
 
 public:
-    KeyedVector<int, NODE> map;
-
     SessionMap() {}
 
     virtual ~SessionMap() {
+        Mutex::Autolock lock(mLock);
         destroyMap();
     }
 
-/**
- * Adds a new value in the session map table. It expects memory to be allocated already
- * for the session object
- *
- * @param key - key or Session ID
- * @param value - session object to add
- *
- * @return boolean result of adding value. returns false if key is already exist.
- */
-bool addValue(int key, NODE value) {
-    bool result = false;
-
-    if (!isCreated(key)) {
-        map.add(key, value);
-        result = true;
+    /**
+     * Adds a new value in the session map table. It expects memory to be allocated already
+     * for the session object
+     *
+     * @param key - key or Session ID
+     * @param value - session object to add
+     *
+     * @return boolean result of adding value. returns false if key is already exist.
+     */
+    bool addValue(int key, TValue value) {
+        Mutex::Autolock lock(mLock);
+        if (!isCreatedInternal(key)) {
+            map.add(key, value);
+            return true;
+        }
+        return false;
     }
 
-    return result;
-}
-
-
-/**
- * returns the session object by the key
- *
- * @param key - key or Session ID
- *
- * @return session object as per the key
- */
-NODE getValue(int key) {
-    NODE value = NULL;
-
-    if (isCreated(key)) {
-        value = (NODE) map.valueFor(key);
+    /**
+     * returns the session object by the key
+     *
+     * @param key - key or Session ID
+     *
+     * @return session object as per the key
+     */
+    TValue getValue(int key) {
+        Mutex::Autolock lock(mLock);
+        return getValueInternal(key);
     }
 
-    return value;
-}
-
-/**
- * returns the number of objects in the session map table
- *
- * @return count of number of session objects.
- */
-int getSize() {
-    return map.size();
-}
-
-/**
- * returns the session object by the index in the session map table
- *
- * @param index - index of the value required
- *
- * @return session object as per the index
- */
-NODE getValueAt(unsigned int index) {
-    NODE value = NULL;
-
-    if (map.size() > index) {
-      value = map.valueAt(index);
+    /**
+     * returns the number of objects in the session map table
+     *
+     * @return count of number of session objects.
+     */
+    int getSize() {
+        Mutex::Autolock lock(mLock);
+        return map.size();
     }
 
-    return value;
-}
+    /**
+     * returns the session object by the index in the session map table
+     *
+     * @param index - index of the value required
+     *
+     * @return session object as per the index
+     */
+    TValue getValueAt(unsigned int index) {
+        TValue value = NULL;
+        Mutex::Autolock lock(mLock);
 
-/**
- * deletes the object from session map. It also frees up memory for the session object.
- *
- * @param key - key of the value to be deleted
- *
- */
-void removeValue(int key) {
-    deleteValue(getValue(key));
-    map.removeItem(key);
-}
-
-/**
- * decides if session is already created.
- *
- * @param key - key of the value for the session
- *
- * @return boolean result of whether session is created
- */
-bool isCreated(int key) {
-    return (0 <= map.indexOfKey(key));
-}
-
-/**
- * empty the entire session table. It releases all the memory for session objects.
- */
-void destroyMap() {
-    int size = map.size();
-    int i = 0;
-
-    for (i = 0; i < size; i++) {
-        deleteValue(map.valueAt(i));
+        if (map.size() > index) {
+            value = map.valueAt(index);
+        }
+        return value;
     }
 
-    map.clear();
-}
+    /**
+     * deletes the object from session map. It also frees up memory for the session object.
+     *
+     * @param key - key of the value to be deleted
+     *
+     */
+    void removeValue(int key) {
+        Mutex::Autolock lock(mLock);
+        deleteValue(getValueInternal(key));
+        map.removeItem(key);
+    }
 
-/**
- * free up the memory for the session object.
- * Make sure if any reference to the session object anywhere, otherwise it will be a
- * dangle pointer after this call.
- *
- * @param value - session object to free
- *
- */
-void deleteValue(NODE value) {
-    delete value;
-}
+    /**
+     * decides if session is already created.
+     *
+     * @param key - key of the value for the session
+     *
+     * @return boolean result of whether session is created
+     */
+    bool isCreated(int key) {
+        Mutex::Autolock lock(mLock);
+        return isCreatedInternal(key);
+    }
 
+    SessionMap<TValue> & operator=(const SessionMap<TValue> & objectCopy) {
+        Mutex::Autolock lock(mLock);
+
+        destroyMap();
+        map = objectCopy.map;
+        return *this;
+    }
+
+private:
+    KeyedVector<int, TValue> map;
+    Mutex mLock;
+
+   /**
+    * free up the memory for the session object.
+    * Make sure if any reference to the session object anywhere, otherwise it will be a
+    * dangle pointer after this call.
+    *
+    * @param value - session object to free
+    *
+    */
+    void deleteValue(TValue value) {
+        delete value;
+    }
+
+   /**
+    * free up the memory for the entire map.
+    * free up any resources in the sessions before calling this funtion.
+    *
+    */
+    void destroyMap() {
+        int size = map.size();
+
+        for (int i = 0; i < size; i++) {
+            deleteValue(map.valueAt(i));
+        }
+        map.clear();
+    }
+
+   /**
+    * decides if session is already created.
+    *
+    * @param key - key of the value for the session
+    *
+    * @return boolean result of whether session is created
+    */
+    bool isCreatedInternal(int key) {
+        return(0 <= map.indexOfKey(key));
+    }
+
+   /**
+    * returns the session object by the key
+    *
+    * @param key - key or Session ID
+    *
+    * @return session object as per the key
+    */
+    TValue getValueInternal(int key) {
+        TValue value = NULL;
+        if (isCreatedInternal(key)) {
+            value = (TValue) map.valueFor(key);
+        }
+        return value;
+    }
 };
 
 };
diff --git a/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp b/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
index 4ee903e..57ef799 100644
--- a/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
+++ b/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
@@ -22,6 +22,13 @@
 #undef LOG_TAG
 #define LOG_TAG "MimeTypeUtil"
 
+#ifdef DRM_OMA_FL_ENGINE_DEBUG
+#define LOG_NDEBUG 0
+#define LOG_DEBUG(...) LOGD(__VA_ARGS__)
+#else
+#define LOG_DEBUG(...)
+#endif
+
 enum {
     MIMETYPE_AUDIO       = 0,
     MIMETYPE_APPLICATION = 1,
@@ -59,6 +66,7 @@
 static const char mime_group_application[] = "application/";
 static const char mime_group_image[]       = "image/";
 static const char mime_group_video[]       = "video/";
+static const char mime_type_unsupported[]  = "unsupported/drm.mimetype";
 
 static struct MimeGroup mimeGroup[] = {
     {MIMETYPE_AUDIO,       mime_group_audio,        sizeof(mime_group_audio)-1},
@@ -107,48 +115,52 @@
  * replacement mimetype otherwise the original mimetype
  * is returned.
  *
+ * If the mimetype is of unsupported group i.e. application/*
+ * then "unsupported/drm.mimetype" will be returned.
+ *
  * @param mimeType - mimetype in lower case to convert.
  *
- * @return mimetype or null.
+ * @return mimetype or "unsupported/drm.mimetype".
  */
 String8 MimeTypeUtil::convertMimeType(String8& mimeType) {
     String8 result = mimeType;
-    const char* pTmp;
     const char* pMimeType;
     struct MimeGroup* pGroup;
     struct MimeTypeList* pMimeItem;
     int len;
-
     pMimeType = mimeType.string();
     if (NULL != pMimeType) {
-        /* Check which group the mimetype is */
-        pGroup = mimeGroup;
-
-        while (MIMETYPE_LAST != pGroup->type) {
-            if (0 == strncmp(pMimeType, pGroup->pGroup, pGroup->size)) {
-                break;
-            }
-            pGroup++;
-        }
-
-        /* Go through the mimetype list. Only check items of the correct group */
-        if (MIMETYPE_LAST != pGroup->type) {
-            pMimeItem = mimeTypeList;
-            len = strlen (pMimeType+pGroup->size);
-
-            while (MIMETYPE_LAST != pMimeItem->type) {
-                if ((len == pMimeItem->size) &&
-                    (0 == strcmp(pMimeType+pGroup->size, pMimeItem->pMimeExt))) {
-                    result = String8(pMimeItem->pMimeType);
+        if ((0 == strncmp(pMimeType, mime_group_audio, (sizeof mime_group_audio) - 1)) ||
+            (0 == strncmp(pMimeType, mime_group_video, (sizeof mime_group_video) - 1))) {
+            /* Check which group the mimetype is */
+            pGroup = mimeGroup;
+            while (MIMETYPE_LAST != pGroup->type) {
+                if (0 == strncmp(pMimeType, pGroup->pGroup, pGroup->size)) {
                     break;
                 }
-                pMimeItem++;
+                pGroup++;
             }
-        }
-        LOGI("convertMimeType got mimetype %s, converted into mimetype %s",
-             pMimeType, result.string());
-    }
 
+            /* Go through the mimetype list. Only check items of the correct group */
+            if (MIMETYPE_LAST != pGroup->type) {
+                pMimeItem = mimeTypeList;
+                len = strlen (pMimeType+pGroup->size);
+                while (MIMETYPE_LAST != pMimeItem->type) {
+                    if ((pGroup->type == pMimeItem->type) &&
+                        (len == pMimeItem->size) &&
+                        (0 == strcmp(pMimeType+pGroup->size, pMimeItem->pMimeExt))) {
+                        result = String8(pMimeItem->pMimeType);
+                        break;
+                    }
+                    pMimeItem++;
+                }
+            }
+        } else {
+            result = String8(mime_type_unsupported);
+        }
+        LOG_DEBUG("convertMimeType got mimetype %s, converted into mimetype %s",
+                pMimeType, result.string());
+    }
     return result;
 }
 };
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
index 9805a40..e359dbd 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
@@ -17,6 +17,9 @@
 
 include $(CLEAR_VARS)
 
+# The flag below turns on local debug printouts
+#LOCAL_CFLAGS += -DDRM_OMA_FL_ENGINE_DEBUG
+
 base := frameworks/base
 
 # Determine whether the DRM framework uses 64-bit data types for file offsets and do the same.
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
index 31c3c14..e184545 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
@@ -41,6 +41,13 @@
 #undef LOG_TAG
 #define LOG_TAG "FwdLockEngine"
 
+#ifdef DRM_OMA_FL_ENGINE_DEBUG
+#define LOG_NDEBUG 0
+#define LOG_VERBOSE(...) LOGV(__VA_ARGS__)
+#else
+#define LOG_VERBOSE(...)
+#endif
+
 using namespace android;
 // This extern "C" is mandatory to be managed by TPlugInManager
 extern "C" IDrmEngine* create() {
@@ -53,14 +60,25 @@
 }
 
 FwdLockEngine::FwdLockEngine() {
-    LOGV("FwdLockEngine Construction");
+    LOG_VERBOSE("FwdLockEngine Construction");
 }
 
 FwdLockEngine::~FwdLockEngine() {
-    LOGV("FwdLockEngine Destruction");
+    LOG_VERBOSE("FwdLockEngine Destruction");
 
-    convertSessionMap.destroyMap();
-    decodeSessionMap.destroyMap();
+    int size = decodeSessionMap.getSize();
+
+    for (int i = 0; i < size; i++) {
+        DecodeSession *session = (DecodeSession*) decodeSessionMap.getValueAt(i);
+        FwdLockFile_detach(session->fileDesc);
+        ::close(session->fileDesc);
+    }
+
+    size = convertSessionMap.getSize();
+    for (int i = 0; i < size; i++) {
+        ConvertSession *convSession = (ConvertSession*) convertSessionMap.getValueAt(i);
+        FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output));
+    }
 }
 
 int FwdLockEngine::getConvertedStatus(FwdLockConv_Status_t status) {
@@ -74,12 +92,12 @@
         case FwdLockConv_Status_InvalidArgument:
         case FwdLockConv_Status_UnsupportedFileFormat:
         case FwdLockConv_Status_UnsupportedContentTransferEncoding:
-            LOGD("FwdLockEngine getConvertedStatus: file conversion Error %d. " \
+            LOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. "
                   "Returning STATUS_INPUTDATA_ERROR", status);
             retStatus = DrmConvertedStatus::STATUS_INPUTDATA_ERROR;
             break;
         default:
-            LOGD("FwdLockEngine getConvertedStatus: file conversion Error %d. " \
+            LOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. "
                   "Returning STATUS_ERROR", status);
             retStatus = DrmConvertedStatus::STATUS_ERROR;
             break;
@@ -91,7 +109,7 @@
 DrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* path, int action) {
     DrmConstraints* drmConstraints = NULL;
 
-    LOGV("FwdLockEngine::onGetConstraints");
+    LOG_VERBOSE("FwdLockEngine::onGetConstraints");
 
     if (NULL != path &&
         (RightsStatus::RIGHTS_VALID == onCheckRightsStatus(uniqueId, *path, action))) {
@@ -105,7 +123,7 @@
 DrmMetadata* FwdLockEngine::onGetMetadata(int uniqueId, const String8* path) {
     DrmMetadata* drmMetadata = NULL;
 
-    LOGV("FwdLockEngine::onGetMetadata");
+    LOG_VERBOSE("FwdLockEngine::onGetMetadata");
 
     if (NULL != path) {
         // Returns empty metadata to show no error condition.
@@ -116,13 +134,12 @@
 }
 
 android::status_t FwdLockEngine::onInitialize(int uniqueId) {
-    LOGV("FwdLockEngine::onInitialize");
-
+    LOG_VERBOSE("FwdLockEngine::onInitialize");
 
     if (FwdLockGlue_InitializeKeyEncryption()) {
-        LOGV("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded");
+        LOG_VERBOSE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded");
     } else {
-        LOGD("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption failed:"
+        LOGE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption failed:"
              "errno = %d", errno);
     }
 
@@ -132,13 +149,13 @@
 android::status_t
 FwdLockEngine::onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
     // Not used
-    LOGV("FwdLockEngine::onSetOnInfoListener");
+    LOG_VERBOSE("FwdLockEngine::onSetOnInfoListener");
 
     return DRM_NO_ERROR;
 }
 
 android::status_t FwdLockEngine::onTerminate(int uniqueId) {
-    LOGV("FwdLockEngine::onTerminate");
+    LOG_VERBOSE("FwdLockEngine::onTerminate");
 
     return DRM_NO_ERROR;
 }
@@ -146,7 +163,7 @@
 DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int uniqueId) {
     DrmSupportInfo* pSupportInfo = new DrmSupportInfo();
 
-    LOGV("FwdLockEngine::onGetSupportInfo");
+    LOG_VERBOSE("FwdLockEngine::onGetSupportInfo");
 
     // fill all Forward Lock mimetypes and extensions
     if (NULL != pSupportInfo) {
@@ -182,7 +199,7 @@
 
     drmInfoStatus = new DrmInfoStatus((int)DrmInfoStatus::STATUS_OK, 0, NULL, String8(""));
 
-    LOGV("FwdLockEngine::onProcessDrmInfo");
+    LOG_VERBOSE("FwdLockEngine::onProcessDrmInfo");
 
     return drmInfoStatus;
 }
@@ -193,7 +210,7 @@
             const String8& rightsPath,
             const String8& contentPath) {
     // No rights to save. Return
-    LOGV("FwdLockEngine::onSaveRights");
+    LOG_VERBOSE("FwdLockEngine::onSaveRights");
     return DRM_ERROR_UNKNOWN;
 }
 
@@ -201,7 +218,7 @@
     DrmInfo* drmInfo = NULL;
 
     // Nothing to be done for Forward Lock file
-    LOGV("FwdLockEngine::onAcquireDrmInfo");
+    LOG_VERBOSE("FwdLockEngine::onAcquireDrmInfo");
 
     return drmInfo;
 }
@@ -211,7 +228,7 @@
                                        int action) {
     int result = RightsStatus::RIGHTS_INVALID;
 
-    LOGV("FwdLockEngine::onCheckRightsStatus");
+    LOG_VERBOSE("FwdLockEngine::onCheckRightsStatus");
 
     // Only Transfer action is not allowed for forward Lock files.
     if (onCanHandle(uniqueId, path)) {
@@ -241,7 +258,7 @@
                                         int action,
                                         bool reserve) {
     // No rights consumption
-    LOGV("FwdLockEngine::onConsumeRights");
+    LOG_VERBOSE("FwdLockEngine::onConsumeRights");
     return DRM_NO_ERROR;
 }
 
@@ -249,14 +266,14 @@
                                      const String8& path,
                                      int action,
                                      const ActionDescription& description) {
-    LOGV("FwdLockEngine::onValidateAction");
+    LOG_VERBOSE("FwdLockEngine::onValidateAction");
 
     // For the forwardlock engine checkRights and ValidateAction are the same.
     return (onCheckRightsStatus(uniqueId, path, action) == RightsStatus::RIGHTS_VALID);
 }
 
 String8 FwdLockEngine::onGetOriginalMimeType(int uniqueId, const String8& path) {
-    LOGV("FwdLockEngine::onGetOriginalMimeType");
+    LOG_VERBOSE("FwdLockEngine::onGetOriginalMimeType");
     String8 mimeString = String8("");
     int fileDesc = FwdLockFile_open(path.string());
 
@@ -280,7 +297,7 @@
                                       const String8& mimeType) {
     String8 mimeStr = String8(mimeType);
 
-    LOGV("FwdLockEngine::onGetDrmObjectType");
+    LOG_VERBOSE("FwdLockEngine::onGetDrmObjectType");
 
     mimeStr.toLower();
 
@@ -301,13 +318,13 @@
 
 status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) {
     // No Rights to remove
-    LOGV("FwdLockEngine::onRemoveRights");
+    LOG_VERBOSE("FwdLockEngine::onRemoveRights");
     return DRM_NO_ERROR;
 }
 
 status_t FwdLockEngine::onRemoveAllRights(int uniqueId) {
     // No rights to remove
-    LOGV("FwdLockEngine::onRemoveAllRights");
+    LOG_VERBOSE("FwdLockEngine::onRemoveAllRights");
     return DRM_NO_ERROR;
 }
 
@@ -319,14 +336,14 @@
                                             int playbackStatus, int position) {
 #endif
     // Not used
-    LOGV("FwdLockEngine::onSetPlaybackStatus");
+    LOG_VERBOSE("FwdLockEngine::onSetPlaybackStatus");
     return DRM_NO_ERROR;
 }
 
 status_t FwdLockEngine::onOpenConvertSession(int uniqueId,
                                          int convertId) {
     status_t result = DRM_ERROR_UNKNOWN;
-    LOGV("FwdLockEngine::onOpenConvertSession");
+    LOG_VERBOSE("FwdLockEngine::onOpenConvertSession");
     if (!convertSessionMap.isCreated(convertId)) {
         ConvertSession *newSession = new ConvertSession();
         if (FwdLockConv_Status_OK ==
@@ -334,7 +351,7 @@
             convertSessionMap.addValue(convertId, newSession);
             result = DRM_NO_ERROR;
         } else {
-            LOGD("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed.");
+            LOGE("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed.");
             delete newSession;
         }
     }
@@ -383,7 +400,7 @@
     DrmBuffer *convResult = new DrmBuffer(NULL, 0);
     int offset = -1;
 
-    LOGV("FwdLockEngine::onCloseConvertSession");
+    LOG_VERBOSE("FwdLockEngine::onCloseConvertSession");
 
     if (convertSessionMap.isCreated(convertId)) {
         ConvertSession *convSession = convertSessionMap.getValue(convertId);
@@ -424,14 +441,14 @@
     status_t result = DRM_ERROR_CANNOT_HANDLE;
     int fileDesc = -1;
 
-    LOGV("FwdLockEngine::onOpenDecryptSession");
+    LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession");
 
     if ((-1 < fd) &&
         (NULL != decryptHandle) &&
         (!decodeSessionMap.isCreated(decryptHandle->decryptId))) {
         fileDesc = dup(fd);
     } else {
-        LOGD("FwdLockEngine::onOpenDecryptSession parameter error");
+        LOGE("FwdLockEngine::onOpenDecryptSession parameter error");
         return result;
     }
 
@@ -453,7 +470,7 @@
             decryptHandle->decryptInfo = NULL;
             result = DRM_NO_ERROR;
         } else {
-            LOGD("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
+            LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
             FwdLockFile_detach(fileDesc);
             delete decodeSession;
         }
@@ -463,7 +480,7 @@
         ::close(fileDesc);
     }
 
-    LOGV("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);
+    LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);
 
     return result;
 }
@@ -500,7 +517,7 @@
 status_t FwdLockEngine::onCloseDecryptSession(int uniqueId,
                                               DecryptHandle* decryptHandle) {
     status_t result = DRM_ERROR_UNKNOWN;
-    LOGV("FwdLockEngine::onCloseDecryptSession");
+    LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession");
 
     if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
         DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
@@ -525,7 +542,7 @@
         decryptHandle = NULL;
     }
 
-    LOGV("FwdLockEngine::onCloseDecryptSession Exit");
+    LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession Exit");
     return result;
 }
 
@@ -533,13 +550,13 @@
                                                 DecryptHandle* decryptHandle,
                                                 int decryptUnitId,
                                                 const DrmBuffer* headerInfo) {
-    LOGV("FwdLockEngine::onInitializeDecryptUnit");
+    LOGE("FwdLockEngine::onInitializeDecryptUnit is not supported for this DRM scheme");
     return DRM_ERROR_UNKNOWN;
 }
 
 status_t FwdLockEngine::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
             const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
-    LOGV("FwdLockEngine::onDecrypt");
+    LOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
     return DRM_ERROR_UNKNOWN;
 }
 
@@ -548,14 +565,14 @@
                                   int decryptUnitId,
                                   const DrmBuffer* encBuffer,
                                   DrmBuffer** decBuffer) {
-    LOGV("FwdLockEngine::onDecrypt");
+    LOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
     return DRM_ERROR_UNKNOWN;
 }
 
 status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId,
                                               DecryptHandle* decryptHandle,
                                               int decryptUnitId) {
-    LOGV("FwdLockEngine::onFinalizeDecryptUnit");
+    LOGE("FwdLockEngine::onFinalizeDecryptUnit is not supported for this DRM scheme");
     return DRM_ERROR_UNKNOWN;
 }
 
@@ -633,11 +650,11 @@
         if (((off_t)-1) != decoderSession->offset) {
             bytesRead = onRead(uniqueId, decryptHandle, buffer, numBytes);
             if (bytesRead < 0) {
-                LOGD("FwdLockEngine::onPread error reading");
+                LOGE("FwdLockEngine::onPread error reading");
             }
         }
     } else {
-        LOGD("FwdLockEngine::onPread decryptId not found");
+        LOGE("FwdLockEngine::onPread decryptId not found");
     }
 
     return bytesRead;
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
index 14ea9e9..299116d 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
@@ -275,17 +275,18 @@
 }
 
 /**
- * Checks whether a given character is valid in a boundary. Note that the boundary may contain
- * leading and internal spaces.
+ * Checks whether a given character is valid in a boundary. Allows some non-standard characters that
+ * are invalid according to RFC 2046 but nevertheless used by one vendor's DRM packager. Note that
+ * the boundary may contain leading and internal spaces.
  *
  * @param[in] ch The character to check.
  *
  * @return A Boolean value indicating whether the given character is valid in a boundary.
  */
 static int FwdLockConv_IsBoundaryChar(int ch) {
-    return isalnum(ch) || ch == '\'' ||
-            ch == '(' || ch == ')' || ch == '+' || ch == '_' || ch == ',' || ch == '-' ||
-            ch == '.' || ch == '/' || ch == ':' || ch == '=' || ch == '?' || ch == ' ';
+    return isalnum(ch) || ch == '\'' || ch == '(' || ch == ')' || ch == '+' || ch == '_' ||
+            ch == ',' || ch == '-' || ch == '.' || ch == '/' || ch == ':' || ch == '=' ||
+            ch == '?' || ch == ' ' || ch == '%' || ch == '[' || ch == '&' || ch == '*' || ch == '^';
 }
 
 /**
@@ -1085,6 +1086,13 @@
         status = FwdLockConv_MatchBinaryEncodedData(pSession, ch, pOutput);
         break;
     case FwdLockConv_ParserState_WantsBase64EncodedData:
+        if (ch == '\n' && pSession->scannerState != FwdLockConv_ScannerState_WantsLF) {
+            // Repair base64-encoded data that doesn't have carriage returns in its line breaks.
+            status = FwdLockConv_MatchBase64EncodedData(pSession, '\r', pOutput);
+            if (status != FwdLockConv_Status_OK) {
+                break;
+            }
+        }
         status = FwdLockConv_MatchBase64EncodedData(pSession, ch, pOutput);
         break;
     case FwdLockConv_ParserState_Done:
@@ -1199,7 +1207,7 @@
             status = FwdLockConv_Status_SyntaxError;
         } else {
             // Finalize the data signature.
-            size_t signatureSize;
+            unsigned int signatureSize = SHA1_HASH_SIZE;
             HMAC_Final(&pSession->signingContext, pOutput->fromCloseSession.signatures,
                        &signatureSize);
             if (signatureSize != SHA1_HASH_SIZE) {
@@ -1214,9 +1222,9 @@
                 HMAC_Update(&pSession->signingContext, pSession->pEncryptedSessionKey,
                             pSession->encryptedSessionKeyLength);
                 HMAC_Update(&pSession->signingContext, pOutput->fromCloseSession.signatures,
-                            signatureSize);
-                HMAC_Final(&pSession->signingContext, &pOutput->fromCloseSession.
-                           signatures[signatureSize], &signatureSize);
+                            SHA1_HASH_SIZE);
+                HMAC_Final(&pSession->signingContext,
+                           &pOutput->fromCloseSession.signatures[SHA1_HASH_SIZE], &signatureSize);
                 if (signatureSize != SHA1_HASH_SIZE) {
                     status = FwdLockConv_Status_ProgramError;
                 } else {
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c
index 98284e72..dacf00e 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c
@@ -114,7 +114,7 @@
 }
 
 /**
- * Finds the file session associated to the given file descriptor.
+ * Finds the file session associated with the given file descriptor.
  *
  * @param[in] fileDesc A file descriptor.
  *
@@ -389,7 +389,7 @@
                 result = FALSE;
             } else {
                 ssize_t numBytesRead;
-                size_t signatureSize = SHA1_HASH_SIZE;
+                unsigned int signatureSize = SHA1_HASH_SIZE;
                 while ((numBytesRead =
                         read(pSession->fileDesc, pData->buffer, SIG_CALC_BUFFER_SIZE)) > 0) {
                     HMAC_Update(&pSession->signingContext, pData->buffer, (size_t)numBytesRead);
@@ -399,7 +399,7 @@
                 } else {
                     HMAC_Final(&pSession->signingContext, pData->signature, &signatureSize);
                     assert(signatureSize == SHA1_HASH_SIZE);
-                    result = memcmp(pData->signature, pSession->dataSignature, signatureSize) == 0;
+                    result = memcmp(pData->signature, pSession->dataSignature, SHA1_HASH_SIZE) == 0;
                 }
                 HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL);
                 (void)lseek64(pSession->fileDesc, pSession->dataOffset + pSession->filePos,
@@ -419,16 +419,16 @@
     } else {
         FwdLockFile_Session_t *pSession = sessionPtrs[sessionId];
         unsigned char signature[SHA1_HASH_SIZE];
-        size_t signatureSize = SHA1_HASH_SIZE;
+        unsigned int signatureSize = SHA1_HASH_SIZE;
         HMAC_Update(&pSession->signingContext, pSession->topHeader, TOP_HEADER_SIZE);
         HMAC_Update(&pSession->signingContext, (unsigned char *)pSession->pContentType,
                     pSession->contentTypeLength);
         HMAC_Update(&pSession->signingContext, pSession->pEncryptedSessionKey,
                     pSession->encryptedSessionKeyLength);
-        HMAC_Update(&pSession->signingContext, pSession->dataSignature, signatureSize);
+        HMAC_Update(&pSession->signingContext, pSession->dataSignature, SHA1_HASH_SIZE);
         HMAC_Final(&pSession->signingContext, signature, &signatureSize);
         assert(signatureSize == SHA1_HASH_SIZE);
-        result = memcmp(signature, pSession->headerSignature, signatureSize) == 0;
+        result = memcmp(signature, pSession->headerSignature, SHA1_HASH_SIZE) == 0;
         HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL);
     }
     return result;
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index b8e9384..7269a71 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -84,9 +84,19 @@
     public static final int JPEG = 0x100;
 
     /**
+     * Raw bayer format used for images, which is 10 bit precision samples
+     * stored in 16 bit words. The filter pattern is RGGB. Whether this format
+     * is supported by the camera hardware can be determined by
+     * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
+     *
+     * @hide
+     */
+    public static final int BAYER_RGGB = 0x200;
+
+    /**
      * Use this function to retrieve the number of bits per pixel of an
      * ImageFormat.
-     * 
+     *
      * @param format
      * @return the number of bits per pixel of the given format or -1 if the
      *         format doesn't exist or is not supported.
@@ -103,6 +113,8 @@
                 return 12;
             case NV21:
                 return 12;
+            case BAYER_RGGB:
+                return 16;
         }
         return -1;
     }
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 1647ff3..d62fd67 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -187,6 +187,25 @@
         return nativeGetTimestamp();
     }
 
+    /**
+     * release() frees all the buffers and puts the SurfaceTexture into the
+     * 'abandoned' state. Once put in this state the SurfaceTexture can never
+     * leave it. When in the 'abandoned' state, all methods of the
+     * ISurfaceTexture interface will fail with the NO_INIT error.
+     *
+     * Note that while calling this method causes all the buffers to be freed
+     * from the perspective of the the SurfaceTexture, if there are additional
+     * references on the buffers (e.g. if a buffer is referenced by a client or
+     * by OpenGL ES as a texture) then those buffer will remain allocated.
+     *
+     * Always call this method when you are done with SurfaceTexture. Failing
+     * to do so may delay resource deallocation for a significant amount of
+     * time.
+     */
+    public void release() {
+        nativeRelease();
+    }
+
     protected void finalize() throws Throwable {
         try {
             nativeFinalize();
@@ -232,6 +251,7 @@
     private native void nativeSetDefaultBufferSize(int width, int height);
     private native void nativeUpdateTexImage();
     private native int nativeGetQueuedCount();
+    private native void nativeRelease();
 
     /*
      * We use a class initializer to allow the native code to cache some
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 48483fd..b661496 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -573,6 +573,9 @@
     static const char PIXEL_FORMAT_RGB565[];
     static const char PIXEL_FORMAT_RGBA8888[];
     static const char PIXEL_FORMAT_JPEG[];
+    // Raw bayer format used for images, which is 10 bit precision samples
+    // stored in 16 bit words. The filter pattern is RGGB.
+    static const char PIXEL_FORMAT_BAYER_RGGB[];
 
     // Values for focus mode settings.
     // Auto-focus mode. Applications should call
diff --git a/include/media/stagefright/MediaBuffer.h b/include/media/stagefright/MediaBuffer.h
index c1c4f94..3d79596 100644
--- a/include/media/stagefright/MediaBuffer.h
+++ b/include/media/stagefright/MediaBuffer.h
@@ -25,6 +25,7 @@
 
 namespace android {
 
+struct ABuffer;
 class GraphicBuffer;
 class MediaBuffer;
 class MediaBufferObserver;
@@ -51,6 +52,8 @@
 
     MediaBuffer(const sp<GraphicBuffer>& graphicBuffer);
 
+    MediaBuffer(const sp<ABuffer> &buffer);
+
     // Decrements the reference count and returns the buffer to its
     // associated MediaBufferGroup if the reference count drops to 0.
     void release();
@@ -100,6 +103,7 @@
     void *mData;
     size_t mSize, mRangeOffset, mRangeLength;
     sp<GraphicBuffer> mGraphicBuffer;
+    sp<ABuffer> mBuffer;
 
     bool mOwnsData;
 
diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp
index 251615d..51b96c1 100644
--- a/libs/camera/CameraParameters.cpp
+++ b/libs/camera/CameraParameters.cpp
@@ -151,6 +151,7 @@
 const char CameraParameters::PIXEL_FORMAT_RGB565[] = "rgb565";
 const char CameraParameters::PIXEL_FORMAT_RGBA8888[] = "rgba8888";
 const char CameraParameters::PIXEL_FORMAT_JPEG[] = "jpeg";
+const char CameraParameters::PIXEL_FORMAT_BAYER_RGGB[] = "bayer-rggb";
 
 // Values for focus mode settings.
 const char CameraParameters::FOCUS_MODE_AUTO[] = "auto";
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 4f51f03..1a036ee 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -910,6 +910,7 @@
     Mutex::Autolock lock(mMutex);
     freeAllBuffers();
     mAbandoned = true;
+    mCurrentTextureBuf.clear();
     mDequeueCondition.signal();
 }
 
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 731d1f3..e7a306b 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1802,36 +1802,20 @@
 
     /**
      * @hide
-     * FIXME to be changed to address Neel's comments
-     * Force a refresh of the remote control client associated with the event receiver.
+     * Notifies the users of the associated remote control client that the information to display
+     * has changed.
      * @param eventReceiver
      */
-    public void refreshRemoteControlDisplay(ComponentName eventReceiver) {
+    public void notifyRemoteControlInformationChanged(ComponentName eventReceiver) {
         IAudioService service = getService();
         try {
-            service.refreshRemoteControlDisplay(eventReceiver);
+            service.notifyRemoteControlInformationChanged(eventReceiver);
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in refreshRemoteControlDisplay"+e);
         }
     }
 
     /**
-     * @hide
-     * FIXME API to be used by implementors of remote controls, not a candidate for SDK
-     */
-    public void registerRemoteControlObserver() {
-
-    }
-
-    /**
-     * @hide
-     * FIXME API to be used by implementors of remote controls, not a candidate for SDK
-     */
-    public void unregisterRemoteControlObserver() {
-
-    }
-
-    /**
      *  @hide
      *  Reload audio settings. This method is called by Settings backup
      *  agent when audio settings are restored and causes the AudioService
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index cd55b0e..bf1585d 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -3200,8 +3200,8 @@
         }
     }
 
-    /** see AudioManager.refreshRemoteControlDisplay(ComponentName er) */
-    public void refreshRemoteControlDisplay(ComponentName eventReceiver) {
+    /** see AudioManager.notifyRemoteControlInformationChanged(ComponentName er) */
+    public void notifyRemoteControlInformationChanged(ComponentName eventReceiver) {
         synchronized(mAudioFocusLock) {
             synchronized(mRCStack) {
                 // only refresh if the eventReceiver is at the top of the stack
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 1a05f152..9afe553 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -93,7 +93,7 @@
     void registerRemoteControlClient(in ComponentName eventReceiver,
            in IRemoteControlClient rcClient, in String callingPackageName);
 
-    void refreshRemoteControlDisplay(in ComponentName eventReceiver);
+    void notifyRemoteControlInformationChanged(in ComponentName eventReceiver);
 
     void startBluetoothSco(IBinder cb);
 
diff --git a/media/libstagefright/MediaBuffer.cpp b/media/libstagefright/MediaBuffer.cpp
index a8fadf2..0b14f1e 100644
--- a/media/libstagefright/MediaBuffer.cpp
+++ b/media/libstagefright/MediaBuffer.cpp
@@ -21,6 +21,7 @@
 #include <pthread.h>
 #include <stdlib.h>
 
+#include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MetaData.h>
@@ -70,6 +71,20 @@
       mOriginal(NULL) {
 }
 
+MediaBuffer::MediaBuffer(const sp<ABuffer> &buffer)
+    : mObserver(NULL),
+      mNextBuffer(NULL),
+      mRefCount(0),
+      mData(buffer->data()),
+      mSize(buffer->size()),
+      mRangeOffset(0),
+      mRangeLength(mSize),
+      mBuffer(buffer),
+      mOwnsData(false),
+      mMetaData(new MetaData),
+      mOriginal(NULL) {
+}
+
 void MediaBuffer::release() {
     if (mObserver == NULL) {
         CHECK_EQ(mRefCount, 0);
diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
index 07a9eb8..887fe7c 100644
--- a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
+++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
@@ -47,6 +47,8 @@
     delete mDelegate;
     mDelegate = NULL;
 
+    clearDRMState_l();
+
     if (mDrmManagerClient != NULL) {
         delete mDrmManagerClient;
         mDrmManagerClient = NULL;
@@ -116,8 +118,6 @@
     // mURI.clear();
 
     mIOResult = err;
-
-    clearDRMState_l();
 }
 
 void ChromiumHTTPDataSource::disconnect() {
@@ -251,8 +251,6 @@
     // mURI.clear();
 
     mCondition.broadcast();
-
-    clearDRMState_l();
 }
 
 sp<DecryptHandle> ChromiumHTTPDataSource::DrmInitialization() {
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
index eb10ab7..26c3eda 100644
--- a/media/libstagefright/chromium_http/support.cpp
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -183,19 +183,19 @@
 
 void SfDelegate::OnReceivedRedirect(
             net::URLRequest *request, const GURL &new_url, bool *defer_redirect) {
-    MY_LOGI("OnReceivedRedirect");
+    MY_LOGV("OnReceivedRedirect");
 }
 
 void SfDelegate::OnAuthRequired(
             net::URLRequest *request, net::AuthChallengeInfo *auth_info) {
-    MY_LOGI("OnAuthRequired");
+    MY_LOGV("OnAuthRequired");
 
     inherited::OnAuthRequired(request, auth_info);
 }
 
 void SfDelegate::OnCertificateRequested(
             net::URLRequest *request, net::SSLCertRequestInfo *cert_request_info) {
-    MY_LOGI("OnCertificateRequested");
+    MY_LOGV("OnCertificateRequested");
 
     inherited::OnCertificateRequested(request, cert_request_info);
 }
@@ -208,7 +208,7 @@
 }
 
 void SfDelegate::OnGetCookies(net::URLRequest *request, bool blocked_by_policy) {
-    MY_LOGI("OnGetCookies");
+    MY_LOGV("OnGetCookies");
 }
 
 void SfDelegate::OnSetCookie(
@@ -216,7 +216,7 @@
         const std::string &cookie_line,
         const net::CookieOptions &options,
         bool blocked_by_policy) {
-    MY_LOGI("OnSetCookie");
+    MY_LOGV("OnSetCookie");
 }
 
 void SfDelegate::OnResponseStarted(net::URLRequest *request) {
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 2578d2d..f67cdac 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -617,23 +617,32 @@
             goto rinse_repeat;
         }
 
-        if (!mPlaylist->isComplete()
-                && mSeqNumber > lastSeqNumberInPlaylist
-                && mNumRetries < kMaxNumRetries) {
+        if (!mPlaylist->isComplete() && mNumRetries < kMaxNumRetries) {
             ++mNumRetries;
 
-            mLastPlaylistFetchTimeUs = -1;
-            postMonitorQueue(3000000ll);
+            if (mSeqNumber > lastSeqNumberInPlaylist) {
+                mLastPlaylistFetchTimeUs = -1;
+                postMonitorQueue(3000000ll);
+                return;
+            }
+
+            // we've missed the boat, let's start from the lowest sequence
+            // number available and signal a discontinuity.
+
+            LOGI("We've missed the boat, restarting playback.");
+            mSeqNumber = lastSeqNumberInPlaylist;
+            explicitDiscontinuity = true;
+
+            // fall through
+        } else {
+            LOGE("Cannot find sequence number %d in playlist "
+                 "(contains %d - %d)",
+                 mSeqNumber, firstSeqNumberInPlaylist,
+                 firstSeqNumberInPlaylist + mPlaylist->size() - 1);
+
+            mDataSource->queueEOS(ERROR_END_OF_STREAM);
             return;
         }
-
-        LOGE("Cannot find sequence number %d in playlist "
-             "(contains %d - %d)",
-             mSeqNumber, firstSeqNumberInPlaylist,
-             firstSeqNumberInPlaylist + mPlaylist->size() - 1);
-
-        mDataSource->queueEOS(ERROR_END_OF_STREAM);
-        return;
     }
 
     mNumRetries = 0;
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index 59de17e..2e66a2c 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -105,12 +105,10 @@
             int64_t timeUs;
             CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
 
-            MediaBuffer *mediaBuffer = new MediaBuffer(buffer->size());
+            MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
+
             mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
 
-            // hexdump(buffer->data(), buffer->size());
-
-            memcpy(mediaBuffer->data(), buffer->data(), buffer->size());
             *out = mediaBuffer;
             return OK;
         }
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index a02591f..4ecb92f 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -628,14 +628,12 @@
 
         updateNormalPlayTime_l(buffer);
 
-        MediaBuffer *mediaBuffer = new MediaBuffer(buffer->size());
-
         int64_t timeUs;
         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
 
+        MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
         mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
 
-        memcpy(mediaBuffer->data(), buffer->data(), buffer->size());
         *out = mediaBuffer;
 
         mBuffers.erase(mBuffers.begin());
diff --git a/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml b/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
index 3668b8c..7dfa53e 100644
--- a/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
+++ b/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
@@ -18,10 +18,20 @@
  */
 -->
 
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="fill_parent" 
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent" 
+              android:layout_height="match_parent"
+              android:orientation="vertical"
+              android:padding="16dp" >
+
+    <ScrollView 
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:layout_width="match_parent">
+        <LinearLayout
+                android:orientation="vertical"
                 android:layout_height="wrap_content"
-                android:padding="16dp" >
+                android:layout_width="match_parent">
 
     <TextView android:id="@+id/confirm_text"
               android:layout_width="match_parent" 
@@ -63,13 +73,21 @@
               android:layout_marginLeft="30dp"
               android:layout_below="@id/enc_password"
               android:layout_marginBottom="30dp" />
+        </LinearLayout>
+    </ScrollView>
+
+    <LinearLayout android:orientation="horizontal"
+                  android:layout_height="wrap_content"
+                  android:layout_width="match_parent"
+                  android:layout_gravity="bottom">
 
     <Button android:id="@+id/button_allow"
             android:filterTouchesWhenObscured="true"
             android:text="@string/allow_backup_button_label"
             android:layout_below="@id/package_name"
             android:layout_height="wrap_content"
-            android:layout_width="wrap_content" />
+            android:layout_width="0dp"
+            android:layout_weight="1" />
 
     <Button android:id="@+id/button_deny"
             android:text="@string/deny_backup_button_label"
@@ -77,6 +95,9 @@
             android:layout_toRightOf="@id/button_allow"
             android:layout_alignTop="@id/button_allow"
             android:layout_height="wrap_content"
-            android:layout_width="wrap_content" />
+            android:layout_width="0dp"
+            android:layout_weight="1" />
 
-</RelativeLayout>
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml b/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
index 38fcc49..4927cbb 100644
--- a/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
+++ b/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
@@ -18,65 +18,86 @@
  */
 -->
 
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="fill_parent" 
-                android:layout_height="wrap_content"
-                android:padding="16dp" >
-
-    <TextView android:id="@+id/confirm_text"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="match_parent" 
-              android:layout_height="wrap_content"
-              android:layout_marginBottom="30dp"
-              android:text="@string/restore_confirm_text" />
+              android:layout_height="match_parent"
+              android:orientation="vertical"
+              android:padding="16dp" >
 
-    <TextView android:id="@+id/password_desc"
-              android:layout_below="@id/confirm_text"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:layout_marginBottom="10dp"
-              android:text="@string/current_password_text" />
+    <ScrollView 
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:layout_width="match_parent">
+        <LinearLayout
+                android:orientation="vertical"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent">
 
-    <EditText android:id="@+id/password"
-              android:layout_below="@id/password_desc"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:layout_marginBottom="30dp"
-              android:password="true" />
+        <TextView android:id="@+id/confirm_text"
+                  android:layout_width="match_parent" 
+                  android:layout_height="wrap_content"
+                  android:layout_marginBottom="30dp"
+                  android:text="@string/restore_confirm_text" />
 
-    <TextView android:id="@+id/enc_password_desc"
-              android:layout_below="@id/password"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:layout_marginBottom="10dp"
-              android:text="@string/restore_enc_password_text" />
+        <TextView android:id="@+id/password_desc"
+                  android:layout_below="@id/confirm_text"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:layout_marginBottom="10dp"
+                  android:text="@string/current_password_text" />
 
-    <EditText android:id="@+id/enc_password"
-              android:layout_below="@id/enc_password_desc"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:layout_marginBottom="30dp"
-              android:password="true" />
+        <EditText android:id="@+id/password"
+                  android:layout_below="@id/password_desc"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:layout_marginBottom="30dp"
+                  android:password="true" />
 
-    <TextView android:id="@+id/package_name"
-              android:layout_width="match_parent"
-              android:layout_height="20dp"
-              android:layout_marginLeft="30dp"
-              android:layout_below="@id/enc_password"
-              android:layout_marginBottom="30dp" />
+        <TextView android:id="@+id/enc_password_desc"
+                  android:layout_below="@id/password"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:layout_marginBottom="10dp"
+                  android:text="@string/restore_enc_password_text" />
 
-    <Button android:id="@+id/button_allow"
-            android:filterTouchesWhenObscured="true"
-            android:text="@string/allow_restore_button_label"
-            android:layout_below="@id/package_name"
-            android:layout_height="wrap_content"
-            android:layout_width="wrap_content" />
+        <EditText android:id="@+id/enc_password"
+                  android:layout_below="@id/enc_password_desc"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:layout_marginBottom="30dp"
+                  android:password="true" />
 
-    <Button android:id="@+id/button_deny"
-            android:text="@string/deny_restore_button_label"
-            android:layout_below="@id/package_name"
-            android:layout_toRightOf="@id/button_allow"
-            android:layout_alignTop="@id/button_allow"
-            android:layout_height="wrap_content"
-            android:layout_width="wrap_content" />
+        <TextView android:id="@+id/package_name"
+                  android:layout_width="match_parent"
+                  android:layout_height="20dp"
+                  android:layout_marginLeft="30dp"
+                  android:layout_below="@id/enc_password"
+                  android:layout_marginBottom="10dp" />
+        </LinearLayout>
+    </ScrollView>
 
-</RelativeLayout>
+    <LinearLayout android:orientation="horizontal"
+                  android:layout_height="wrap_content"
+                  android:layout_width="match_parent"
+                  android:layout_gravity="bottom">
+
+        <Button android:id="@+id/button_allow"
+                android:filterTouchesWhenObscured="true"
+                android:text="@string/allow_restore_button_label"
+                android:layout_below="@id/package_name"
+                android:layout_height="wrap_content"
+                android:layout_width="0dp"
+                android:layout_weight="1" />
+
+        <Button android:id="@+id/button_deny"
+                android:text="@string/deny_restore_button_label"
+                android:layout_below="@id/package_name"
+                android:layout_toRightOf="@id/button_allow"
+                android:layout_alignTop="@id/button_allow"
+                android:layout_height="wrap_content"
+                android:layout_width="0dp"
+                android:layout_weight="1" />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar.xml b/packages/SystemUI/res/layout-sw600dp/status_bar.xml
index 55e57ab..a204f17 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar.xml
@@ -35,18 +35,6 @@
             android:clipChildren="false"
             >
 
-            <ImageView android:id="@+id/clear_all_button"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:layout_alignParentRight="true"
-                android:layout_marginTop="1dp"
-                android:layout_marginRight="20dp"
-                android:paddingLeft="15dp"
-                android:paddingRight="15dp"
-                android:src="@drawable/ic_notify_clear"
-                android:visibility="invisible"
-                />
-
             <!-- notification icons & panel access -->
             <include layout="@layout/status_bar_notification_area" 
                 android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel.xml
index 9f11e08..1641c70 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel.xml
@@ -24,6 +24,18 @@
     android:gravity="right"
     >
 
+    <ImageView android:id="@+id/clear_all_button"
+        android:layout_width="wrap_content"
+        android:layout_height="@*android:dimen/status_bar_height"
+        android:layout_alignParentRight="true"
+        android:layout_alignParentBottom="true"
+        android:layout_marginRight="20dp"
+        android:paddingLeft="15dp"
+        android:paddingRight="15dp"
+        android:src="@drawable/ic_notify_clear"
+        android:visibility="invisible"
+        />
+
     <RelativeLayout
         android:id="@+id/content_parent"
         android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index d97b90f..1446099 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -135,4 +135,8 @@
     <skip />
     <!-- no translation found for gps_notification_found_text (4619274244146446464) -->
     <skip />
+
+    <!-- in Japanese the day of week should follow the date -->
+    <string name="status_bar_date_formatter">%2$s\n%1$s</string>
+
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 2b3118d..03b82fd 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -41,8 +41,9 @@
     <!-- Title shown in recents popup for inspecting an application's properties -->
     <string name="status_bar_recent_inspect_item_title">Inspect</string>
 
-
-
+    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default,
+         but this may be overridden on a per-locale basis if necessary. -->
+    <string name="status_bar_date_formatter">%1$s\n%2$s</string>
 
     <!-- The label in the bar at the top of the status bar when there are no notifications
          showing.  [CHAR LIMIT=40]-->
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 7bb8277..7d1aedc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -87,6 +87,9 @@
     static final boolean SPEW = false;
     public static final boolean DEBUG = false;
 
+    // additional instrumentation for testing purposes; intended to be left on during development
+    public static final boolean CHATTY = DEBUG || true;
+
     public static final String ACTION_STATUSBAR_START
             = "com.android.internal.policy.statusbar.START";
 
@@ -1261,6 +1264,10 @@
     }
 
     void prepareTracking(int y, boolean opening) {
+        if (CHATTY) {
+            Slog.d(TAG, "panel: beginning to track the user's touch, y=" + y + " opening=" + opening);
+        }
+
         mTracking = true;
         mVelocityTracker = VelocityTracker.obtain();
         if (opening) {
@@ -1290,6 +1297,10 @@
     }
 
     void performFling(int y, float vel, boolean always) {
+        if (CHATTY) {
+            Slog.d(TAG, "panel: will fling, y=" + y + " vel=" + vel);
+        }
+
         mAnimatingReveal = false;
 
         mAnimY = y;
@@ -1352,6 +1363,12 @@
         if (SPEW) {
             Slog.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled="
                 + mDisabled);
+        } else if (CHATTY) {
+            if (event.getAction() == MotionEvent.ACTION_DOWN) {
+                Slog.d(TAG, String.format(
+                            "panel: ACTION_DOWN at (%f, %f) mDisabled=0x%08x",
+                            event.getRawX(), event.getRawY(), mDisabled));
+            }
         }
 
         if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
@@ -1873,7 +1890,7 @@
     }
 
     void updateExpandedSize() {
-        if (mExpandedDialog != null) {
+        if (mExpandedDialog != null && mExpandedParams != null && mDisplaySize != null) {
             mExpandedParams.width = mDisplaySize.x;
             mExpandedParams.height = getExpandedHeight(mDisplaySize.y);
             if (!mExpandedVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index 6ab03e1..a171514 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -28,6 +28,8 @@
 import android.view.View;
 import android.view.ViewParent;
 
+import com.android.systemui.R;
+
 import java.util.Date;
 
 public final class DateView extends TextView {
@@ -90,7 +92,7 @@
         Date now = new Date();
         CharSequence dow = DateFormat.format("EEEE", now);
         CharSequence date = DateFormat.getMediumDateFormat(getContext()).format(now);
-        setText(dow + "\n" + date);
+        setText(context.getString(R.string.status_bar_date_formatter, dow, date));
     }
 
     private boolean isVisible() {
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 f32c602..97b6298 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -61,6 +61,7 @@
     // debug
     static final String TAG = "StatusBar.NetworkController";
     static final boolean DEBUG = false;
+    static final boolean CHATTY = true; // additional diagnostics, but not logspew
 
     // telephony
     boolean mHspaDataDistinguishable;
@@ -286,7 +287,7 @@
 
         @Override
         public void onDataConnectionStateChanged(int state, int networkType) {
-            if (DEBUG) {
+            if (DEBUG || CHATTY) {
                 Slog.d(TAG, "onDataConnectionStateChanged: state=" + state
                         + " type=" + networkType);
             }
@@ -682,10 +683,19 @@
     // ===== Full or limited Internet connectivity ==================================
 
     private void updateConnectivity(Intent intent) {
+        if (CHATTY) {
+            Slog.d(TAG, "updateConnectivity: intent=" + intent);
+        }
+
         NetworkInfo info = (NetworkInfo)(intent.getParcelableExtra(
                 ConnectivityManager.EXTRA_NETWORK_INFO));
         int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
 
+        if (CHATTY) {
+            Slog.d(TAG, "updateConnectivity: networkInfo=" + info);
+            Slog.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus);
+        }
+
         int inetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
 
         switch (info.getType()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
index 100ed55..fd58174 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
@@ -22,6 +22,7 @@
 import android.util.AttributeSet;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
 import android.view.View;
 import android.widget.ImageView;
 
@@ -48,6 +49,9 @@
     private boolean mScreenLocked = false;
     private boolean mHardKeyboardAvailable;
 
+    // Please refer to InputMethodManagerService.TAG_TRY_SUPPRESSING_IME_SWITCHER
+    private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
+
     public InputMethodButton(Context context, AttributeSet attrs) {
         super(context, attrs);
 
@@ -64,10 +68,49 @@
         refreshStatusIcon();
     }
 
-    // Display IME switcher icon only when all of the followings are true:
-    // * There is only one enabled IME on the device.  (Note that the IME should be the system IME)
-    // * There are no explicitly enabled (by the user) subtypes of the IME, or the IME doesn't have
-    // its subtypes at all
+    // Refer to InputMethodManagerService.needsToShowImeSwitchOngoingNotification()
+    private boolean needsToShowIMEButtonWhenVisibilityAuto() {
+        List<InputMethodInfo> imis = mImm.getEnabledInputMethodList();
+        final int N = imis.size();
+        if (N > 2) return true;
+        if (N < 1) return false;
+        int nonAuxCount = 0;
+        int auxCount = 0;
+        InputMethodSubtype nonAuxSubtype = null;
+        InputMethodSubtype auxSubtype = null;
+        for(int i = 0; i < N; ++i) {
+            final InputMethodInfo imi = imis.get(i);
+            final List<InputMethodSubtype> subtypes = mImm.getEnabledInputMethodSubtypeList(
+                    imi, true);
+            final int subtypeCount = subtypes.size();
+            if (subtypeCount == 0) {
+                ++nonAuxCount;
+            } else {
+                for (int j = 0; j < subtypeCount; ++j) {
+                    final InputMethodSubtype subtype = subtypes.get(j);
+                    if (!subtype.isAuxiliary()) {
+                        ++nonAuxCount;
+                        nonAuxSubtype = subtype;
+                    } else {
+                        ++auxCount;
+                        auxSubtype = subtype;
+                    }
+                }
+            }
+        }
+        if (nonAuxCount > 1 || auxCount > 1) {
+            return true;
+        } else if (nonAuxCount == 1 && auxCount == 1) {
+            if (nonAuxSubtype != null && auxSubtype != null
+                    && nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
+                    && nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
+                return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
     private boolean needsToShowIMEButton() {
         if (!mShowButton || mScreenLocked) return false;
 
@@ -75,13 +118,10 @@
             return true;
         }
 
-        List<InputMethodInfo> imis = mImm.getEnabledInputMethodList();
-        final int size = imis.size();
         final int visibility = loadInputMethodSelectorVisibility();
         switch (visibility) {
             case ID_IME_BUTTON_VISIBILITY_AUTO:
-                return size > 1 || (size == 1
-                        && mImm.getEnabledInputMethodSubtypeList(imis.get(0), false).size() > 1);
+                return needsToShowIMEButtonWhenVisibilityAuto();
             case ID_IME_BUTTON_VISIBILITY_ALWAYS_SHOW:
                 return true;
             case ID_IME_BUTTON_VISIBILITY_ALWAYS_HIDE:
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 74dbfef..d9cb4e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -40,6 +40,7 @@
     final static int PANEL_FADE_DURATION = 150;
 
     boolean mShowing;
+    boolean mHasClearableNotifications = false;
     int mNotificationCount = 0;
     NotificationPanelTitle mTitleArea;
     View mSettingsButton;
@@ -50,6 +51,7 @@
     View mSettingsView;
     ViewGroup mContentParent;
     TabletStatusBar mBar;
+    View mClearButton;
 
     // amount to slide mContentParent down by when mContentFrame is missing
     float mContentFrameMissingTranslation;
@@ -84,14 +86,27 @@
 
         mNotificationScroller = findViewById(R.id.notification_scroller);
         mContentFrame = (ViewGroup)findViewById(R.id.content_frame);
-        mContentFrameMissingTranslation =
-            mContentFrame.getBackground().getMinimumHeight() + 10;
+        mContentFrameMissingTranslation = 0; // not needed with current assets
+
+        // the "X" that appears in place of the clock when the panel is showing notifications
+        mClearButton = findViewById(R.id.clear_all_button);
+        mClearButton.setOnClickListener(mClearButtonListener);
 
         mShowing = false;
 
         setContentFrameVisible(mNotificationCount > 0, false);
     }
 
+    private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
+        public void onClick(View v) {
+            mBar.clearAll();
+        }
+    };
+
+    public View getClearButton() {
+        return mClearButton;
+    }
+
     public void show(boolean show, boolean animate) {
         if (show && !mShowing) {
             setContentFrameVisible(mSettingsView != null || mNotificationCount > 0, false);
@@ -264,12 +279,16 @@
         if (mBar != null) {
             final boolean showX 
                 = (isShowing()
-                        && mNotificationScroller.getVisibility() == View.VISIBLE 
-                        && mNotificationCount > 0);
-            mBar.getClearButton().setVisibility(showX ? View.VISIBLE : View.INVISIBLE);
+                        && mHasClearableNotifications
+                        && mNotificationScroller.getVisibility() == View.VISIBLE);
+            getClearButton().setVisibility(showX ? View.VISIBLE : View.INVISIBLE);
         }
     }
 
+    public void setClearable(boolean clearable) {
+        mHasClearableNotifications = clearable;
+    }
+
     public void updatePanelModeButtons() {
         final boolean settingsVisible = (mSettingsView != null);
         mSettingsButton.setVisibility(!settingsVisible ? View.VISIBLE : View.INVISIBLE);
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 dc7e3137..7f56d45 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -122,7 +122,6 @@
     View mNotificationTrigger;
     NotificationIconArea mNotificationIconArea;
     ViewGroup mNavigationArea;
-    View mClearButton;
 
     boolean mNotificationDNDMode;
     NotificationData.Entry mNotificationDNDDummyEntry;
@@ -453,10 +452,6 @@
         // the more notifications icon
         mNotificationIconArea = (NotificationIconArea)sb.findViewById(R.id.notificationIcons);
 
-        // the "X" that appears in place of the clock when the panel is showing notifications
-        mClearButton = sb.findViewById(R.id.clear_all_button);
-        mClearButton.setOnClickListener(mClearButtonListener);
-
         // where the icons go
         mIconLayout = (NotificationIconArea.IconLayout) sb.findViewById(R.id.icons);
         mIconLayout.setOnTouchListener(new NotificationIconTouchListener());
@@ -587,21 +582,6 @@
         return sb;
     }
 
-    private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
-        public void onClick(View v) {
-            try {
-                mBarService.onClearAllNotifications();
-            } catch (RemoteException ex) {
-                // system process is dead if we're here.
-            }
-            animateCollapse();
-        }
-    };
-
-    public View getClearButton() {
-        return mClearButton;
-    }
-
     public int getStatusBarHeight() {
         return mHeightReceiver.getHeight();
     }
@@ -1097,7 +1077,10 @@
 
         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();
@@ -1204,6 +1187,9 @@
     }
 
     private void setAreThereNotifications() {
+        if (mNotificationPanel != null) {
+            mNotificationPanel.setClearable(mNotificationData.hasClearableItems());
+        }
     }
 
     /**
@@ -1606,6 +1592,10 @@
             }
 
             return;
+        } else if (0 != (mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) {
+            // if icons are disabled but we're not in DND mode, this is probably Setup and we should
+            // just leave the area totally empty
+            return;
         }
 
         int N = mNotificationData.size();
@@ -1775,6 +1765,15 @@
         return true;
     }
 
+    public void clearAll() {
+        try {
+            mBarService.onClearAllNotifications();
+        } catch (RemoteException ex) {
+            // system process is dead if we're here.
+        }
+        animateCollapse();
+    }
+
     public void userActivity() {
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
index dff1f6a..7d11251 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
@@ -94,6 +94,11 @@
         mHandler = h;
     }
 
+    /**
+     * Let the status bar know that if you tap on ignore while panel is showing, don't do anything.
+     * 
+     * Debounces taps on, say, a popup's trigger when the popup is already showing.
+     */
     public void setIgnoreChildren(int index, View ignore, View panel) {
         mIgnoreChildren[index] = ignore;
         mPanels[index] = panel;
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index bd5f739..8e062b7 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -5,7 +5,6 @@
     <application android:label="VpnDialogs"
             android:allowBackup="false" >
         <activity android:name=".ConfirmDialog"
-                android:permission="android.permission.VPN"
                 android:theme="@style/transparent">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
index 40c0a02..d668e98 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
@@ -79,7 +79,7 @@
             mDataTransmitted = (TextView) view.findViewById(R.id.data_transmitted);
             mDataReceived = (TextView) view.findViewById(R.id.data_received);
 
-            if (mConfig.packagz.equals(VpnConfig.LEGACY_VPN)) {
+            if (mConfig.user.equals(VpnConfig.LEGACY_VPN)) {
                 mDialog = new AlertDialog.Builder(this)
                         .setIcon(android.R.drawable.ic_dialog_info)
                         .setTitle(R.string.legacy_title)
@@ -89,7 +89,7 @@
                         .create();
             } else {
                 PackageManager pm = getPackageManager();
-                ApplicationInfo app = pm.getApplicationInfo(mConfig.packagz, 0);
+                ApplicationInfo app = pm.getApplicationInfo(mConfig.user, 0);
                 mDialog = new AlertDialog.Builder(this)
                         .setIcon(app.loadIcon(pm))
                         .setTitle(app.loadLabel(pm))
@@ -131,7 +131,7 @@
             if (which == AlertDialog.BUTTON_POSITIVE) {
                 mConfig.configureIntent.send();
             } else if (which == AlertDialog.BUTTON_NEUTRAL) {
-                mService.prepareVpn(mConfig.packagz, VpnConfig.LEGACY_VPN);
+                mService.prepareVpn(mConfig.user, VpnConfig.LEGACY_VPN);
             }
         } catch (Exception e) {
             Log.e(TAG, "onClick", e);
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
index 7a14480..21a8c14 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
@@ -232,10 +232,14 @@
      * @param resId resource id of the message
      */
     public void setCarrierHelpText(int resId) {
-        mCarrierHelpText = getContext().getText(resId);
+        mCarrierHelpText = getText(resId);
         update(CARRIER_HELP_TEXT, mCarrierHelpText);
     }
 
+    private CharSequence getText(int resId) {
+        return resId == 0 ? null : getContext().getText(resId);
+    }
+
     /**
      * Unlock help message.  This is typically for help with unlock widgets, e.g. "wrong password"
      * or "try again."
@@ -244,7 +248,7 @@
      * @param lockIcon
      */
     public void setHelpMessage(int textResId, int lockIcon) {
-        mHelpMessageText = getContext().getString(textResId);
+        mHelpMessageText = getText(textResId).toString();
         update(HELP_MESSAGE_TEXT, mHelpMessageText);
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 4a14dd9..9d360ac 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -23,7 +23,9 @@
 import com.android.internal.widget.multiwaveview.MultiWaveView;
 
 import android.app.ActivityManager;
+import android.content.ActivityNotFoundException;
 import android.content.Context;
+import android.content.Intent;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.view.KeyEvent;
@@ -181,14 +183,33 @@
             UnlockWidgetCommonMethods {
 
         private final MultiWaveView mMultiWaveView;
+        private boolean mCameraDisabled;
 
         MultiWaveViewMethods(MultiWaveView multiWaveView) {
             mMultiWaveView = multiWaveView;
+            final boolean cameraDisabled = mLockPatternUtils.getDevicePolicyManager()
+                    .getCameraDisabled(null);
+            if (cameraDisabled) {
+                Log.v(TAG, "Camera disabled by Device Policy");
+                mCameraDisabled = true;
+            } else {
+                // Camera is enabled if resource is initially defined for MultiWaveView
+                // in the lockscreen layout file
+                mCameraDisabled = mMultiWaveView.getTargetResourceId()
+                        != R.array.lockscreen_targets_with_camera;
+            }
         }
 
         public void updateResources() {
-            mMultiWaveView.setTargetResources(mSilentMode ? R.array.lockscreen_targets_when_silent
-                    : R.array.lockscreen_targets_when_soundon);
+            int resId;
+            if (mCameraDisabled) {
+                // Fall back to showing ring/silence if camera is disabled by DPM...
+                resId = mSilentMode ? R.array.lockscreen_targets_when_silent
+                    : R.array.lockscreen_targets_when_soundon;
+            } else {
+                resId = R.array.lockscreen_targets_with_camera;
+            }
+            mMultiWaveView.setTargetResources(resId);
         }
 
         public void onGrabbed(View v, int handle) {
@@ -200,12 +221,19 @@
         }
 
         public void onTrigger(View v, int target) {
-            if (target == 0) { // TODO: Use resources to determine which handle was used
+            if (target == 0 || target == 1) { // 0 = unlock/portrait, 1 = unlock/landscape
                 mCallback.goToUnlockScreen();
-            } else if (target == 2) {
-                toggleRingMode();
-                mUnlockWidgetMethods.updateResources();
-                mCallback.pokeWakelock();
+            } else if (target == 2 || target == 3) { // 2 = alt/portrait, 3 = alt/landscape
+                if (!mCameraDisabled) {
+                    // Broadcast an intent to start the Camera
+                    Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null);
+                    mContext.sendOrderedBroadcast(intent, null);
+                    mCallback.goToUnlockScreen();
+                } else {
+                    toggleRingMode();
+                    mUnlockWidgetMethods.updateResources();
+                    mCallback.pokeWakelock();
+                }
             }
         }
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index b7f6adf..a2dbb78 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -113,6 +113,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
+import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
@@ -162,36 +163,39 @@
     static final int APPLICATION_LAYER = 2;
     static final int PHONE_LAYER = 3;
     static final int SEARCH_BAR_LAYER = 4;
-    static final int STATUS_BAR_SUB_PANEL_LAYER = 5;
-    static final int SYSTEM_DIALOG_LAYER = 6;
+    static final int SYSTEM_DIALOG_LAYER = 5;
     // toasts and the plugged-in battery thing
-    static final int TOAST_LAYER = 7;
+    static final int TOAST_LAYER = 6;
     // SIM errors and unlock.  Not sure if this really should be in a high layer.
-    static final int PRIORITY_PHONE_LAYER = 8;
+    static final int PRIORITY_PHONE_LAYER = 7;
     // like the ANR / app crashed dialogs
-    static final int SYSTEM_ALERT_LAYER = 9;
+    static final int SYSTEM_ALERT_LAYER = 8;
     // system-level error dialogs
-    static final int SYSTEM_ERROR_LAYER = 10;
+    static final int SYSTEM_ERROR_LAYER = 9;
     // on-screen keyboards and other such input method user interfaces go here.
-    static final int INPUT_METHOD_LAYER = 11;
+    static final int INPUT_METHOD_LAYER = 10;
     // on-screen keyboards and other such input method user interfaces go here.
-    static final int INPUT_METHOD_DIALOG_LAYER = 12;
+    static final int INPUT_METHOD_DIALOG_LAYER = 11;
     // the keyguard; nothing on top of these can take focus, since they are
     // responsible for power management when displayed.
-    static final int KEYGUARD_LAYER = 13;
-    static final int KEYGUARD_DIALOG_LAYER = 14;
+    static final int KEYGUARD_LAYER = 12;
+    static final int KEYGUARD_DIALOG_LAYER = 13;
+    static final int STATUS_BAR_SUB_PANEL_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 on-screen volume indicator and controller shown when the user
+    // changes the device volume
+    static final int VOLUME_OVERLAY_LAYER = 18;
     // the drag layer: input for drag-and-drop is associated with this window,
     // which sits above all other focusable windows
-    static final int DRAG_LAYER = 18;
+    static final int DRAG_LAYER = 19;
     // things in here CAN NOT take focus, but are shown on top of everything else.
-    static final int SYSTEM_OVERLAY_LAYER = 19;
-    static final int SECURE_SYSTEM_OVERLAY_LAYER = 20;
+    static final int SYSTEM_OVERLAY_LAYER = 20;
+    static final int SECURE_SYSTEM_OVERLAY_LAYER = 21;
     // the (mouse) pointer layer
-    static final int POINTER_LAYER = 21;
+    static final int POINTER_LAYER = 22;
 
     static final int APPLICATION_MEDIA_SUBLAYER = -2;
     static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
@@ -1057,6 +1061,8 @@
             return INPUT_METHOD_LAYER;
         case TYPE_INPUT_METHOD_DIALOG:
             return INPUT_METHOD_DIALOG_LAYER;
+        case TYPE_VOLUME_OVERLAY:
+            return VOLUME_OVERLAY_LAYER;
         case TYPE_SYSTEM_OVERLAY:
             return SYSTEM_OVERLAY_LAYER;
         case TYPE_SECURE_SYSTEM_OVERLAY:
@@ -3012,7 +3018,8 @@
         }
     }
 
-    Runnable mScreenSaverActivator = new Runnable() {
+    Runnable mScreenSaverActivator = null;
+    /*new Runnable() {
         public void run() {
             synchronized (this) {
                 if (!(mScreenSaverEnabled && mScreenOn)) {
@@ -3043,9 +3050,12 @@
             }
         }
     };
+    */
 
     // Must call while holding mLock
     private void updateScreenSaverTimeoutLocked() {
+        if (mScreenSaverActivator == null) return;
+
         synchronized (mScreenSaverActivator) {
             mHandler.removeCallbacks(mScreenSaverActivator);
             if (mScreenSaverEnabled && mScreenOn && mScreenSaverTimeout > 0) {
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index a59b6c0..30de385 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -1231,6 +1231,13 @@
         }
     }
 
+    @Override
+    public boolean isBandwidthControlEnabled() {
+        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+        return mBandwidthControlEnabled;
+    }
+
+    @Override
     public NetworkStats getNetworkStatsUidDetail(int uid) {
         if (Binder.getCallingUid() != uid) {
             mContext.enforceCallingOrSelfPermission(
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index f15eca6..4a0dcdf 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -27,6 +27,7 @@
 import android.content.pm.IPackageManager;
 import android.content.res.Configuration;
 import android.media.AudioService;
+import android.net.wifi.p2p.WifiP2pService;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -37,7 +38,6 @@
 import android.server.BluetoothA2dpService;
 import android.server.BluetoothService;
 import android.server.search.SearchManagerService;
-import android.server.WifiP2pService;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Slog;
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index e97df84..238b747 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -31,19 +31,17 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.os.Binder;
+import android.os.Bundle;
 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.text.TextUtils;
 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 {
@@ -180,7 +178,8 @@
 
     @Override
     public void getSpellCheckerService(String sciId, String locale,
-            ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener) {
+            ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener,
+            Bundle bundle) {
         if (!mSystemReady) {
             return;
         }
@@ -199,7 +198,7 @@
                 if (bindGroup != null) {
                     final InternalDeathRecipient recipient =
                             mSpellCheckerBindGroups.get(sciId).addListener(
-                                    tsListener, locale, scListener, uid);
+                                    tsListener, locale, scListener, uid, bundle);
                     if (recipient == null) {
                         if (DBG) {
                             Slog.w(TAG, "Didn't create a death recipient.");
@@ -217,7 +216,7 @@
                         try {
                             final ISpellCheckerSession session =
                                     bindGroup.mSpellChecker.getISpellCheckerSession(
-                                            recipient.mScLocale, recipient.mScListener);
+                                            recipient.mScLocale, recipient.mScListener, bundle);
                             if (session != null) {
                                 tsListener.onServiceConnected(session);
                                 return;
@@ -236,7 +235,8 @@
             }
             final long ident = Binder.clearCallingIdentity();
             try {
-                startSpellCheckerServiceInnerLocked(sci, locale, tsListener, scListener, uid);
+                startSpellCheckerServiceInnerLocked(
+                        sci, locale, tsListener, scListener, uid, bundle);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -246,13 +246,13 @@
 
     private void startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, String locale,
             ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener,
-            int uid) {
+            int uid, Bundle bundle) {
         if (DBG) {
             Slog.w(TAG, "Start spell checker session inner locked.");
         }
         final String sciId = info.getId();
         final InternalServiceConnection connection = new InternalServiceConnection(
-                sciId, locale, scListener);
+                sciId, locale, scListener, bundle);
         final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE);
         serviceIntent.setComponent(info.getComponent());
         if (DBG) {
@@ -263,7 +263,7 @@
             return;
         }
         final SpellCheckerBindGroup group = new SpellCheckerBindGroup(
-                connection, tsListener, locale, scListener, uid);
+                connection, tsListener, locale, scListener, uid, bundle);
         mSpellCheckerBindGroups.put(sciId, group);
     }
 
@@ -332,10 +332,10 @@
 
         public SpellCheckerBindGroup(InternalServiceConnection connection,
                 ITextServicesSessionListener listener, String locale,
-                ISpellCheckerSessionListener scListener, int uid) {
+                ISpellCheckerSessionListener scListener, int uid, Bundle bundle) {
             mInternalConnection = connection;
             mConnected = false;
-            addListener(listener, locale, scListener, uid);
+            addListener(listener, locale, scListener, uid, bundle);
         }
 
         public void onServiceConnected(ISpellCheckerService spellChecker) {
@@ -346,7 +346,7 @@
                 for (InternalDeathRecipient listener : mListeners) {
                     try {
                         final ISpellCheckerSession session = spellChecker.getISpellCheckerSession(
-                                listener.mScLocale, listener.mScListener);
+                                listener.mScLocale, listener.mScListener, listener.mBundle);
                         listener.mTsListener.onServiceConnected(session);
                     } catch (RemoteException e) {
                         Slog.e(TAG, "Exception in getting the spell checker session: " + e);
@@ -360,7 +360,7 @@
         }
 
         public InternalDeathRecipient addListener(ITextServicesSessionListener tsListener,
-                String locale, ISpellCheckerSessionListener scListener, int uid) {
+                String locale, ISpellCheckerSessionListener scListener, int uid, Bundle bundle) {
             if (DBG) {
                 Slog.d(TAG, "addListener: " + locale);
             }
@@ -375,7 +375,7 @@
                         }
                     }
                     recipient = new InternalDeathRecipient(
-                            this, tsListener, locale, scListener, uid);
+                            this, tsListener, locale, scListener, uid, bundle);
                     scListener.asBinder().linkToDeath(recipient, 0);
                     mListeners.add(recipient);
                 } catch(RemoteException e) {
@@ -440,11 +440,13 @@
         private final ISpellCheckerSessionListener mListener;
         private final String mSciId;
         private final String mLocale;
+        private final Bundle mBundle;
         public InternalServiceConnection(
-                String id, String locale, ISpellCheckerSessionListener listener) {
+                String id, String locale, ISpellCheckerSessionListener listener, Bundle bundle) {
             mSciId = id;
             mLocale = locale;
             mListener = listener;
+            mBundle = bundle;
         }
 
         @Override
@@ -473,14 +475,16 @@
         public final String mScLocale;
         private final SpellCheckerBindGroup mGroup;
         public final int mUid;
+        public final Bundle mBundle;
         public InternalDeathRecipient(SpellCheckerBindGroup group,
                 ITextServicesSessionListener tsListener, String scLocale,
-                ISpellCheckerSessionListener scListener, int uid) {
+                ISpellCheckerSessionListener scListener, int uid, Bundle bundle) {
             mTsListener = tsListener;
             mScListener = scListener;
             mScLocale = scLocale;
             mGroup = group;
             mUid = uid;
+            mBundle = bundle;
         }
 
         public boolean hasSpellCheckerListener(ISpellCheckerSessionListener listener) {
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index f9f63b1..242a93d 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -1592,7 +1592,10 @@
                 for (int i = scanResults.size() - 1; i >= 0; i--) {
                     ScanResult scanResult = scanResults.get(i);
 
-                    if (TextUtils.isEmpty(scanResult.capabilities)) {
+                    //A capability of [ESS] represents an open access point
+                    //that is available for an STA to connect
+                    if (scanResult.capabilities != null &&
+                            scanResult.capabilities.equals("[ESS]")) {
                         numOpenNetworks++;
                     }
                 }
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 0ad58d0..0808d5d 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -313,7 +313,7 @@
                             if (moveDelta > mTouchExplorationTapSlop) {
                                 mLastTouchExploreEvent = null;
                                 mPerformLongPressDelayed.remove();
-                               break;
+                                break;
                             }
                         }
                     } break;
@@ -388,6 +388,11 @@
                             mTouchExploreGestureInProgress = false;
                             mLastTouchExploreEvent = MotionEvent.obtain(event);
                             sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_END);
+                            final int lastAction = mPointerTracker.getLastInjectedHoverAction();
+                            if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
+                                sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT,
+                                        pointerIdBits, policyFlags);
+                            }
                             break;
                         }
 
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index ecbad09..b69cc31 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -54,7 +54,6 @@
 public class Vpn extends INetworkManagementEventObserver.Stub {
 
     private final static String TAG = "Vpn";
-    private final static String VPN = android.Manifest.permission.VPN;
 
     private final Context mContext;
     private final VpnCallback mCallback;
@@ -69,18 +68,6 @@
     }
 
     /**
-     * Protect a socket from routing changes by binding it to the given
-     * interface. The socket is NOT closed by this method.
-     *
-     * @param socket The socket to be bound.
-     * @param name The name of the interface.
-     */
-    public void protect(ParcelFileDescriptor socket, String interfaze) {
-        mContext.enforceCallingPermission(VPN, "protect");
-        jniProtect(socket.getFd(), interfaze);
-    }
-
-    /**
      * Prepare for a VPN application. This method is designed to solve
      * race conditions. It first compares the current prepared package
      * with {@code oldPackage}. If they are the same, the prepared
@@ -115,13 +102,6 @@
             throw new SecurityException("Unauthorized Caller");
         }
 
-        // Check the permission of the given package.
-        PackageManager pm = mContext.getPackageManager();
-        if (!newPackage.equals(VpnConfig.LEGACY_VPN) &&
-                pm.checkPermission(VPN, newPackage) != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException(newPackage + " does not have " + VPN);
-        }
-
         // Reset the interface and hide the notification.
         if (mInterface != null) {
             jniReset(mInterface);
@@ -130,12 +110,9 @@
             mInterface = null;
         }
 
-        // Send out the broadcast or stop LegacyVpnRunner.
+        // Revoke the connection or stop LegacyVpnRunner.
         if (!mPackage.equals(VpnConfig.LEGACY_VPN)) {
-            Intent intent = new Intent(VpnConfig.ACTION_VPN_REVOKED);
-            intent.setPackage(mPackage);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-            mContext.sendBroadcast(intent);
+            // TODO
         } else if (mLegacyVpnRunner != null) {
             mLegacyVpnRunner.exit();
             mLegacyVpnRunner = null;
@@ -147,6 +124,22 @@
     }
 
     /**
+     * Protect a socket from routing changes by binding it to the given
+     * interface. The socket is NOT closed by this method.
+     *
+     * @param socket The socket to be bound.
+     * @param name The name of the interface.
+     */
+    public void protect(ParcelFileDescriptor socket, String interfaze) throws Exception {
+        PackageManager pm = mContext.getPackageManager();
+        ApplicationInfo app = pm.getApplicationInfo(mPackage, 0);
+        if (Binder.getCallingUid() != app.uid) {
+            throw new SecurityException("Unauthorized Caller");
+        }
+        jniProtect(socket.getFd(), interfaze);
+    }
+
+    /**
      * Establish a VPN network and return the file descriptor of the VPN
      * interface. This methods returns {@code null} if the application is
      * revoked or not prepared.
@@ -155,9 +148,6 @@
      * @return The file descriptor of the VPN interface.
      */
     public synchronized ParcelFileDescriptor establish(VpnConfig config) {
-        // Check the permission of the caller.
-        mContext.enforceCallingPermission(VPN, "establish");
-
         // Check if the caller is already prepared.
         PackageManager pm = mContext.getPackageManager();
         ApplicationInfo app = null;
@@ -170,6 +160,9 @@
             return null;
         }
 
+        // Check if the service is properly declared.
+        // TODO
+
         // Load the label.
         String label = app.loadLabel(pm).toString();
 
@@ -198,6 +191,7 @@
             if (config.routes != null) {
                 jniSetRoutes(interfaze, config.routes);
             }
+            // TODO: bind the service
             if (mInterface != null && !mInterface.equals(interfaze)) {
                 jniReset(mInterface);
             }
@@ -211,23 +205,25 @@
             throw e;
         }
 
-        // Override DNS servers and search domains.
-        mCallback.override(config.dnsServers, config.searchDomains);
-
         // Fill more values.
-        config.packagz = mPackage;
+        config.user = mPackage;
         config.interfaze = mInterface;
 
-        // Show the notification!
+        // Override DNS servers and show the notification.
+        long identity = Binder.clearCallingIdentity();
+        mCallback.override(config.dnsServers, config.searchDomains);
         showNotification(config, label, bitmap);
+        Binder.restoreCallingIdentity(identity);
         return tun;
     }
 
     // INetworkManagementEventObserver.Stub
+    @Override
     public void interfaceAdded(String interfaze) {
     }
 
     // INetworkManagementEventObserver.Stub
+    @Override
     public synchronized void interfaceStatusChanged(String interfaze, boolean up) {
         if (!up && mLegacyVpnRunner != null) {
             mLegacyVpnRunner.check(interfaze);
@@ -235,23 +231,29 @@
     }
 
     // INetworkManagementEventObserver.Stub
-    public synchronized void interfaceLinkStateChanged(String interfaze, boolean up) {
-        if (!up && mLegacyVpnRunner != null) {
-            mLegacyVpnRunner.check(interfaze);
+    @Override
+    public void interfaceLinkStateChanged(String interfaze, boolean up) {
+        interfaceStatusChanged(interfaze, up);
+    }
+
+    // INetworkManagementEventObserver.Stub
+    @Override
+    public synchronized void interfaceRemoved(String interfaze) {
+        if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
+            long identity = Binder.clearCallingIdentity();
+            mCallback.restore();
+            hideNotification();
+            Binder.restoreCallingIdentity(identity);
+            mInterface = null;
+            // TODO: unbind the service
         }
     }
 
     // INetworkManagementEventObserver.Stub
-    public synchronized void interfaceRemoved(String interfaze) {
-        if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
-            mCallback.restore();
-            hideNotification();
-            mInterface = null;
-        }
+    @Override
+    public void limitReached(String limit, String interfaze) {
     }
 
-    public void limitReached(String limitName, String iface) {}
-
     private void showNotification(VpnConfig config, String label, Bitmap icon) {
         NotificationManager nm = (NotificationManager)
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -263,7 +265,6 @@
                     mContext.getString(R.string.vpn_text_long, config.session);
             config.startTime = SystemClock.elapsedRealtime();
 
-            long identity = Binder.clearCallingIdentity();
             Notification notification = new Notification.Builder(mContext)
                     .setSmallIcon(R.drawable.vpn_connected)
                     .setLargeIcon(icon)
@@ -274,7 +275,6 @@
                     .setOngoing(true)
                     .getNotification();
             nm.notify(R.drawable.vpn_connected, notification);
-            Binder.restoreCallingIdentity(identity);
         }
     }
 
@@ -283,9 +283,7 @@
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
 
         if (nm != null) {
-            long identity = Binder.clearCallingIdentity();
             nm.cancel(R.drawable.vpn_connected);
-            Binder.restoreCallingIdentity(identity);
         }
     }
 
@@ -355,8 +353,8 @@
             mOuterInterface = mConfig.interfaze;
 
             // Legacy VPN is not a real package, so we use it to carry the key.
-            mInfo.key = mConfig.packagz;
-            mConfig.packagz = VpnConfig.LEGACY_VPN;
+            mInfo.key = mConfig.user;
+            mConfig.user = VpnConfig.LEGACY_VPN;
         }
 
         public void check(String interfaze) {
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index b79e31f..0ce5499 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.database.Cursor;
 import android.location.Criteria;
 import android.location.IGpsStatusListener;
 import android.location.IGpsStatusProvider;
@@ -32,6 +33,7 @@
 import android.location.LocationProvider;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -45,6 +47,7 @@
 import android.os.SystemClock;
 import android.os.WorkSource;
 import android.provider.Settings;
+import android.provider.Telephony.Carriers;
 import android.provider.Telephony.Sms.Intents;
 import android.telephony.SmsMessage;
 import android.telephony.TelephonyManager;
@@ -489,8 +492,17 @@
         }
 
         if (info != null) {
+            boolean dataEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
+                                                         Settings.Secure.MOBILE_DATA, 1) == 1;
+            boolean networkAvailable = info.isAvailable() && dataEnabled;
+            String defaultApn = getSelectedApn();
+            if (defaultApn == null) {
+                defaultApn = "dummy-apn";
+            }
+
             native_update_network_state(info.isConnected(), info.getType(),
-                    info.isRoaming(), info.getExtraInfo());
+                                        info.isRoaming(), networkAvailable,
+                                        info.getExtraInfo(), defaultApn);
         }
 
         if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
@@ -1597,6 +1609,25 @@
         }
     }
 
+    private String getSelectedApn() {
+        Uri uri = Uri.parse("content://telephony/carriers/preferapn");
+        String apn = null;
+
+        Cursor cursor = mContext.getContentResolver().query(uri, new String[] {"apn"},
+                null, null, Carriers.DEFAULT_SORT_ORDER);
+
+        if (null != cursor) {
+            try {
+                if (cursor.moveToFirst()) {
+                    apn = cursor.getString(0);
+                }
+            } finally {
+                cursor.close();
+            }
+        }
+        return apn;
+    }
+
     // for GPS SV statistics
     private static final int MAX_SVS = 32;
     private static final int EPHEMERIS_MASK = 0;
@@ -1655,5 +1686,5 @@
     private native void native_agps_set_id(int type, String setid);
 
     private native void native_update_network_state(boolean connected, int type,
-            boolean roaming, String extraInfo);
+            boolean roaming, boolean available, String extraInfo, String defaultAPN);
 }
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 24188ca..deca7a9 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -16,10 +16,10 @@
 
 package com.android.server.net;
 
-import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
 import static android.Manifest.permission.ACCESS_NETWORK_STATE;
-import static android.Manifest.permission.MODIFY_NETWORK_ACCOUNTING;
+import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
 import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.MODIFY_NETWORK_ACCOUNTING;
 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
 import static android.content.Intent.ACTION_SHUTDOWN;
 import static android.content.Intent.ACTION_UID_REMOVED;
@@ -68,7 +68,6 @@
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
-import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.NtpTrustedTime;
 import android.util.Slog;
@@ -282,13 +281,13 @@
     }
 
     @Override
-    public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template) {
+    public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
         mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
 
         synchronized (mStatsLock) {
             // combine all interfaces that match template
             final NetworkStatsHistory combined = new NetworkStatsHistory(
-                    mSettings.getNetworkBucketDuration(), estimateNetworkBuckets());
+                    mSettings.getNetworkBucketDuration(), estimateNetworkBuckets(), fields);
             for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
                 if (templateMatches(template, ident)) {
                     final NetworkStatsHistory history = mNetworkStats.get(ident);
@@ -302,7 +301,8 @@
     }
 
     @Override
-    public NetworkStatsHistory getHistoryForUid(NetworkTemplate template, int uid, int tag) {
+    public NetworkStatsHistory getHistoryForUid(
+            NetworkTemplate template, int uid, int tag, int fields) {
         mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
 
         synchronized (mStatsLock) {
@@ -311,7 +311,7 @@
 
             // combine all interfaces that match template
             final NetworkStatsHistory combined = new NetworkStatsHistory(
-                    mSettings.getUidBucketDuration(), estimateUidBuckets());
+                    mSettings.getUidBucketDuration(), estimateUidBuckets(), fields);
             for (NetworkIdentitySet ident : mUidStats.keySet()) {
                 if (templateMatches(template, ident)) {
                     final NetworkStatsHistory history = mUidStats.get(ident).get(packed);
@@ -596,7 +596,7 @@
 
         // decide if enough has changed to trigger persist
         final NetworkStats persistDelta = computeStatsDelta(
-                mLastPersistNetworkSnapshot, networkSnapshot);
+                mLastPersistNetworkSnapshot, networkSnapshot, true);
         final long persistThreshold = mSettings.getPersistThreshold();
 
         NetworkStats.Entry entry = null;
@@ -626,7 +626,7 @@
     private void performNetworkPollLocked(NetworkStats networkSnapshot, long currentTime) {
         final HashSet<String> unknownIface = Sets.newHashSet();
 
-        final NetworkStats delta = computeStatsDelta(mLastNetworkSnapshot, networkSnapshot);
+        final NetworkStats delta = computeStatsDelta(mLastNetworkSnapshot, networkSnapshot, false);
         final long timeStart = currentTime - delta.getElapsedRealtime();
 
         NetworkStats.Entry entry = null;
@@ -661,9 +661,9 @@
     private void performUidPollLocked(NetworkStats uidSnapshot, long currentTime) {
         ensureUidStatsLoadedLocked();
 
-        final NetworkStats delta = computeStatsDelta(mLastUidSnapshot, uidSnapshot);
+        final NetworkStats delta = computeStatsDelta(mLastUidSnapshot, uidSnapshot, false);
         final NetworkStats operationsDelta = computeStatsDelta(
-                mLastOperationsSnapshot, mOperations);
+                mLastOperationsSnapshot, mOperations, false);
         final long timeStart = currentTime - delta.getElapsedRealtime();
 
         NetworkStats.Entry entry = null;
@@ -932,6 +932,7 @@
             out.flush();
             mNetworkFile.finishWrite(fos);
         } catch (IOException e) {
+            Slog.w(TAG, "problem writing stats: ", e);
             if (fos != null) {
                 mNetworkFile.failWrite(fos);
             }
@@ -978,6 +979,7 @@
             out.flush();
             mUidFile.finishWrite(fos);
         } catch (IOException e) {
+            Slog.w(TAG, "problem writing stats: ", e);
             if (fos != null) {
                 mUidFile.failWrite(fos);
             }
@@ -1052,15 +1054,20 @@
      */
     @Deprecated
     private void generateRandomLocked() {
-        long networkEnd = System.currentTimeMillis();
-        long networkStart = networkEnd - mSettings.getNetworkMaxHistory();
-        long networkRx = 3 * GB_IN_BYTES;
-        long networkTx = 2 * GB_IN_BYTES;
+        final long NET_END = System.currentTimeMillis();
+        final long NET_START = NET_END - mSettings.getNetworkMaxHistory();
+        final long NET_RX_BYTES = 3 * GB_IN_BYTES;
+        final long NET_RX_PACKETS = NET_RX_BYTES / 1024;
+        final long NET_TX_BYTES = 2 * GB_IN_BYTES;
+        final long NET_TX_PACKETS = NET_TX_BYTES / 1024;
 
-        long uidEnd = System.currentTimeMillis();
-        long uidStart = uidEnd - mSettings.getUidMaxHistory();
-        long uidRx = 500 * MB_IN_BYTES;
-        long uidTx = 100 * MB_IN_BYTES;
+        final long UID_END = System.currentTimeMillis();
+        final long UID_START = UID_END - mSettings.getUidMaxHistory();
+        final long UID_RX_BYTES = 500 * MB_IN_BYTES;
+        final long UID_RX_PACKETS = UID_RX_BYTES / 1024;
+        final long UID_TX_BYTES = 100 * MB_IN_BYTES;
+        final long UID_TX_PACKETS = UID_TX_BYTES / 1024;
+        final long UID_OPERATIONS = UID_RX_BYTES / 2048;
 
         final List<ApplicationInfo> installedApps = mContext
                 .getPackageManager().getInstalledApplications(0);
@@ -1068,13 +1075,13 @@
         mNetworkStats.clear();
         mUidStats.clear();
         for (NetworkIdentitySet ident : mActiveIfaces.values()) {
-            findOrCreateNetworkStatsLocked(ident).generateRandom(
-                    networkStart, networkEnd, networkRx, networkTx);
+            findOrCreateNetworkStatsLocked(ident).generateRandom(NET_START, NET_END, NET_RX_BYTES,
+                    NET_RX_PACKETS, NET_TX_BYTES, NET_TX_PACKETS, 0L);
 
             for (ApplicationInfo info : installedApps) {
                 final int uid = info.uid;
-                findOrCreateUidStatsLocked(ident, uid, TAG_NONE).generateRandom(
-                        uidStart, uidEnd, uidRx, uidTx);
+                findOrCreateUidStatsLocked(ident, uid, TAG_NONE).generateRandom(UID_START, UID_END,
+                        UID_RX_BYTES, UID_RX_PACKETS, UID_TX_BYTES, UID_TX_PACKETS, UID_OPERATIONS);
             }
         }
     }
@@ -1083,9 +1090,13 @@
      * Return the delta between two {@link NetworkStats} snapshots, where {@code
      * before} can be {@code null}.
      */
-    private static NetworkStats computeStatsDelta(NetworkStats before, NetworkStats current) {
+    private static NetworkStats computeStatsDelta(
+            NetworkStats before, NetworkStats current, boolean collectStale) {
         if (before != null) {
             return current.subtractClamped(before);
+        } else if (collectStale) {
+            // caller is okay collecting stale stats for first call.
+            return current;
         } else {
             // this is first snapshot; to prevent from double-counting we only
             // observe traffic occuring between known snapshots.
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index 86de880..91c5e33 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -382,7 +382,7 @@
                 mAdbEnabled = enable;
                 // Due to the persist.sys.usb.config property trigger, changing adb state requires
                 // switching to default function
-                setEnabledFunctions(mDefaultFunctions, false);
+                setEnabledFunctions(mDefaultFunctions, true);
                 updateAdbNotification();
             }
         }
diff --git a/services/jni/com_android_server_location_GpsLocationProvider.cpp b/services/jni/com_android_server_location_GpsLocationProvider.cpp
index c29be3a..c823da5 100755
--- a/services/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -543,7 +543,7 @@
 }
 
 static void android_location_GpsLocationProvider_update_network_state(JNIEnv* env, jobject obj,
-        jboolean connected, int type, jboolean roaming, jstring extraInfo)
+        jboolean connected, int type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn)
 {
 
     if (sAGpsRilInterface && sAGpsRilInterface->update_network_state) {
@@ -554,6 +554,14 @@
         } else {
             sAGpsRilInterface->update_network_state(connected, type, roaming, NULL);
         }
+
+        // update_network_availability callback was not included in original AGpsRilInterface
+        if (sAGpsRilInterface->size >= sizeof(AGpsRilInterface)
+                && sAGpsRilInterface->update_network_availability) {
+            const char *c_apn = env->GetStringUTFChars(apn, NULL);
+            sAGpsRilInterface->update_network_availability(available, c_apn);
+            env->ReleaseStringUTFChars(apn, c_apn);
+        }
     }
 }
 
@@ -582,7 +590,7 @@
     {"native_send_ni_response", "(II)V", (void*)android_location_GpsLocationProvider_send_ni_response},
     {"native_agps_ni_message", "([BI)V", (void *)android_location_GpsLocationProvider_agps_send_ni_message},
     {"native_get_internal_state", "()Ljava/lang/String;", (void*)android_location_GpsLocationProvider_get_internal_state},
-    {"native_update_network_state", "(ZIZLjava/lang/String;)V", (void*)android_location_GpsLocationProvider_update_network_state },
+    {"native_update_network_state", "(ZIZZLjava/lang/String;Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_update_network_state },
 };
 
 int register_android_server_location_GpsLocationProvider(JNIEnv* env)
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 91fef22..09f8ff3 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -20,14 +20,18 @@
 import static android.content.Intent.EXTRA_UID;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.NetworkPolicy.LIMIT_DISABLED;
 import static android.net.NetworkPolicy.SNOOZE_NEVER;
+import static android.net.NetworkPolicy.WARNING_DISABLED;
 import static android.net.NetworkPolicyManager.POLICY_NONE;
 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
 import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
 import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
+import static android.net.NetworkPolicyManager.computeNextCycleBoundary;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
+import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
 import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
@@ -79,6 +83,7 @@
 import org.easymock.IAnswer;
 
 import java.io.File;
+import java.util.LinkedHashSet;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
@@ -402,7 +407,7 @@
         final NetworkPolicy policy = new NetworkPolicy(
                 sTemplateWifi, 5, 1024L, 1024L, SNOOZE_NEVER);
         final long actualCycle = computeLastCycleBoundary(currentTime, policy);
-        assertEquals(expectedCycle, actualCycle);
+        assertTimeEquals(expectedCycle, actualCycle);
     }
 
     public void testLastCycleBoundaryLastMonth() throws Exception {
@@ -413,7 +418,7 @@
         final NetworkPolicy policy = new NetworkPolicy(
                 sTemplateWifi, 20, 1024L, 1024L, SNOOZE_NEVER);
         final long actualCycle = computeLastCycleBoundary(currentTime, policy);
-        assertEquals(expectedCycle, actualCycle);
+        assertTimeEquals(expectedCycle, actualCycle);
     }
 
     public void testLastCycleBoundaryThisMonthFebruary() throws Exception {
@@ -424,18 +429,48 @@
         final NetworkPolicy policy = new NetworkPolicy(
                 sTemplateWifi, 30, 1024L, 1024L, SNOOZE_NEVER);
         final long actualCycle = computeLastCycleBoundary(currentTime, policy);
-        assertEquals(expectedCycle, actualCycle);
+        assertTimeEquals(expectedCycle, actualCycle);
     }
 
     public void testLastCycleBoundaryLastMonthFebruary() throws Exception {
         // assume cycle day of "30th" in february, which should clamp
         final long currentTime = parseTime("2007-03-14T00:00:00.000Z");
-        final long expectedCycle = parseTime("2007-03-01T00:00:00.000Z");
+        final long expectedCycle = parseTime("2007-02-28T23:59:59.000Z");
 
         final NetworkPolicy policy = new NetworkPolicy(
                 sTemplateWifi, 30, 1024L, 1024L, SNOOZE_NEVER);
         final long actualCycle = computeLastCycleBoundary(currentTime, policy);
-        assertEquals(expectedCycle, actualCycle);
+        assertTimeEquals(expectedCycle, actualCycle);
+    }
+
+    public void testNextCycleSane() throws Exception {
+        final NetworkPolicy policy = new NetworkPolicy(
+                sTemplateWifi, 31, WARNING_DISABLED, LIMIT_DISABLED, SNOOZE_NEVER);
+        final LinkedHashSet<Long> seen = new LinkedHashSet<Long>();
+
+        // walk forwards, ensuring that cycle boundaries don't get stuck
+        long currentCycle = computeNextCycleBoundary(parseTime("2011-08-01T00:00:00.000Z"), policy);
+        for (int i = 0; i < 128; i++) {
+            long nextCycle = computeNextCycleBoundary(currentCycle, policy);
+            assertEqualsFuzzy(DAY_IN_MILLIS * 30, nextCycle - currentCycle, DAY_IN_MILLIS * 3);
+            assertUnique(seen, nextCycle);
+            currentCycle = nextCycle;
+        }
+    }
+
+    public void testLastCycleSane() throws Exception {
+        final NetworkPolicy policy = new NetworkPolicy(
+                sTemplateWifi, 31, WARNING_DISABLED, LIMIT_DISABLED, SNOOZE_NEVER);
+        final LinkedHashSet<Long> seen = new LinkedHashSet<Long>();
+
+        // walk backwards, ensuring that cycle boundaries look sane
+        long currentCycle = computeLastCycleBoundary(parseTime("2011-08-04T00:00:00.000Z"), policy);
+        for (int i = 0; i < 128; i++) {
+            long lastCycle = computeLastCycleBoundary(currentCycle, policy);
+            assertEqualsFuzzy(DAY_IN_MILLIS * 30, currentCycle - lastCycle, DAY_IN_MILLIS * 3);
+            assertUnique(seen, lastCycle);
+            currentCycle = lastCycle;
+        }
     }
 
     public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
@@ -734,6 +769,32 @@
         }
     }
 
+    private static void assertTimeEquals(long expected, long actual) {
+        if (expected != actual) {
+            fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual));
+        }
+    }
+
+    private static String formatTime(long millis) {
+        final Time time = new Time(Time.TIMEZONE_UTC);
+        time.set(millis);
+        return time.format3339(false);
+    }
+
+    private static void assertEqualsFuzzy(long expected, long actual, long fuzzy) {
+        final long low = expected - fuzzy;
+        final long high = expected + fuzzy;
+        if (actual < low || actual > high) {
+            fail("value " + actual + " is outside [" + low + "," + high + "]");
+        }
+    }
+
+    private static void assertUnique(LinkedHashSet<Long> seen, Long value) {
+        if (!seen.add(value)) {
+            fail("found duplicate time " + value + " in series " + seen.toString());
+        }
+    }
+
     private static void assertNotificationType(int expected, String actualTag) {
         assertEquals(
                 Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index cf69fd5..8eb9cc3 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -25,6 +25,7 @@
 import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
+import static android.net.NetworkStatsHistory.FIELD_ALL;
 import static android.net.NetworkTemplate.buildTemplateMobileAll;
 import static android.net.NetworkTemplate.buildTemplateWifi;
 import static android.net.TrafficStats.UID_REMOVED;
@@ -302,7 +303,7 @@
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
 
         // verify service recorded history
-        history = mService.getHistoryForNetwork(sTemplateWifi);
+        history = mService.getHistoryForNetwork(sTemplateWifi, FIELD_ALL);
         assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0);
         assertEquals(HOUR_IN_MILLIS, history.getBucketDuration());
         assertEquals(2, history.size());
@@ -319,7 +320,7 @@
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
 
         // verify identical stats, but spread across 4 buckets now
-        history = mService.getHistoryForNetwork(sTemplateWifi);
+        history = mService.getHistoryForNetwork(sTemplateWifi, FIELD_ALL);
         assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0);
         assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration());
         assertEquals(4, history.size());
@@ -631,14 +632,15 @@
 
     private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long rxPackets,
             long txBytes, long txPackets, int operations) {
-        final NetworkStatsHistory history = mService.getHistoryForNetwork(template);
+        final NetworkStatsHistory history = mService.getHistoryForNetwork(template, FIELD_ALL);
         assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes,
                 txPackets, operations);
     }
 
     private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long rxPackets,
             long txBytes, long txPackets, int operations) {
-        final NetworkStatsHistory history = mService.getHistoryForUid(template, uid, TAG_NONE);
+        final NetworkStatsHistory history = mService.getHistoryForUid(
+                template, uid, TAG_NONE, FIELD_ALL);
         assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes,
                 txPackets, operations);
     }
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java
index aad138c..9ea90f8 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java
@@ -236,8 +236,10 @@
             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]);
+                String statLabel = resources.getString(
+                        Stats[statIndex].getLabelId()).substring(0,3);
+                label = statLabel + " " + resources.getString(
+                        R.string.format_stat, mStats[metricIndex][statIndex]);
                 yPos = LABELOFFSET + (1 + statIndex) * PlaybackView.TILE_SCALE
                         / 2;
                 canvas.drawText(label, xPos, yPos, whiteLabels);
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java
index a63a2f0..82a7e82 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java
@@ -223,7 +223,7 @@
         mMovementSpinner = (Spinner) findViewById(R.id.movement);
         mUrl = (EditText) findViewById(R.id.url);
         mWeb = (ProfiledWebView) findViewById(R.id.web);
-        mCallback = new ProfileCallback() {
+        setCallback(new ProfileCallback() {
             @SuppressWarnings("unchecked")
             @Override
             public void profileCallback(RunData data) {
@@ -232,7 +232,7 @@
                 mCaptureButton.setChecked(false);
                 setTestingState(TestingState.STOP_TESTING);
             }
-        };
+        });
 
         // Inspect button (opens PlaybackActivity)
         mInspectButton.setOnClickListener(new OnClickListener() {
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
index 625b40d..0928ec5 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
@@ -417,6 +417,22 @@
     }
 
     @Override
+    public boolean getBoolean(int id) throws NotFoundException {
+        Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
+
+        if (value != null && value.getSecond().getValue() != null) {
+            String v = value.getSecond().getValue();
+            return Boolean.parseBoolean(v);
+        }
+
+        // id was not found or not resolved. Throw a NotFoundException.
+        throwException(id);
+
+        // this is not used since the method above always throws
+        return false;
+    }
+
+    @Override
     public String getResourceEntryName(int resid) throws NotFoundException {
         throw new UnsupportedOperationException();
     }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index de49eb4..331d5c0 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -57,6 +57,7 @@
 import android.net.NetworkUtils;
 import android.net.wifi.WpsResult.Status;
 import android.net.wifi.p2p.WifiP2pManager;
+import android.net.wifi.p2p.WifiP2pService;
 import android.net.wifi.StateChangeResult;
 import android.os.Binder;
 import android.os.IBinder;
@@ -69,7 +70,6 @@
 import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.WorkSource;
-import android.server.WifiP2pService;
 import android.provider.Settings;
 import android.util.EventLog;
 import android.util.Log;
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
index be9dfcf..168c68b 100644
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -44,9 +44,11 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.HttpURLConnection;
+import java.net.InetAddress;
 import java.net.URL;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * {@link WifiWatchdogStateMachine} monitors the initial connection to a Wi-Fi
@@ -82,7 +84,6 @@
     private static final int DEFAULT_MAX_SSID_BLACKLISTS = 7;
     private static final int DEFAULT_NUM_DNS_PINGS = 5;
     private static final int DEFAULT_MIN_DNS_RESPONSES = 3;
-    private static final long DNS_PING_INTERVAL_MS = 100;
 
     private static final int DEFAULT_DNS_PING_TIMEOUT_MS = 2000;
 
@@ -92,6 +93,7 @@
     private static final String DEFAULT_WALLED_GARDEN_URL =
             "http://clients3.google.com/generate_204";
     private static final int WALLED_GARDEN_SOCKET_TIMEOUT_MS = 10000;
+    private static final int DNS_INTRATEST_PING_INTERVAL = 20;
 
     private static final int BASE = Protocol.BASE_WIFI_WATCHDOG;
 
@@ -114,9 +116,8 @@
     private static final int EVENT_WIFI_RADIO_STATE_CHANGE = BASE + 5;
     private static final int EVENT_WATCHDOG_SETTINGS_CHANGE = BASE + 6;
 
-    private static final int MESSAGE_CHECK_STEP = BASE + 100;
-    private static final int MESSAGE_HANDLE_WALLED_GARDEN = BASE + 101;
-    private static final int MESSAGE_HANDLE_BAD_AP = BASE + 102;
+    private static final int MESSAGE_HANDLE_WALLED_GARDEN = BASE + 100;
+    private static final int MESSAGE_HANDLE_BAD_AP = BASE + 101;
     /**
      * arg1 == mOnlineWatchState.checkCount
      */
@@ -189,8 +190,9 @@
         mContext = context;
         mContentResolver = context.getContentResolver();
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
-        mDnsPinger = new DnsPinger("WifiWatchdogServer.DnsPinger", context,
-                ConnectivityManager.TYPE_WIFI);
+        mDnsPinger = new DnsPinger(mContext, "WifiWatchdogStateMachine.DnsPinger",
+                                this.getHandler().getLooper(), this.getHandler(),
+                                ConnectivityManager.TYPE_WIFI);
 
         setupNetworkReceiver();
 
@@ -637,36 +639,43 @@
     }
 
     class DnsCheckingState extends State {
-        int dnsCheckTries = 0;
         int dnsCheckSuccesses = 0;
+        int dnsCheckTries = 0;
         String dnsCheckLogStr = "";
+        Set<Integer> ids = new HashSet<Integer>();
 
         @Override
         public void enter() {
             dnsCheckSuccesses = 0;
             dnsCheckTries = 0;
+            ids.clear();
+            InetAddress dns = mDnsPinger.getDns();
             if (DBG) {
                 Slog.d(WWSM_TAG, "Starting DNS pings at " + SystemClock.elapsedRealtime());
                 dnsCheckLogStr = String.format("Pinging %s on ssid [%s]: ",
-                        mDnsPinger.getDns(), mInitialConnInfo.getSSID());
+                        dns, mInitialConnInfo.getSSID());
             }
 
-            sendCheckStepMessage(0);
+            for (int i=0; i < mNumDnsPings; i++) {
+                ids.add(mDnsPinger.pingDnsAsync(dns, mDnsPingTimeoutMs,
+                        DNS_INTRATEST_PING_INTERVAL * i));
+            }
         }
 
         @Override
         public boolean processMessage(Message msg) {
-            if (msg.what != MESSAGE_CHECK_STEP) {
+            if (msg.what != DnsPinger.DNS_PING_RESULT) {
                 return NOT_HANDLED;
             }
-            if (msg.arg1 != mNetEventCounter) {
-                Slog.d(WWSM_TAG, "Check step out of sync, ignoring...");
+
+            int pingID = msg.arg1;
+            int pingResponseTime = msg.arg2;
+
+            if (!ids.contains(pingID)) {
+                Slog.w(WWSM_TAG, "Received a Dns response with unknown ID!");
                 return HANDLED;
             }
-
-            long pingResponseTime = mDnsPinger.pingDns(mDnsPinger.getDns(),
-                    mDnsPingTimeoutMs);
-
+            ids.remove(pingID);
             dnsCheckTries++;
             if (pingResponseTime >= 0)
                 dnsCheckSuccesses++;
@@ -730,11 +739,15 @@
                 return HANDLED;
             }
 
-            // Still in dns check step
-            sendCheckStepMessage(DNS_PING_INTERVAL_MS);
             return HANDLED;
         }
 
+        @Override
+        public void exit() {
+            mDnsPinger.cancelPings();
+        }
+
+
         private boolean shouldCheckWalledGarden() {
             if (!mWalledGardenTestEnabled) {
                 if (VDBG)
@@ -752,11 +765,6 @@
             }
             return true;
         }
-
-        private void sendCheckStepMessage(long delay) {
-            sendMessageDelayed(obtainMessage(MESSAGE_CHECK_STEP, mNetEventCounter, 0), delay);
-        }
-
     }
 
     class OnlineWatchState extends State {
@@ -779,12 +787,15 @@
         int checkGuard = 0;
         Long lastCheckTime = null;
 
+        int curPingID = 0;
+
         @Override
         public void enter() {
             lastCheckTime = SystemClock.elapsedRealtime();
             signalUnstable = false;
             checkGuard++;
             unstableSignalChecks = false;
+            curPingID = 0;
             triggerSingleDnsCheck();
         }
 
@@ -820,8 +831,18 @@
                         return HANDLED;
                     }
                     lastCheckTime = SystemClock.elapsedRealtime();
-                    long responseTime = mDnsPinger.pingDns(mDnsPinger.getDns(),
-                            mDnsPingTimeoutMs);
+                    curPingID = mDnsPinger.pingDnsAsync(mDnsPinger.getDns(),
+                            mDnsPingTimeoutMs, 0);
+                    return HANDLED;
+                case DnsPinger.DNS_PING_RESULT:
+                    if ((short) msg.arg1 != curPingID) {
+                        if (VDBG) {
+                            Slog.v(WWSM_TAG, "Received non-matching DnsPing w/ id: " +
+                                    msg.arg1);
+                        }
+                        return HANDLED;
+                    }
+                    int responseTime = msg.arg2;
                     if (responseTime >= 0) {
                         if (VDBG) {
                             Slog.v(WWSM_TAG, "Ran a single DNS ping. Response time: "
@@ -842,6 +863,11 @@
             return NOT_HANDLED;
         }
 
+        @Override
+        public void exit() {
+            mDnsPinger.cancelPings();
+        }
+
         /**
          * Times a dns check with an interval based on {@link #signalUnstable}
          */
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 4988f0b..28afd44 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.server;
+package android.net.wifi.p2p;
 
 import android.app.AlertDialog;
 import android.content.BroadcastReceiver;
@@ -31,20 +31,13 @@
 import android.net.wifi.WifiStateMachine;
 import android.net.wifi.WpsConfiguration;
 import android.net.wifi.WpsConfiguration.Setup;
-import android.net.wifi.p2p.IWifiP2pManager;
-import android.net.wifi.p2p.WifiP2pConfig;
-import android.net.wifi.p2p.WifiP2pDevice;
 import android.net.wifi.p2p.WifiP2pDevice.Status;
-import android.net.wifi.p2p.WifiP2pDeviceList;
-import android.net.wifi.p2p.WifiP2pGroup;
-import android.net.wifi.p2p.WifiP2pManager;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Handler;
-import android.os.Messenger;
 import android.os.HandlerThread;
-import android.os.IBinder;
 import android.os.Message;
+import android.os.Messenger;
 import android.util.Slog;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -55,9 +48,9 @@
 import java.io.PrintWriter;
 import java.util.Collection;
 
+import com.android.internal.R;
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
-import com.android.internal.R;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;