Merge "Bluetooth Health APIs"
diff --git a/Android.mk b/Android.mk
index 5f3327c..335fb73 100644
--- a/Android.mk
+++ b/Android.mk
@@ -36,6 +36,7 @@
 # EventLogTags files.
 LOCAL_SRC_FILES += \
        core/java/android/content/EventLogTags.logtags \
+       core/java/android/speech/tts/EventLogTags.logtags \
        core/java/android/webkit/EventLogTags.logtags \
        telephony/java/com/android/internal/telephony/EventLogTags.logtags \
 
@@ -190,7 +191,6 @@
 	telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
 	wifi/java/android/net/wifi/IWifiManager.aidl \
 	telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl \
-	vpn/java/android/net/vpn/IVpnService.aidl \
 	voip/java/android/net/sip/ISipSession.aidl \
 	voip/java/android/net/sip/ISipSessionListener.aidl \
 	voip/java/android/net/sip/ISipService.aidl
@@ -280,7 +280,6 @@
 	frameworks/base/telephony/java/android/telephony/ServiceState.aidl \
 	frameworks/base/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
 	frameworks/base/telephony/java/com/android/internal/telephony/ITelephony.aidl \
-	frameworks/base/vpn/java/android/net/vpn/IVpnService.aidl \
 
 gen := $(TARGET_OUT_COMMON_INTERMEDIATES)/framework.aidl
 $(gen): PRIVATE_SRC_FILES := $(aidl_files)
@@ -452,7 +451,9 @@
 		-samplecode $(sample_dir)/VoicemailProviderDemo \
 		            resources/samples/VoicemailProviderDemo "Voicemail Provider Demo" \
 		-samplecode $(sample_dir)/XmlAdapters \
-		            resources/samples/XmlAdapters "XML Adapters"
+		            resources/samples/XmlAdapters "XML Adapters" \
+		-samplecode $(sample_dir)/TtsEngine \
+		            resources/samples/TtsEngine "Text To Speech Engine"
 
 ## SDK version identifiers used in the published docs
   # major[.minor] version for current SDK. (full releases only)
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 8d34636..f3eaeeb 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -100,6 +100,7 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libstagefright_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os)
 $(call add-clean-step, rm -rf $(OUT_DIR)target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/keystore/java/android/security/IKeyChainAliasResponse.java)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/vpn)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/api/13.xml b/api/13.xml
index 9af0640..2bfa04e 100644
--- a/api/13.xml
+++ b/api/13.xml
@@ -25290,7 +25290,7 @@
  abstract="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="ActivityGroup"
@@ -30614,6 +30614,17 @@
  visibility="public"
 >
 </method>
+<method name="isDetached"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isHidden"
  return="boolean"
  abstract="false"
@@ -33935,7 +33946,7 @@
  abstract="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="LocalActivityManager"
@@ -37009,7 +37020,7 @@
  abstract="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="TabActivity"
@@ -61810,6 +61821,28 @@
  visibility="public"
 >
 </field>
+<field name="FEATURE_SCREEN_LANDSCAPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.hardware.screen.landscape&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FEATURE_SCREEN_PORTRAIT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.hardware.screen.portrait&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FEATURE_SENSOR_ACCELEROMETER"
  type="java.lang.String"
  transient="false"
@@ -148973,6 +149006,17 @@
  visibility="public"
 >
 </field>
+<field name="TWEET_TRANSACTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1599362900"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </interface>
 <interface name="IBinder.DeathRecipient"
  abstract="true"
diff --git a/api/14.txt b/api/14.txt
index 050540b..d25d2b9 100644
--- a/api/14.txt
+++ b/api/14.txt
@@ -16272,20 +16272,10 @@
 
   public class AllocationAdapter extends android.renderscript.Allocation {
     method public static android.renderscript.AllocationAdapter create2D(android.renderscript.RenderScript, android.renderscript.Allocation);
-    method public void readData(int[]);
-    method public void readData(float[]);
     method public void setFace(android.renderscript.Type.CubemapFace);
     method public void setLOD(int);
     method public void setY(int);
     method public void setZ(int);
-    method public void subData(int, android.renderscript.FieldPacker);
-    method public void subData1D(int, int, int[]);
-    method public void subData1D(int, int, short[]);
-    method public void subData1D(int, int, byte[]);
-    method public void subData1D(int, int, float[]);
-    method public void subData2D(int, int, int, int, int[]);
-    method public void subData2D(int, int, int, int, float[]);
-    method public void subElementData(int, int, android.renderscript.FieldPacker);
   }
 
    class BaseObj {
diff --git a/api/current.txt b/api/current.txt
index 2ad044e..46cf2af 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -183,13 +183,14 @@
   public static final class R.attr {
     ctor public R.attr();
     field public static final int absListViewStyle = 16842858; // 0x101006a
-    field public static final int accessibilityEventTypes = 16843650; // 0x1010382
-    field public static final int accessibilityFeedbackType = 16843652; // 0x1010384
-    field public static final int accessibilityFlags = 16843654; // 0x1010386
+    field public static final int accessibilityEventTypes = 16843649; // 0x1010381
+    field public static final int accessibilityFeedbackType = 16843651; // 0x1010383
+    field public static final int accessibilityFlags = 16843653; // 0x1010385
     field public static final int accountPreferences = 16843423; // 0x101029f
     field public static final int accountType = 16843407; // 0x101028f
     field public static final int action = 16842797; // 0x101002d
     field public static final int actionBarSize = 16843499; // 0x10102eb
+    field public static final int actionBarSplitStyle = 16843675; // 0x101039b
     field public static final int actionBarStyle = 16843470; // 0x10102ce
     field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4
     field public static final int actionBarTabStyle = 16843507; // 0x10102f3
@@ -205,8 +206,9 @@
     field public static final int actionModeCopyDrawable = 16843538; // 0x1010312
     field public static final int actionModeCutDrawable = 16843537; // 0x1010311
     field public static final int actionModePasteDrawable = 16843539; // 0x1010313
-    field public static final int actionModeSelectAllDrawable = 16843648; // 0x1010380
+    field public static final int actionModeSelectAllDrawable = 16843647; // 0x101037f
     field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
+    field public static final int actionProviderClass = 16843677; // 0x101039d
     field public static final int actionViewClass = 16843516; // 0x10102fc
     field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
     field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
@@ -218,7 +220,7 @@
     field public static final int alertDialogIcon = 16843605; // 0x1010355
     field public static final int alertDialogStyle = 16842845; // 0x101005d
     field public static final int alertDialogTheme = 16843529; // 0x1010309
-    field public static final int alignmentMode = 16843642; // 0x101037a
+    field public static final int alignmentMode = 16843641; // 0x1010379
     field public static final int allContactsName = 16843468; // 0x10102cc
     field public static final int allowBackup = 16843392; // 0x1010280
     field public static final int allowClearUserData = 16842757; // 0x1010005
@@ -252,6 +254,8 @@
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
+    field public static final int backgroundSplit = 16843679; // 0x101039f
+    field public static final int backgroundStacked = 16843678; // 0x101039e
     field public static final int backupAgent = 16843391; // 0x101027f
     field public static final int baseline = 16843548; // 0x101031c
     field public static final int baselineAlignBottom = 16843042; // 0x1010122
@@ -260,7 +264,7 @@
     field public static final int borderlessButtonStyle = 16843563; // 0x101032b
     field public static final int bottom = 16843184; // 0x10101b0
     field public static final int bottomBright = 16842957; // 0x10100cd
-    field public static final int bottomChevronDrawable = 16843661; // 0x101038d
+    field public static final int bottomChevronDrawable = 16843660; // 0x101038c
     field public static final int bottomDark = 16842953; // 0x10100c9
     field public static final int bottomLeftRadius = 16843179; // 0x10101ab
     field public static final int bottomMedium = 16842958; // 0x10100ce
@@ -279,7 +283,7 @@
     field public static final int cacheColorHint = 16843009; // 0x1010101
     field public static final int calendarViewShown = 16843596; // 0x101034c
     field public static final int calendarViewStyle = 16843613; // 0x101035d
-    field public static final int canRetrieveWindowContent = 16843655; // 0x1010387
+    field public static final int canRetrieveWindowContent = 16843654; // 0x1010386
     field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
     field public static final deprecated int capitalize = 16843113; // 0x1010169
     field public static final int centerBright = 16842956; // 0x10100cc
@@ -308,13 +312,18 @@
     field public static final int codes = 16843330; // 0x1010242
     field public static final int collapseColumns = 16843083; // 0x101014b
     field public static final int color = 16843173; // 0x10101a5
+    field public static final int colorActivatedHighlight = 16843684; // 0x10103a4
     field public static final int colorBackground = 16842801; // 0x1010031
     field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
+    field public static final int colorFocusedHighlight = 16843683; // 0x10103a3
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
-    field public static final int columnCount = 16843639; // 0x1010377
+    field public static final int colorLongPressedHighlight = 16843682; // 0x10103a2
+    field public static final int colorMultiSelectHighlight = 16843685; // 0x10103a5
+    field public static final int colorPressedHighlight = 16843681; // 0x10103a1
+    field public static final int columnCount = 16843638; // 0x1010376
     field public static final int columnDelay = 16843215; // 0x10101cf
-    field public static final int columnOrderPreserved = 16843640; // 0x1010378
+    field public static final int columnOrderPreserved = 16843639; // 0x1010377
     field public static final int columnWidth = 16843031; // 0x1010117
     field public static final int compatibleWidthLimitDp = 16843621; // 0x1010365
     field public static final int completionHint = 16843122; // 0x1010172
@@ -427,7 +436,7 @@
     field public static final int fastScrollTextColor = 16843609; // 0x1010359
     field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336
     field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339
-    field public static final int feedbackCount = 16843667; // 0x1010393
+    field public static final int feedbackCount = 16843666; // 0x1010392
     field public static final int fillAfter = 16843197; // 0x10101bd
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillEnabled = 16843343; // 0x101024f
@@ -460,7 +469,6 @@
     field public static final int fromXScale = 16843202; // 0x10101c2
     field public static final int fromYDelta = 16843208; // 0x10101c8
     field public static final int fromYScale = 16843204; // 0x10101c4
-    field public static final int fullBackupAgent = 16843635; // 0x1010373
     field public static final int fullBright = 16842954; // 0x10100ca
     field public static final int fullDark = 16842950; // 0x10100c6
     field public static final int functionalTest = 16842787; // 0x1010023
@@ -481,7 +489,7 @@
     field public static final int hand_hour = 16843011; // 0x1010103
     field public static final int hand_minute = 16843012; // 0x1010104
     field public static final int handle = 16843354; // 0x101025a
-    field public static final int handleDrawable = 16843657; // 0x1010389
+    field public static final int handleDrawable = 16843656; // 0x1010388
     field public static final int handleProfiling = 16842786; // 0x1010022
     field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
     field public static final int hardwareAccelerated = 16843475; // 0x10102d3
@@ -490,12 +498,12 @@
     field public static final int headerDividersEnabled = 16843310; // 0x101022e
     field public static final int height = 16843093; // 0x1010155
     field public static final int hint = 16843088; // 0x1010150
-    field public static final int hitRadius = 16843664; // 0x1010390
+    field public static final int hitRadius = 16843663; // 0x101038f
     field public static final int homeAsUpIndicator = 16843531; // 0x101030b
     field public static final int homeLayout = 16843549; // 0x101031d
     field public static final int horizontalDivider = 16843053; // 0x101012d
     field public static final int horizontalGap = 16843327; // 0x101023f
-    field public static final int horizontalOffset = 16843669; // 0x1010395
+    field public static final int horizontalOffset = 16843668; // 0x1010394
     field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
     field public static final int horizontalSpacing = 16843028; // 0x1010114
     field public static final int host = 16842792; // 0x1010028
@@ -541,7 +549,7 @@
     field public static final int installLocation = 16843447; // 0x10102b7
     field public static final int interpolator = 16843073; // 0x1010141
     field public static final int isAlwaysSyncable = 16843571; // 0x1010333
-    field public static final int isAuxiliary = 16843649; // 0x1010381
+    field public static final int isAuxiliary = 16843648; // 0x1010380
     field public static final int isDefault = 16843297; // 0x1010221
     field public static final int isIndicator = 16843079; // 0x1010147
     field public static final int isModifier = 16843334; // 0x1010246
@@ -595,18 +603,20 @@
     field public static final int layout_centerInParent = 16843151; // 0x101018f
     field public static final int layout_centerVertical = 16843153; // 0x1010191
     field public static final int layout_column = 16843084; // 0x101014c
-    field public static final int layout_columnSpan = 16843646; // 0x101037e
-    field public static final int layout_columnWeight = 16843647; // 0x101037f
+    field public static final int layout_columnFlexibility = 16843646; // 0x101037e
+    field public static final int layout_columnSpan = 16843645; // 0x101037d
     field public static final int layout_gravity = 16842931; // 0x10100b3
     field public static final int layout_height = 16842997; // 0x10100f5
     field public static final int layout_margin = 16842998; // 0x10100f6
     field public static final int layout_marginBottom = 16843002; // 0x10100fa
+    field public static final int layout_marginEnd = 16843674; // 0x101039a
     field public static final int layout_marginLeft = 16842999; // 0x10100f7
     field public static final int layout_marginRight = 16843001; // 0x10100f9
+    field public static final int layout_marginStart = 16843673; // 0x1010399
     field public static final int layout_marginTop = 16843000; // 0x10100f8
-    field public static final int layout_row = 16843643; // 0x101037b
-    field public static final int layout_rowSpan = 16843644; // 0x101037c
-    field public static final int layout_rowWeight = 16843645; // 0x101037d
+    field public static final int layout_row = 16843642; // 0x101037a
+    field public static final int layout_rowFlexibility = 16843644; // 0x101037c
+    field public static final int layout_rowSpan = 16843643; // 0x101037b
     field public static final int layout_scale = 16843155; // 0x1010193
     field public static final int layout_span = 16843085; // 0x101014d
     field public static final int layout_toLeftOf = 16843138; // 0x1010182
@@ -616,7 +626,7 @@
     field public static final int layout_x = 16843135; // 0x101017f
     field public static final int layout_y = 16843136; // 0x1010180
     field public static final int left = 16843181; // 0x10101ad
-    field public static final int leftChevronDrawable = 16843658; // 0x101038a
+    field public static final int leftChevronDrawable = 16843657; // 0x1010389
     field public static final int lineSpacingExtra = 16843287; // 0x1010217
     field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
     field public static final int lines = 16843092; // 0x1010154
@@ -628,8 +638,8 @@
     field public static final int listDividerAlertDialog = 16843525; // 0x1010305
     field public static final int listPopupWindowStyle = 16843519; // 0x10102ff
     field public static final int listPreferredItemHeight = 16842829; // 0x101004d
-    field public static final int listPreferredItemHeightLarge = 16843670; // 0x1010396
-    field public static final int listPreferredItemHeightSmall = 16843671; // 0x1010397
+    field public static final int listPreferredItemHeightLarge = 16843669; // 0x1010395
+    field public static final int listPreferredItemHeightSmall = 16843670; // 0x1010396
     field public static final int listSelector = 16843003; // 0x10100fb
     field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208
     field public static final int listViewStyle = 16842868; // 0x1010074
@@ -675,7 +685,7 @@
     field public static final int nextFocusUp = 16842979; // 0x10100e3
     field public static final int noHistory = 16843309; // 0x101022d
     field public static final int normalScreens = 16843397; // 0x1010285
-    field public static final int notificationTimeout = 16843653; // 0x1010385
+    field public static final int notificationTimeout = 16843652; // 0x1010384
     field public static final int numColumns = 16843032; // 0x1010118
     field public static final int numStars = 16843076; // 0x1010144
     field public static final deprecated int numeric = 16843109; // 0x1010165
@@ -689,17 +699,17 @@
     field public static final int orderingFromXml = 16843239; // 0x10101e7
     field public static final int orientation = 16842948; // 0x10100c4
     field public static final int outAnimation = 16843128; // 0x1010178
-    field public static final int outerRadius = 16843663; // 0x101038f
+    field public static final int outerRadius = 16843662; // 0x101038e
     field public static final int overScrollFooter = 16843459; // 0x10102c3
     field public static final int overScrollHeader = 16843458; // 0x10102c2
     field public static final int overScrollMode = 16843457; // 0x10102c1
-    field public static final int packageNames = 16843651; // 0x1010383
+    field public static final int packageNames = 16843650; // 0x1010382
     field public static final int padding = 16842965; // 0x10100d5
     field public static final int paddingBottom = 16842969; // 0x10100d9
-    field public static final int paddingEnd = 16843673; // 0x1010399
+    field public static final int paddingEnd = 16843672; // 0x1010398
     field public static final int paddingLeft = 16842966; // 0x10100d6
     field public static final int paddingRight = 16842968; // 0x10100d8
-    field public static final int paddingStart = 16843672; // 0x1010398
+    field public static final int paddingStart = 16843671; // 0x1010397
     field public static final int paddingTop = 16842967; // 0x10100d7
     field public static final int panelBackground = 16842846; // 0x101005e
     field public static final int panelColorBackground = 16842849; // 0x1010061
@@ -780,17 +790,17 @@
     field public static final int restoreAnyVersion = 16843450; // 0x10102ba
     field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
     field public static final int right = 16843183; // 0x10101af
-    field public static final int rightChevronDrawable = 16843659; // 0x101038b
+    field public static final int rightChevronDrawable = 16843658; // 0x101038a
     field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
     field public static final int ringtoneType = 16843257; // 0x10101f9
     field public static final int rotation = 16843558; // 0x1010326
     field public static final int rotationX = 16843559; // 0x1010327
     field public static final int rotationY = 16843560; // 0x1010328
-    field public static final int rowCount = 16843637; // 0x1010375
+    field public static final int rowCount = 16843636; // 0x1010374
     field public static final int rowDelay = 16843216; // 0x10101d0
     field public static final int rowEdgeFlags = 16843329; // 0x1010241
     field public static final int rowHeight = 16843058; // 0x1010132
-    field public static final int rowOrderPreserved = 16843638; // 0x1010376
+    field public static final int rowOrderPreserved = 16843637; // 0x1010375
     field public static final int saveEnabled = 16842983; // 0x10100e7
     field public static final int scaleGravity = 16843262; // 0x10101fe
     field public static final int scaleHeight = 16843261; // 0x10101fd
@@ -856,7 +866,7 @@
     field public static final int smallIcon = 16843422; // 0x101029e
     field public static final int smallScreens = 16843396; // 0x1010284
     field public static final int smoothScrollbar = 16843313; // 0x1010231
-    field public static final int snapMargin = 16843666; // 0x1010392
+    field public static final int snapMargin = 16843665; // 0x1010391
     field public static final int soundEffectsEnabled = 16843285; // 0x1010215
     field public static final int spacing = 16843027; // 0x1010113
     field public static final int spinnerDropDownItemStyle = 16842887; // 0x1010087
@@ -904,7 +914,7 @@
     field public static final int subtitleTextStyle = 16843513; // 0x10102f9
     field public static final int suggestActionMsg = 16843228; // 0x10101dc
     field public static final int suggestActionMsgColumn = 16843229; // 0x10101dd
-    field public static final int suggestionsEnabled = 16843636; // 0x1010374
+    field public static final int suggestionsEnabled = 16843635; // 0x1010373
     field public static final int summary = 16843241; // 0x10101e9
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
@@ -921,7 +931,7 @@
     field public static final int tag = 16842961; // 0x10100d1
     field public static final int targetActivity = 16843266; // 0x1010202
     field public static final int targetClass = 16842799; // 0x101002f
-    field public static final int targetDrawables = 16843656; // 0x1010388
+    field public static final int targetDrawables = 16843655; // 0x1010387
     field public static final int targetPackage = 16842785; // 0x1010021
     field public static final int targetSdkVersion = 16843376; // 0x1010270
     field public static final int taskAffinity = 16842770; // 0x1010012
@@ -936,6 +946,7 @@
     field public static final int tension = 16843370; // 0x101026a
     field public static final int testOnly = 16843378; // 0x1010272
     field public static final int text = 16843087; // 0x101014f
+    field public static final int textAllCaps = 16843680; // 0x10103a0
     field public static final int textAppearance = 16842804; // 0x1010034
     field public static final int textAppearanceButton = 16843271; // 0x1010207
     field public static final int textAppearanceInverse = 16842805; // 0x1010035
@@ -972,6 +983,7 @@
     field public static final int textColorTertiary = 16843282; // 0x1010212
     field public static final int textColorTertiaryInverse = 16843283; // 0x1010213
     field public static final int textCursorDrawable = 16843618; // 0x1010362
+    field public static final int textDirection = 16843676; // 0x101039c
     field public static final int textEditNoPasteWindowLayout = 16843541; // 0x1010315
     field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
     field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
@@ -1011,7 +1023,7 @@
     field public static final int toYScale = 16843205; // 0x10101c5
     field public static final int top = 16843182; // 0x10101ae
     field public static final int topBright = 16842955; // 0x10100cb
-    field public static final int topChevronDrawable = 16843660; // 0x101038c
+    field public static final int topChevronDrawable = 16843659; // 0x101038b
     field public static final int topDark = 16842951; // 0x10100c7
     field public static final int topLeftRadius = 16843177; // 0x10101a9
     field public static final int topOffset = 16843352; // 0x1010258
@@ -1027,7 +1039,7 @@
     field public static final int unfocusedMonthDateColor = 16843588; // 0x1010344
     field public static final int unselectedAlpha = 16843278; // 0x101020e
     field public static final int updatePeriodMillis = 16843344; // 0x1010250
-    field public static final int useDefaultMargins = 16843641; // 0x1010379
+    field public static final int useDefaultMargins = 16843640; // 0x1010378
     field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
     field public static final int useLevel = 16843167; // 0x101019f
     field public static final int userVisible = 16843409; // 0x1010291
@@ -1041,10 +1053,10 @@
     field public static final int verticalCorrection = 16843322; // 0x101023a
     field public static final int verticalDivider = 16843054; // 0x101012e
     field public static final int verticalGap = 16843328; // 0x1010240
-    field public static final int verticalOffset = 16843668; // 0x1010394
+    field public static final int verticalOffset = 16843667; // 0x1010393
     field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
     field public static final int verticalSpacing = 16843029; // 0x1010115
-    field public static final int vibrationDuration = 16843665; // 0x1010391
+    field public static final int vibrationDuration = 16843664; // 0x1010390
     field public static final int visibility = 16842972; // 0x10100dc
     field public static final int visible = 16843156; // 0x1010194
     field public static final int vmSafeMode = 16843448; // 0x10102b8
@@ -1061,7 +1073,7 @@
     field public static final int wallpaperIntraOpenExitAnimation = 16843416; // 0x1010298
     field public static final int wallpaperOpenEnterAnimation = 16843411; // 0x1010293
     field public static final int wallpaperOpenExitAnimation = 16843412; // 0x1010294
-    field public static final int waveDrawable = 16843662; // 0x101038e
+    field public static final int waveDrawable = 16843661; // 0x101038d
     field public static final int webTextViewStyle = 16843449; // 0x10102b9
     field public static final int webViewStyle = 16842885; // 0x1010085
     field public static final int weekDayTextAppearance = 16843592; // 0x1010348
@@ -1114,6 +1126,16 @@
     field public static final int background_light = 17170447; // 0x106000f
     field public static final int black = 17170444; // 0x106000c
     field public static final int darker_gray = 17170432; // 0x1060000
+    field public static final int holo_blue_bright = 17170459; // 0x106001b
+    field public static final int holo_blue_dark = 17170451; // 0x1060013
+    field public static final int holo_blue_light = 17170450; // 0x1060012
+    field public static final int holo_green_dark = 17170453; // 0x1060015
+    field public static final int holo_green_light = 17170452; // 0x1060014
+    field public static final int holo_orange_dark = 17170457; // 0x1060019
+    field public static final int holo_orange_light = 17170456; // 0x1060018
+    field public static final int holo_purple = 17170458; // 0x106001a
+    field public static final int holo_red_dark = 17170455; // 0x1060017
+    field public static final int holo_red_light = 17170454; // 0x1060016
     field public static final int primary_text_dark = 17170433; // 0x1060001
     field public static final int primary_text_dark_nodisable = 17170434; // 0x1060002
     field public static final int primary_text_light = 17170435; // 0x1060003
@@ -1506,10 +1528,15 @@
     field public static final int TextAppearance_Holo_Small = 16974081; // 0x1030101
     field public static final int TextAppearance_Holo_Small_Inverse = 16974082; // 0x1030102
     field public static final int TextAppearance_Holo_Widget = 16974085; // 0x1030105
+    field public static final int TextAppearance_Holo_Widget_ActionBar_Menu = 16974113; // 0x1030121
     field public static final int TextAppearance_Holo_Widget_ActionBar_Subtitle = 16974099; // 0x1030113
+    field public static final int TextAppearance_Holo_Widget_ActionBar_Subtitle_Inverse = 16974110; // 0x103011e
     field public static final int TextAppearance_Holo_Widget_ActionBar_Title = 16974098; // 0x1030112
+    field public static final int TextAppearance_Holo_Widget_ActionBar_Title_Inverse = 16974109; // 0x103011d
     field public static final int TextAppearance_Holo_Widget_ActionMode_Subtitle = 16974101; // 0x1030115
+    field public static final int TextAppearance_Holo_Widget_ActionMode_Subtitle_Inverse = 16974112; // 0x1030120
     field public static final int TextAppearance_Holo_Widget_ActionMode_Title = 16974100; // 0x1030114
+    field public static final int TextAppearance_Holo_Widget_ActionMode_Title_Inverse = 16974111; // 0x103011f
     field public static final int TextAppearance_Holo_Widget_Button = 16974086; // 0x1030106
     field public static final int TextAppearance_Holo_Widget_DropDownHint = 16974091; // 0x103010b
     field public static final int TextAppearance_Holo_Widget_DropDownItem = 16974092; // 0x103010c
@@ -1572,10 +1599,16 @@
     field public static final int Theme_Holo_Light_NoActionBar = 16974064; // 0x10300f0
     field public static final int Theme_Holo_Light_NoActionBar_Fullscreen = 16974065; // 0x10300f1
     field public static final int Theme_Holo_Light_Panel = 16973948; // 0x103007c
+    field public static final int Theme_Holo_Light_SolidActionBar = 16974122; // 0x103012a
+    field public static final int Theme_Holo_Light_SolidActionBar_Inverse = 16974123; // 0x103012b
+    field public static final int Theme_Holo_Light_SolidActionBar_Inverse_SplitActionBarWhenNarrow = 16974126; // 0x103012e
+    field public static final int Theme_Holo_Light_SolidActionBar_SplitActionBarWhenNarrow = 16974125; // 0x103012d
     field public static final int Theme_Holo_Light_SplitActionBarWhenNarrow = 16974106; // 0x103011a
     field public static final int Theme_Holo_NoActionBar = 16973932; // 0x103006c
     field public static final int Theme_Holo_NoActionBar_Fullscreen = 16973933; // 0x103006d
     field public static final int Theme_Holo_Panel = 16973947; // 0x103007b
+    field public static final int Theme_Holo_SolidActionBar = 16974121; // 0x1030129
+    field public static final int Theme_Holo_SolidActionBar_SplitActionBarWhenNarrow = 16974124; // 0x103012c
     field public static final int Theme_Holo_SplitActionBarWhenNarrow = 16974105; // 0x1030119
     field public static final int Theme_Holo_Wallpaper = 16973949; // 0x103007d
     field public static final int Theme_Holo_Wallpaper_NoTitleBar = 16973950; // 0x103007e
@@ -1627,6 +1660,7 @@
     field public static final int Widget_GridView = 16973874; // 0x1030032
     field public static final int Widget_Holo = 16973962; // 0x103008a
     field public static final int Widget_Holo_ActionBar = 16974004; // 0x10300b4
+    field public static final int Widget_Holo_ActionBar_Solid = 16974114; // 0x1030122
     field public static final int Widget_Holo_ActionBar_TabBar = 16974071; // 0x10300f7
     field public static final int Widget_Holo_ActionBar_TabText = 16974070; // 0x10300f6
     field public static final int Widget_Holo_ActionBar_TabView = 16974069; // 0x10300f5
@@ -1656,13 +1690,19 @@
     field public static final int Widget_Holo_ImageButton = 16973974; // 0x1030096
     field public static final int Widget_Holo_Light = 16974005; // 0x10300b5
     field public static final int Widget_Holo_Light_ActionBar = 16974049; // 0x10300e1
+    field public static final int Widget_Holo_Light_ActionBar_Solid = 16974115; // 0x1030123
+    field public static final int Widget_Holo_Light_ActionBar_Solid_Inverse = 16974116; // 0x1030124
     field public static final int Widget_Holo_Light_ActionBar_TabBar = 16974074; // 0x10300fa
+    field public static final int Widget_Holo_Light_ActionBar_TabBar_Inverse = 16974117; // 0x1030125
     field public static final int Widget_Holo_Light_ActionBar_TabText = 16974073; // 0x10300f9
+    field public static final int Widget_Holo_Light_ActionBar_TabText_Inverse = 16974119; // 0x1030127
     field public static final int Widget_Holo_Light_ActionBar_TabView = 16974072; // 0x10300f8
+    field public static final int Widget_Holo_Light_ActionBar_TabView_Inverse = 16974118; // 0x1030126
     field public static final int Widget_Holo_Light_ActionButton = 16974045; // 0x10300dd
     field public static final int Widget_Holo_Light_ActionButton_CloseMode = 16974048; // 0x10300e0
     field public static final int Widget_Holo_Light_ActionButton_Overflow = 16974046; // 0x10300de
     field public static final int Widget_Holo_Light_ActionMode = 16974047; // 0x10300df
+    field public static final int Widget_Holo_Light_ActionMode_Inverse = 16974120; // 0x1030128
     field public static final int Widget_Holo_Light_AutoCompleteTextView = 16974011; // 0x10300bb
     field public static final int Widget_Holo_Light_Button = 16974006; // 0x10300b6
     field public static final int Widget_Holo_Light_Button_Borderless_Small = 16974108; // 0x103011c
@@ -3367,6 +3407,7 @@
     method public void send(android.content.Context, int, android.content.Intent) throws android.app.PendingIntent.CanceledException;
     method public void send(int, android.app.PendingIntent.OnFinished, android.os.Handler) throws android.app.PendingIntent.CanceledException;
     method public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler) throws android.app.PendingIntent.CanceledException;
+    method public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler, java.lang.String) throws android.app.PendingIntent.CanceledException;
     method public static void writePendingIntentOrNullToParcel(android.app.PendingIntent, android.os.Parcel);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
@@ -3448,6 +3489,7 @@
     field public static final java.lang.String SUGGEST_COLUMN_INTENT_DATA = "suggest_intent_data";
     field public static final java.lang.String SUGGEST_COLUMN_INTENT_DATA_ID = "suggest_intent_data_id";
     field public static final java.lang.String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data";
+    field public static final java.lang.String SUGGEST_COLUMN_LAST_ACCESS_HINT = "suggest_last_access_hint";
     field public static final java.lang.String SUGGEST_COLUMN_QUERY = "suggest_intent_query";
     field public static final java.lang.String SUGGEST_COLUMN_SHORTCUT_ID = "suggest_shortcut_id";
     field public static final java.lang.String SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING = "suggest_spinner_while_refreshing";
@@ -3730,7 +3772,11 @@
     method public abstract void onBackup(android.os.ParcelFileDescriptor, android.app.backup.BackupDataOutput, android.os.ParcelFileDescriptor) throws java.io.IOException;
     method public void onCreate();
     method public void onDestroy();
+    method public void onFullBackup(android.app.backup.FullBackupDataOutput) throws java.io.IOException;
     method public abstract void onRestore(android.app.backup.BackupDataInput, int, android.os.ParcelFileDescriptor) throws java.io.IOException;
+    method public void onRestoreFile(android.os.ParcelFileDescriptor, long, java.io.File, int, long, long) throws java.io.IOException;
+    field public static final int TYPE_DIRECTORY = 2; // 0x2
+    field public static final int TYPE_FILE = 1; // 0x1
   }
 
   public class BackupAgentHelper extends android.app.backup.BackupAgent {
@@ -3782,6 +3828,9 @@
     method public void writeNewStateDescription(android.os.ParcelFileDescriptor);
   }
 
+  public class FullBackupDataOutput {
+  }
+
   public abstract class RestoreObserver {
     ctor public RestoreObserver();
     method public void onUpdate(int, java.lang.String);
@@ -5293,6 +5342,7 @@
     method public java.lang.String getTargetPackage();
     method public static android.content.IntentSender readIntentSenderOrNullFromParcel(android.os.Parcel);
     method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler) throws android.content.IntentSender.SendIntentException;
+    method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler, java.lang.String) throws android.content.IntentSender.SendIntentException;
     method public static void writeIntentSenderOrNullToParcel(android.content.IntentSender, android.os.Parcel);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
@@ -5893,6 +5943,7 @@
     field public long codeSize;
     field public long dataSize;
     field public long externalCacheSize;
+    field public long externalCodeSize;
     field public long externalDataSize;
     field public long externalMediaSize;
     field public long externalObbSize;
@@ -7417,6 +7468,7 @@
     method public static final android.graphics.Bitmap.CompressFormat[] values();
     enum_constant public static final android.graphics.Bitmap.CompressFormat JPEG;
     enum_constant public static final android.graphics.Bitmap.CompressFormat PNG;
+    enum_constant public static final android.graphics.Bitmap.CompressFormat WEBP;
   }
 
   public static final class Bitmap.Config extends java.lang.Enum {
@@ -7570,6 +7622,8 @@
     method public int getHeight();
     method public void getMatrix(android.graphics.Matrix);
     method public final android.graphics.Matrix getMatrix();
+    method public int getMaximumBitmapHeight();
+    method public int getMaximumBitmapWidth();
     method public int getSaveCount();
     method public int getWidth();
     method public boolean isHardwareAccelerated();
@@ -9393,6 +9447,7 @@
     method public void onUpdateExtractingViews(android.view.inputmethod.EditorInfo);
     method public void onUpdateExtractingVisibility(android.view.inputmethod.EditorInfo);
     method public void onUpdateSelection(int, int, int, int, int, int);
+    method public void onViewClicked(boolean);
     method public void onWindowHidden();
     method public void onWindowShown();
     method public void requestHideSelf(int);
@@ -9436,6 +9491,7 @@
     method public void updateCursor(android.graphics.Rect);
     method public void updateExtractedText(int, android.view.inputmethod.ExtractedText);
     method public void updateSelection(int, int, int, int, int, int);
+    method public void viewClicked(boolean);
   }
 
   public static final class InputMethodService.Insets {
@@ -11236,7 +11292,8 @@
     method public static long getUidUdpRxPackets(int);
     method public static long getUidUdpTxBytes(int);
     method public static long getUidUdpTxPackets(int);
-    method public static void setThreadStatsTag(java.lang.String);
+    method public static void setThreadStatsTag(int);
+    method public static deprecated void setThreadStatsTag(java.lang.String);
     method public static void tagSocket(java.net.Socket) throws java.net.SocketException;
     method public static void untagSocket(java.net.Socket) throws java.net.SocketException;
     field public static final int UNSUPPORTED = -1; // 0xffffffff
@@ -11442,11 +11499,14 @@
   }
 
   public class SslError {
-    ctor public SslError(int, android.net.http.SslCertificate);
-    ctor public SslError(int, java.security.cert.X509Certificate);
+    ctor public deprecated SslError(int, android.net.http.SslCertificate);
+    ctor public deprecated SslError(int, java.security.cert.X509Certificate);
+    ctor public SslError(int, android.net.http.SslCertificate, java.lang.String);
+    ctor public SslError(int, java.security.cert.X509Certificate, java.lang.String);
     method public boolean addError(int);
     method public android.net.http.SslCertificate getCertificate();
     method public int getPrimaryError();
+    method public java.lang.String getUrl();
     method public boolean hasError(int);
     field public static final int SSL_EXPIRED = 1; // 0x1
     field public static final int SSL_IDMISMATCH = 2; // 0x2
@@ -14332,7 +14392,7 @@
     method public static final void sendSignal(int, int);
     method public static final void setThreadPriority(int, int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
     method public static final void setThreadPriority(int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
-    method public static final boolean supportsProcesses();
+    method public static final deprecated boolean supportsProcesses();
     field public static final int BLUETOOTH_GID = 2000; // 0x7d0
     field public static final int FIRST_APPLICATION_UID = 10000; // 0x2710
     field public static final int LAST_APPLICATION_UID = 99999; // 0x1869f
@@ -14954,6 +15014,257 @@
     field public static final deprecated java.lang.String URL = "url";
   }
 
+  public final class CalendarContract {
+    field public static final java.lang.String ACCOUNT_TYPE_LOCAL = "LOCAL";
+    field public static final java.lang.String ACTION_EVENT_REMINDER = "android.intent.action.EVENT_REMINDER";
+    field public static final java.lang.String AUTHORITY = "com.android.calendar";
+    field public static final java.lang.String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String EXTRA_EVENT_BEGIN_TIME = "beginTime";
+    field public static final java.lang.String EXTRA_EVENT_END_TIME = "endTime";
+  }
+
+  public static final class CalendarContract.Attendees implements android.provider.BaseColumns android.provider.CalendarContract.AttendeesColumns android.provider.CalendarContract.EventsColumns {
+    method public static final android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.AttendeesColumns {
+    field public static final java.lang.String ATTENDEE_EMAIL = "attendeeEmail";
+    field public static final java.lang.String ATTENDEE_NAME = "attendeeName";
+    field public static final java.lang.String ATTENDEE_RELATIONSHIP = "attendeeRelationship";
+    field public static final java.lang.String ATTENDEE_STATUS = "attendeeStatus";
+    field public static final int ATTENDEE_STATUS_ACCEPTED = 1; // 0x1
+    field public static final int ATTENDEE_STATUS_DECLINED = 2; // 0x2
+    field public static final int ATTENDEE_STATUS_INVITED = 3; // 0x3
+    field public static final int ATTENDEE_STATUS_NONE = 0; // 0x0
+    field public static final int ATTENDEE_STATUS_TENTATIVE = 4; // 0x4
+    field public static final java.lang.String ATTENDEE_TYPE = "attendeeType";
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final int RELATIONSHIP_ATTENDEE = 1; // 0x1
+    field public static final int RELATIONSHIP_NONE = 0; // 0x0
+    field public static final int RELATIONSHIP_ORGANIZER = 2; // 0x2
+    field public static final int RELATIONSHIP_PERFORMER = 3; // 0x3
+    field public static final int RELATIONSHIP_SPEAKER = 4; // 0x4
+    field public static final int TYPE_NONE = 0; // 0x0
+    field public static final int TYPE_OPTIONAL = 2; // 0x2
+    field public static final int TYPE_REQUIRED = 1; // 0x1
+  }
+
+  public static final class CalendarContract.CalendarAlerts implements android.provider.BaseColumns android.provider.CalendarContract.CalendarAlertsColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns {
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final android.net.Uri CONTENT_URI_BY_INSTANCE;
+  }
+
+  protected static abstract interface CalendarContract.CalendarAlertsColumns {
+    field public static final java.lang.String ALARM_TIME = "alarmTime";
+    field public static final java.lang.String BEGIN = "begin";
+    field public static final java.lang.String CREATION_TIME = "creationTime";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "begin ASC,title ASC";
+    field public static final java.lang.String END = "end";
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final java.lang.String MINUTES = "minutes";
+    field public static final java.lang.String NOTIFY_TIME = "notifyTime";
+    field public static final java.lang.String RECEIVED_TIME = "receivedTime";
+    field public static final java.lang.String STATE = "state";
+    field public static final int STATE_DISMISSED = 2; // 0x2
+    field public static final int STATE_FIRED = 1; // 0x1
+    field public static final int STATE_SCHEDULED = 0; // 0x0
+  }
+
+  public static final class CalendarContract.CalendarCache implements android.provider.CalendarContract.CalendarCacheColumns {
+    field public static final java.lang.String KEY_TIMEZONE_INSTANCES = "timezoneInstances";
+    field public static final java.lang.String KEY_TIMEZONE_INSTANCES_PREVIOUS = "timezoneInstancesPrevious";
+    field public static final java.lang.String KEY_TIMEZONE_TYPE = "timezoneType";
+    field public static final java.lang.String TIMEZONE_TYPE_AUTO = "auto";
+    field public static final java.lang.String TIMEZONE_TYPE_HOME = "home";
+    field public static final android.net.Uri URI;
+  }
+
+  protected static abstract interface CalendarContract.CalendarCacheColumns {
+    field public static final java.lang.String KEY = "key";
+    field public static final java.lang.String VALUE = "value";
+  }
+
+  protected static abstract interface CalendarContract.CalendarColumns {
+    field public static final java.lang.String ALLOWED_REMINDERS = "allowedReminders";
+    field public static final java.lang.String CALENDAR_ACCESS_LEVEL = "calendar_access_level";
+    field public static final java.lang.String CALENDAR_COLOR = "calendar_color";
+    field public static final java.lang.String CALENDAR_DISPLAY_NAME = "calendar_displayName";
+    field public static final java.lang.String CALENDAR_TIME_ZONE = "calendar_timezone";
+    field public static final int CAL_ACCESS_CONTRIBUTOR = 500; // 0x1f4
+    field public static final int CAL_ACCESS_EDITOR = 600; // 0x258
+    field public static final int CAL_ACCESS_FREEBUSY = 100; // 0x64
+    field public static final int CAL_ACCESS_NONE = 0; // 0x0
+    field public static final int CAL_ACCESS_OVERRIDE = 400; // 0x190
+    field public static final int CAL_ACCESS_OWNER = 700; // 0x2bc
+    field public static final int CAL_ACCESS_READ = 200; // 0xc8
+    field public static final int CAL_ACCESS_RESPOND = 300; // 0x12c
+    field public static final int CAL_ACCESS_ROOT = 800; // 0x320
+    field public static final java.lang.String CAN_MODIFY_TIME_ZONE = "canModifyTimeZone";
+    field public static final java.lang.String CAN_ORGANIZER_RESPOND = "canOrganizerRespond";
+    field public static final java.lang.String MAX_REMINDERS = "maxReminders";
+    field public static final java.lang.String OWNER_ACCOUNT = "ownerAccount";
+    field public static final java.lang.String SYNC_EVENTS = "sync_events";
+    field public static final java.lang.String VISIBLE = "visible";
+  }
+
+  public static final class CalendarContract.CalendarEntity implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.SyncColumns {
+    method public static android.content.EntityIterator newEntityIterator(android.database.Cursor);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.CalendarSyncColumns {
+    field public static final java.lang.String CAL_SYNC1 = "cal_sync1";
+    field public static final java.lang.String CAL_SYNC10 = "cal_sync10";
+    field public static final java.lang.String CAL_SYNC2 = "cal_sync2";
+    field public static final java.lang.String CAL_SYNC3 = "cal_sync3";
+    field public static final java.lang.String CAL_SYNC4 = "cal_sync4";
+    field public static final java.lang.String CAL_SYNC5 = "cal_sync5";
+    field public static final java.lang.String CAL_SYNC6 = "cal_sync6";
+    field public static final java.lang.String CAL_SYNC7 = "cal_sync7";
+    field public static final java.lang.String CAL_SYNC8 = "cal_sync8";
+    field public static final java.lang.String CAL_SYNC9 = "cal_sync9";
+  }
+
+  public static final class CalendarContract.Calendars implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.SyncColumns {
+    field public static final java.lang.String CALENDAR_LOCATION = "calendar_location";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "displayName";
+    field public static final java.lang.String NAME = "name";
+  }
+
+  public static final class CalendarContract.EventDays implements android.provider.CalendarContract.EventDaysColumns {
+    method public static final android.database.Cursor query(android.content.ContentResolver, int, int, java.lang.String[]);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.EventDaysColumns {
+    field public static final java.lang.String ENDDAY = "endDay";
+    field public static final java.lang.String STARTDAY = "startDay";
+  }
+
+  public static final class CalendarContract.Events implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.SyncColumns {
+    field public static final android.net.Uri CONTENT_EXCEPTION_URI;
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.EventsColumns {
+    field public static final int ACCESS_CONFIDENTIAL = 1; // 0x1
+    field public static final int ACCESS_DEFAULT = 0; // 0x0
+    field public static final java.lang.String ACCESS_LEVEL = "accessLevel";
+    field public static final int ACCESS_PRIVATE = 2; // 0x2
+    field public static final int ACCESS_PUBLIC = 3; // 0x3
+    field public static final java.lang.String ALL_DAY = "allDay";
+    field public static final java.lang.String AVAILABILITY = "availability";
+    field public static final int AVAILABILITY_BUSY = 0; // 0x0
+    field public static final int AVAILABILITY_FREE = 1; // 0x1
+    field public static final java.lang.String CALENDAR_ID = "calendar_id";
+    field public static final java.lang.String CAN_INVITE_OTHERS = "canInviteOthers";
+    field public static final java.lang.String DESCRIPTION = "description";
+    field public static final java.lang.String DTEND = "dtend";
+    field public static final java.lang.String DTSTART = "dtstart";
+    field public static final java.lang.String DURATION = "duration";
+    field public static final java.lang.String EVENT_COLOR = "eventColor";
+    field public static final java.lang.String EVENT_END_TIMEZONE = "eventEndTimezone";
+    field public static final java.lang.String EVENT_LOCATION = "eventLocation";
+    field public static final java.lang.String EVENT_TIMEZONE = "eventTimezone";
+    field public static final java.lang.String EXDATE = "exdate";
+    field public static final java.lang.String EXRULE = "exrule";
+    field public static final java.lang.String GUESTS_CAN_INVITE_OTHERS = "guestsCanInviteOthers";
+    field public static final java.lang.String GUESTS_CAN_MODIFY = "guestsCanModify";
+    field public static final java.lang.String GUESTS_CAN_SEE_GUESTS = "guestsCanSeeGuests";
+    field public static final java.lang.String HAS_ALARM = "hasAlarm";
+    field public static final java.lang.String HAS_ATTENDEE_DATA = "hasAttendeeData";
+    field public static final java.lang.String HAS_EXTENDED_PROPERTIES = "hasExtendedProperties";
+    field public static final java.lang.String LAST_DATE = "lastDate";
+    field public static final java.lang.String LAST_SYNCED = "lastSynced";
+    field public static final java.lang.String ORGANIZER = "organizer";
+    field public static final java.lang.String ORIGINAL_ALL_DAY = "originalAllDay";
+    field public static final java.lang.String ORIGINAL_ID = "original_id";
+    field public static final java.lang.String ORIGINAL_INSTANCE_TIME = "originalInstanceTime";
+    field public static final java.lang.String ORIGINAL_SYNC_ID = "original_sync_id";
+    field public static final java.lang.String RDATE = "rdate";
+    field public static final java.lang.String RRULE = "rrule";
+    field public static final java.lang.String SELF_ATTENDEE_STATUS = "selfAttendeeStatus";
+    field public static final java.lang.String STATUS = "eventStatus";
+    field public static final int STATUS_CANCELED = 2; // 0x2
+    field public static final int STATUS_CONFIRMED = 1; // 0x1
+    field public static final int STATUS_TENTATIVE = 0; // 0x0
+    field public static final java.lang.String SYNC_DATA1 = "sync_data1";
+    field public static final java.lang.String SYNC_DATA10 = "sync_data10";
+    field public static final java.lang.String SYNC_DATA2 = "sync_data2";
+    field public static final java.lang.String SYNC_DATA3 = "sync_data3";
+    field public static final java.lang.String SYNC_DATA4 = "sync_data4";
+    field public static final java.lang.String SYNC_DATA5 = "sync_data5";
+    field public static final java.lang.String SYNC_DATA6 = "sync_data6";
+    field public static final java.lang.String SYNC_DATA7 = "sync_data7";
+    field public static final java.lang.String SYNC_DATA8 = "sync_data8";
+    field public static final java.lang.String SYNC_DATA9 = "sync_data9";
+    field public static final java.lang.String TITLE = "title";
+  }
+
+  public static final class CalendarContract.EventsEntity implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.SyncColumns {
+    method public static android.content.EntityIterator newEntityIterator(android.database.Cursor, android.content.ContentResolver);
+    method public static android.content.EntityIterator newEntityIterator(android.database.Cursor, android.content.ContentProviderClient);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  public static final class CalendarContract.ExtendedProperties implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.ExtendedPropertiesColumns {
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.ExtendedPropertiesColumns {
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final java.lang.String NAME = "name";
+    field public static final java.lang.String VALUE = "value";
+  }
+
+  public static final class CalendarContract.Instances implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns {
+    method public static final android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long);
+    method public static final android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long, java.lang.String);
+    field public static final java.lang.String BEGIN = "begin";
+    field public static final android.net.Uri CONTENT_BY_DAY_URI;
+    field public static final android.net.Uri CONTENT_SEARCH_BY_DAY_URI;
+    field public static final android.net.Uri CONTENT_SEARCH_URI;
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String END = "end";
+    field public static final java.lang.String END_DAY = "endDay";
+    field public static final java.lang.String END_MINUTE = "endMinute";
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final java.lang.String START_DAY = "startDay";
+    field public static final java.lang.String START_MINUTE = "startMinute";
+  }
+
+  public static final class CalendarContract.Reminders implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.RemindersColumns {
+    method public static final android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.RemindersColumns {
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final java.lang.String METHOD = "method";
+    field public static final int METHOD_ALERT = 1; // 0x1
+    field public static final int METHOD_DEFAULT = 0; // 0x0
+    field public static final int METHOD_EMAIL = 2; // 0x2
+    field public static final int METHOD_SMS = 3; // 0x3
+    field public static final java.lang.String MINUTES = "minutes";
+    field public static final int MINUTES_DEFAULT = -1; // 0xffffffff
+  }
+
+  protected static abstract interface CalendarContract.SyncColumns implements android.provider.CalendarContract.CalendarSyncColumns {
+    field public static final java.lang.String ACCOUNT_NAME = "account_name";
+    field public static final java.lang.String ACCOUNT_TYPE = "account_type";
+    field public static final java.lang.String CAN_PARTIALLY_UPDATE = "canPartiallyUpdate";
+    field public static final java.lang.String DELETED = "deleted";
+    field public static final java.lang.String DIRTY = "dirty";
+    field public static final java.lang.String _SYNC_ID = "_sync_id";
+  }
+
+  public static final class CalendarContract.SyncState implements android.provider.SyncStateContract.Columns {
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
   public class CallLog {
     ctor public CallLog();
     field public static final java.lang.String AUTHORITY = "call_log";
@@ -15277,11 +15588,11 @@
 
   public final class ContactsContract {
     ctor public ContactsContract();
+    field public static final java.lang.String ALLOW_PROFILE = "allow_profile";
     field public static final java.lang.String AUTHORITY = "com.android.contacts";
     field public static final android.net.Uri AUTHORITY_URI;
     field public static final java.lang.String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
     field public static final java.lang.String DIRECTORY_PARAM_KEY = "directory";
-    field public static final java.lang.String INCLUDE_PROFILE = "include_profile";
     field public static final java.lang.String LIMIT_PARAM_KEY = "limit";
     field public static final java.lang.String PRIMARY_ACCOUNT_NAME = "name_for_primary_account";
     field public static final java.lang.String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account";
@@ -15579,6 +15890,10 @@
     field public static final java.lang.String PHOTO = "data15";
   }
 
+  public static final class ContactsContract.Contacts.StreamItems implements android.provider.ContactsContract.StreamItemsColumns {
+    field public static final java.lang.String CONTENT_DIRECTORY = "stream_items";
+  }
+
   protected static abstract interface ContactsContract.ContactsColumns {
     field public static final java.lang.String DISPLAY_NAME = "display_name";
     field public static final java.lang.String HAS_PHONE_NUMBER = "has_phone_number";
@@ -15812,6 +16127,10 @@
     field public static final java.lang.String DATA_ID = "data_id";
   }
 
+  public static final class ContactsContract.RawContacts.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
+    field public static final java.lang.String CONTENT_DIRECTORY = "stream_items";
+  }
+
   protected static abstract interface ContactsContract.RawContactsColumns {
     field public static final java.lang.String AGGREGATION_MODE = "aggregation_mode";
     field public static final java.lang.String CONTACT_ID = "contact_id";
@@ -15871,6 +16190,41 @@
     field public static final android.net.Uri CONTENT_URI;
   }
 
+  public static final class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
+  }
+
+  protected static abstract interface ContactsContract.StreamItemPhotosColumns {
+    field public static final java.lang.String ACTION = "action";
+    field public static final java.lang.String ACTION_URI = "action_uri";
+    field public static final java.lang.String PICTURE = "picture";
+    field public static final java.lang.String SORT_INDEX = "sort_index";
+    field public static final java.lang.String STREAM_ITEM_ID = "stream_item_id";
+  }
+
+  public static final class ContactsContract.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
+    field public static final android.net.Uri CONTENT_LIMIT_URI;
+    field public static final android.net.Uri CONTENT_PHOTO_URI;
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String MAX_ITEMS = "max_items";
+    field public static final java.lang.String PHOTO_MAX_BYTES = "photo_max_bytes";
+  }
+
+  public static final class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
+    field public static final java.lang.String CONTENT_DIRECTORY = "photo";
+  }
+
+  protected static abstract interface ContactsContract.StreamItemsColumns {
+    field public static final java.lang.String ACTION = "action";
+    field public static final java.lang.String ACTION_URI = "action_uri";
+    field public static final java.lang.String COMMENTS = "comments";
+    field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id";
+    field public static final java.lang.String RES_ICON = "icon";
+    field public static final java.lang.String RES_LABEL = "label";
+    field public static final java.lang.String RES_PACKAGE = "res_package";
+    field public static final java.lang.String TEXT = "text";
+    field public static final java.lang.String TIMESTAMP = "timestamp";
+  }
+
   protected static abstract interface ContactsContract.SyncColumns implements android.provider.ContactsContract.BaseSyncColumns {
     field public static final java.lang.String ACCOUNT_NAME = "account_name";
     field public static final java.lang.String ACCOUNT_TYPE = "account_type";
@@ -16594,23 +16948,12 @@
   }
 
   public class AllocationAdapter extends android.renderscript.Allocation {
+    method public static android.renderscript.AllocationAdapter create1D(android.renderscript.RenderScript, android.renderscript.Allocation);
     method public static android.renderscript.AllocationAdapter create2D(android.renderscript.RenderScript, android.renderscript.Allocation);
-    method public void readData(int[]);
-    method public void readData(float[]);
     method public void setFace(android.renderscript.Type.CubemapFace);
     method public void setLOD(int);
     method public void setY(int);
     method public void setZ(int);
-    method public void subData(int, android.renderscript.FieldPacker);
-    method public void subData1D(int, int, int[]);
-    method public void subData1D(int, int, short[]);
-    method public void subData1D(int, int, byte[]);
-    method public void subData1D(int, int, float[]);
-    method public void subData1D(int, int, android.renderscript.AllocationAdapter, int);
-    method public void subData2D(int, int, int, int, int[]);
-    method public void subData2D(int, int, int, int, float[]);
-    method public void subData2D(int, int, int, int, android.renderscript.AllocationAdapter, int, int);
-    method public void subElementData(int, int, android.renderscript.FieldPacker);
   }
 
   public class BaseObj {
@@ -17492,9 +17835,13 @@
 
   public final class KeyChain {
     ctor public KeyChain();
-    method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int);
+    method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
+    method public static android.content.Intent createInstallIntent();
     method public static java.security.cert.X509Certificate[] getCertificateChain(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
     method public static java.security.PrivateKey getPrivateKey(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
+    field public static final java.lang.String EXTRA_CERTIFICATE = "CERT";
+    field public static final java.lang.String EXTRA_NAME = "name";
+    field public static final java.lang.String EXTRA_PKCS12 = "PKCS12";
   }
 
   public abstract interface KeyChainAliasCallback {
@@ -20553,6 +20900,12 @@
     method public abstract boolean onPrepareActionMode(android.view.ActionMode, android.view.Menu);
   }
 
+  public abstract class ActionProvider {
+    ctor public ActionProvider(android.content.Context);
+    method public abstract android.view.View onCreateActionView();
+    method public void onPerformDefaultAction(android.view.View);
+  }
+
   public abstract interface ContextMenu implements android.view.Menu {
     method public abstract void clearHeader();
     method public abstract android.view.ContextMenu setHeaderIcon(int);
@@ -21221,6 +21574,7 @@
   public abstract interface MenuItem {
     method public abstract boolean collapseActionView();
     method public abstract boolean expandActionView();
+    method public abstract android.view.ActionProvider getActionProvider();
     method public abstract android.view.View getActionView();
     method public abstract char getAlphabeticShortcut();
     method public abstract int getGroupId();
@@ -21239,6 +21593,7 @@
     method public abstract boolean isChecked();
     method public abstract boolean isEnabled();
     method public abstract boolean isVisible();
+    method public abstract android.view.MenuItem setActionProvider(android.view.ActionProvider);
     method public abstract android.view.MenuItem setActionView(android.view.View);
     method public abstract android.view.MenuItem setActionView(int);
     method public abstract android.view.MenuItem setAlphabeticShortcut(char);
@@ -21422,7 +21777,6 @@
     field public static final int AXIS_Y = 1; // 0x1
     field public static final int AXIS_Z = 11; // 0xb
     field public static final int BUTTON_BACK = 8; // 0x8
-    field public static final int BUTTON_ERASER = 32; // 0x20
     field public static final int BUTTON_FORWARD = 16; // 0x10
     field public static final int BUTTON_PRIMARY = 1; // 0x1
     field public static final int BUTTON_SECONDARY = 2; // 0x2
@@ -21871,6 +22225,7 @@
     method public boolean isHovered();
     method public boolean isInEditMode();
     method public boolean isInTouchMode();
+    method protected static boolean isLayoutDirectionRtl(java.util.Locale);
     method public boolean isLayoutRequested();
     method public boolean isLongClickable();
     method public boolean isOpaque();
@@ -21956,8 +22311,10 @@
     method public void requestLayout();
     method public boolean requestRectangleOnScreen(android.graphics.Rect);
     method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
+    method protected void resetResolvedTextDirection();
     method public static int resolveSize(int, int);
     method public static int resolveSizeAndState(int, int, int);
+    method protected void resolveTextDirection();
     method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
     method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
     method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
@@ -22007,6 +22364,7 @@
     method public void setOnDragListener(android.view.View.OnDragListener);
     method public void setOnFocusChangeListener(android.view.View.OnFocusChangeListener);
     method public void setOnGenericMotionListener(android.view.View.OnGenericMotionListener);
+    method public void setOnHoverListener(android.view.View.OnHoverListener);
     method public void setOnKeyListener(android.view.View.OnKeyListener);
     method public void setOnLongClickListener(android.view.View.OnLongClickListener);
     method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
@@ -22056,6 +22414,8 @@
     method public boolean willNotCacheDrawing();
     method public boolean willNotDraw();
     field public static android.util.Property ALPHA;
+    field protected static int DEFAULT_TEXT_DIRECTION;
+    field protected static float DEFAULT_TEXT_DIRECTION_CHAR_COUNT_THRESHOLD;
     field public static final int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
     field public static final int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
     field public static final int DRAWING_CACHE_QUALITY_LOW = 524288; // 0x80000
@@ -22245,6 +22605,7 @@
     method public static deprecated int getTouchSlop();
     method public static deprecated int getWindowTouchSlop();
     method public static long getZoomControlsTimeout();
+    method public boolean hasPermanentMenuKey();
   }
 
   public class ViewDebug {
@@ -22379,6 +22740,7 @@
     method public void requestDisallowInterceptTouchEvent(boolean);
     method public boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
     method public void requestTransparentRegion(android.view.View);
+    method protected void resetResolvedLayoutDirection();
     method public void scheduleLayoutAnimation();
     method public void setAddStatesFromChildren(boolean);
     method public void setAlwaysDrawnWithCacheEnabled(boolean);
@@ -22845,8 +23207,10 @@
     field public static final int TYPE_VIEW_HOVER_ENTER = 128; // 0x80
     field public static final int TYPE_VIEW_HOVER_EXIT = 256; // 0x100
     field public static final int TYPE_VIEW_LONG_CLICKED = 2; // 0x2
+    field public static final int TYPE_VIEW_SCROLLED = 4096; // 0x1000
     field public static final int TYPE_VIEW_SELECTED = 4; // 0x4
     field public static final int TYPE_VIEW_TEXT_CHANGED = 16; // 0x10
+    field public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192; // 0x2000
     field public static final int TYPE_WINDOW_CONTENT_CHANGED = 2048; // 0x800
     field public static final int TYPE_WINDOW_STATE_CHANGED = 32; // 0x20
   }
@@ -22895,6 +23259,7 @@
     method public boolean isFocused();
     method public boolean isLongClickable();
     method public boolean isPassword();
+    method public boolean isScrollable();
     method public boolean isSelected();
     method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View);
     method public static android.view.accessibility.AccessibilityNodeInfo obtain();
@@ -22914,6 +23279,7 @@
     method public void setPackageName(java.lang.CharSequence);
     method public void setParent(android.view.View);
     method public void setPassword(boolean);
+    method public void setScrollable(boolean);
     method public void setSelected(boolean);
     method public void setSource(android.view.View);
     method public void setText(java.lang.CharSequence);
@@ -22935,13 +23301,17 @@
     method public int getItemCount();
     method public android.os.Parcelable getParcelableData();
     method public int getRemovedCount();
+    method public int getScrollX();
+    method public int getScrollY();
     method public android.view.accessibility.AccessibilityNodeInfo getSource();
     method public java.util.List<java.lang.CharSequence> getText();
+    method public int getToIndex();
     method public int getWindowId();
     method public boolean isChecked();
     method public boolean isEnabled();
     method public boolean isFullScreen();
     method public boolean isPassword();
+    method public boolean isScrollable();
     method public static android.view.accessibility.AccessibilityRecord obtain(android.view.accessibility.AccessibilityRecord);
     method public static android.view.accessibility.AccessibilityRecord obtain();
     method public void recycle();
@@ -22958,7 +23328,11 @@
     method public void setParcelableData(android.os.Parcelable);
     method public void setPassword(boolean);
     method public void setRemovedCount(int);
+    method public void setScrollX(int);
+    method public void setScrollY(int);
+    method public void setScrollable(boolean);
     method public void setSource(android.view.View);
+    method public void setToIndex(int);
   }
 
 }
@@ -23491,6 +23865,7 @@
     method public void updateCursor(android.view.View, int, int, int, int);
     method public void updateExtractedText(android.view.View, int, android.view.inputmethod.ExtractedText);
     method public void updateSelection(android.view.View, int, int, int, int);
+    method public void viewClicked(android.view.View);
     field public static final int HIDE_IMPLICIT_ONLY = 1; // 0x1
     field public static final int HIDE_NOT_ALWAYS = 2; // 0x2
     field public static final int RESULT_HIDDEN = 3; // 0x3
@@ -23511,6 +23886,7 @@
     method public abstract void updateCursor(android.graphics.Rect);
     method public abstract void updateExtractedText(int, android.view.inputmethod.ExtractedText);
     method public abstract void updateSelection(int, int, int, int, int, int);
+    method public abstract void viewClicked(boolean);
   }
 
   public static abstract interface InputMethodSession.EventCallback {
@@ -24857,9 +25233,9 @@
   }
 
   public class GridLayout extends android.view.ViewGroup {
-    ctor public GridLayout(android.content.Context);
     ctor public GridLayout(android.content.Context, android.util.AttributeSet, int);
     ctor public GridLayout(android.content.Context, android.util.AttributeSet);
+    ctor public GridLayout(android.content.Context);
     method public int getAlignmentMode();
     method public int getColumnCount();
     method public int getOrientation();
@@ -24879,6 +25255,7 @@
     field public static final int ALIGN_MARGINS = 1; // 0x1
     field public static final android.widget.GridLayout.Alignment BASELINE;
     field public static final android.widget.GridLayout.Alignment BOTTOM;
+    field public static final int CAN_STRETCH = 2; // 0x2
     field public static final android.widget.GridLayout.Alignment CENTER;
     field public static final android.widget.GridLayout.Alignment FILL;
     field public static final int HORIZONTAL = 0; // 0x0
@@ -24896,6 +25273,7 @@
     ctor public GridLayout.Group(int, int, android.widget.GridLayout.Alignment);
     ctor public GridLayout.Group(int, android.widget.GridLayout.Alignment);
     field public final android.widget.GridLayout.Alignment alignment;
+    field public int flexibility;
   }
 
   public static class GridLayout.LayoutParams extends android.view.ViewGroup.MarginLayoutParams {
@@ -24907,9 +25285,7 @@
     ctor public GridLayout.LayoutParams(android.content.Context, android.util.AttributeSet);
     method public void setGravity(int);
     field public android.widget.GridLayout.Group columnGroup;
-    field public float columnWeight;
     field public android.widget.GridLayout.Group rowGroup;
-    field public float rowWeight;
   }
 
   public class GridView extends android.widget.AbsListView {
@@ -25696,6 +26072,14 @@
     method public abstract void onStopTrackingTouch(android.widget.SeekBar);
   }
 
+  public class ShareActionProvider extends android.view.ActionProvider {
+    ctor public ShareActionProvider(android.content.Context);
+    method public android.view.View onCreateActionView();
+    method public void setShareHistoryFileName(java.lang.String);
+    method public void setShareIntent(android.view.View, android.content.Intent);
+    field public static final java.lang.String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
+  }
+
   public class SimpleAdapter extends android.widget.BaseAdapter implements android.widget.Filterable {
     ctor public SimpleAdapter(android.content.Context, java.util.List<? extends java.util.Map<java.lang.String, ?>>, int, java.lang.String[], int[]);
     method public int getCount();
@@ -26033,6 +26417,8 @@
     method protected void onTextChanged(java.lang.CharSequence, int, int, int);
     method public boolean onTextContextMenuItem(int);
     method public void removeTextChangedListener(android.text.TextWatcher);
+    method protected void resetResolvedLayoutDirection();
+    method public void setAllCaps(boolean);
     method public final void setAutoLinkMask(int);
     method public void setCompoundDrawablePadding(int);
     method public void setCompoundDrawables(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 152a7cb..f2be29f 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -82,35 +82,27 @@
     virtual void onStarted()
     {
         sp<ProcessState> proc = ProcessState::self();
-        if (proc->supportsProcesses()) {
-            LOGV("App process: starting thread pool.\n");
-            proc->startThreadPool();
-        }
+        LOGV("App process: starting thread pool.\n");
+        proc->startThreadPool();
 
         AndroidRuntime* ar = AndroidRuntime::getRuntime();
         ar->callMain(mClassName, mClass, mArgC, mArgV);
 
-        if (ProcessState::self()->supportsProcesses()) {
-            IPCThreadState::self()->stopProcess();
-        }
+        IPCThreadState::self()->stopProcess();
     }
 
     virtual void onZygoteInit()
     {
         sp<ProcessState> proc = ProcessState::self();
-        if (proc->supportsProcesses()) {
-            LOGV("App process: starting thread pool.\n");
-            proc->startThreadPool();
-        }
+        LOGV("App process: starting thread pool.\n");
+        proc->startThreadPool();
     }
 
     virtual void onExit(int code)
     {
         if (mClassName == NULL) {
             // if zygote
-            if (ProcessState::self()->supportsProcesses()) {
-                IPCThreadState::self()->stopProcess();
-            }
+            IPCThreadState::self()->stopProcess();
         }
 
         AndroidRuntime::onExit(code);
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 38d0d2a..2666b41 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -23,6 +23,8 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 
+import java.util.HashSet;
+
 public final class Bmgr {
     IBackupManager mBmgr;
     IRestoreSession mRestore;
@@ -45,7 +47,6 @@
     }
 
     public void run(String[] args) {
-        boolean validCommand = false;
         if (args.length < 1) {
             showUsage();
             return;
@@ -329,7 +330,13 @@
         } else {
             try {
                 long token = Long.parseLong(arg, 16);
-                doRestoreAll(token);
+                HashSet<String> filter = null;
+                while ((arg = nextArg()) != null) {
+                    if (filter == null) filter = new HashSet<String>();
+                    filter.add(arg);
+                }
+
+                doRestoreAll(token, filter);
             } catch (NumberFormatException e) {
                 showUsage();
                 return;
@@ -364,7 +371,7 @@
         }
     }
 
-    private void doRestoreAll(long token) {
+    private void doRestoreAll(long token, HashSet<String> filter) {
         RestoreObserver observer = new RestoreObserver();
 
         try {
@@ -383,7 +390,13 @@
                     for (RestoreSet s : sets) {
                         if (s.token == token) {
                             System.out.println("Scheduling restore: " + s.name);
-                            didRestore = (mRestore.restoreAll(token, observer) == 0);
+                            if (filter == null) {
+                                didRestore = (mRestore.restoreAll(token, observer) == 0);
+                            } else {
+                                String[] names = new String[filter.size()];
+                                filter.toArray(names);
+                                didRestore = (mRestore.restoreSome(token, observer, names) == 0);
+                            }
                             break;
                         }
                     }
@@ -430,6 +443,7 @@
         System.err.println("       bmgr list sets");
         System.err.println("       bmgr transport WHICH");
         System.err.println("       bmgr restore TOKEN");
+        System.err.println("       bmgr restore TOKEN PACKAGE...");
         System.err.println("       bmgr restore PACKAGE");
         System.err.println("       bmgr run");
         System.err.println("       bmgr wipe PACKAGE");
@@ -457,12 +471,18 @@
         System.err.println("The 'transport' command designates the named transport as the currently");
         System.err.println("active one.  This setting is persistent across reboots.");
         System.err.println("");
-        System.err.println("The 'restore' command when given a restore token initiates a full-system");
+        System.err.println("The 'restore' command when given just a restore token initiates a full-system");
         System.err.println("restore operation from the currently active transport.  It will deliver");
         System.err.println("the restore set designated by the TOKEN argument to each application");
         System.err.println("that had contributed data to that restore set.");
         System.err.println("");
-        System.err.println("The 'restore' command when given a package name intiates a restore of");
+        System.err.println("The 'restore' command when given a token and one or more package names");
+        System.err.println("initiates a restore operation of just those given packages from the restore");
+        System.err.println("set designated by the TOKEN argument.  It is effectively the same as the");
+        System.err.println("'restore' operation supplying only a token, but applies a filter to the");
+        System.err.println("set of applications to be restored.");
+        System.err.println("");
+        System.err.println("The 'restore' command when given just a package name intiates a restore of");
         System.err.println("just that one package according to the restore set selection algorithm");
         System.err.println("used by the RestoreSession.restorePackage() method.");
         System.err.println("");
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 0acba8b..ccd668d 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -213,9 +213,10 @@
     // create the native surface
     sp<SurfaceControl> control = session()->createSurface(
             0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
-    session()->openTransaction();
+
+    SurfaceComposerClient::openGlobalTransaction();
     control->setLayer(0x40000000);
-    session()->closeTransaction();
+    SurfaceComposerClient::closeGlobalTransaction();
 
     sp<Surface> s = control->getSurface();
 
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 21bb62e..42c35af 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -47,9 +47,11 @@
     char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
     char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
     char network[PROPERTY_VALUE_MAX], date[80];
+    char build_type[PROPERTY_VALUE_MAX];
 
     property_get("ro.build.display.id", build, "(unknown)");
     property_get("ro.build.fingerprint", fingerprint, "(unknown)");
+    property_get("ro.build.type", build_type, "(unknown)");
     property_get("ro.baseband", radio, "(unknown)");
     property_get("ro.bootloader", bootloader, "(unknown)");
     property_get("gsm.operator.alpha", network, "(unknown)");
@@ -136,9 +138,17 @@
 #ifdef BROKEN_VRIL_IS_FIXED_B_4442803
    char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
     property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
-    if (strlen(ril_dumpstate_timeout) > 0) {
-        run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
-                "su", "root", "vril-dump", NULL);
+    if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
+        if (0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1)) {
+            // su does not exist on user builds, so try running without it.
+            // This way any implementations of vril-dump that do not require
+            // root can run on user builds.
+            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
+                    "vril-dump", NULL);
+        } else {
+            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
+                    "su", "root", "vril-dump", NULL);
+        }
     }
 #endif
 
@@ -275,7 +285,7 @@
 
     if (getuid() == 0) {
         /* switch to non-root user and group */
-        gid_t groups[] = { AID_LOG, AID_SDCARD_RW, AID_MOUNT };
+        gid_t groups[] = { AID_LOG, AID_SDCARD_RW, AID_MOUNT, AID_INET };
         if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
             LOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
             return -1;
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index d45ac19..26b9113 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -288,8 +288,9 @@
 }
 
 int get_size(const char *pkgname, const char *apkpath,
-             const char *fwdlock_apkpath,
-             int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize)
+             const char *fwdlock_apkpath, const char *asecpath,
+             int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize,
+             int64_t* _asecsize)
 {
     DIR *d;
     int dfd;
@@ -300,6 +301,7 @@
     int64_t codesize = 0;
     int64_t datasize = 0;
     int64_t cachesize = 0;
+    int64_t asecsize = 0;
 
         /* count the source apk as code -- but only if it's not
          * on the /system partition and its not on the sdcard.
@@ -324,6 +326,14 @@
         }
     }
 
+        /* compute asec size if it is given
+         */
+    if (asecpath != NULL && asecpath[0] != '!') {
+        if (stat(asecpath, &s) == 0) {
+            asecsize += stat_size(&s);
+        }
+    }
+
     if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, 0)) {
         goto done;
     }
@@ -370,6 +380,7 @@
     *_codesize = codesize;
     *_datasize = datasize;
     *_cachesize = cachesize;
+    *_asecsize = asecsize;
     return 0;
 }
 
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index c062d36..feb6b92 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -77,16 +77,18 @@
     int64_t codesize = 0;
     int64_t datasize = 0;
     int64_t cachesize = 0;
+    int64_t asecsize = 0;
     int res = 0;
 
         /* pkgdir, apkpath */
-    res = get_size(arg[0], arg[1], arg[2], &codesize, &datasize, &cachesize);
+    res = get_size(arg[0], arg[1], arg[2], arg[3], &codesize, &datasize, &cachesize, &asecsize);
 
     /*
      * Each int64_t can take up 22 characters printed out. Make sure it
      * doesn't go over REPLY_MAX in the future.
      */
-    snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64, codesize, datasize, cachesize);
+    snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64,
+            codesize, datasize, cachesize, asecsize);
     return res;
 }
 
@@ -137,7 +139,7 @@
     { "freecache",            1, do_free_cache },
     { "rmcache",              1, do_rm_cache },
     { "protect",              2, do_protect },
-    { "getsize",              3, do_get_size },
+    { "getsize",              4, do_get_size },
     { "rmuserdata",           2, do_rm_user_data },
     { "movefiles",            0, do_movefiles },
     { "linklib",              2, do_linklib },
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index e5f6739..c5872b8 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -143,7 +143,8 @@
 int rm_dex(const char *path);
 int protect(char *pkgname, gid_t gid);
 int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath,
-             int64_t *codesize, int64_t *datasize, int64_t *cachesize);
+             const char *asecpath, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
+             int64_t *asecsize);
 int free_cache(int64_t free_size);
 int dexopt(const char *apk_path, uid_t uid, int is_public);
 int movefiles();
diff --git a/cmds/ip-up-vpn/Android.mk b/cmds/ip-up-vpn/Android.mk
new file mode 100644
index 0000000..de81889
--- /dev/null
+++ b/cmds/ip-up-vpn/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2011 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := ip-up-vpn.c
+LOCAL_SHARED_LIBRARIES := libcutils
+LOCAL_MODULE := ip-up-vpn
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/ppp
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/ip-up-vpn/ip-up-vpn.c b/cmds/ip-up-vpn/ip-up-vpn.c
new file mode 100644
index 0000000..bbf6b14
--- /dev/null
+++ b/cmds/ip-up-vpn/ip-up-vpn.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cutils/properties.h>
+
+int main(int argc, char **argv)
+{
+    if (argc > 1 && strlen(argv[1]) > 0) {
+        char dns[PROPERTY_VALUE_MAX];
+        char *dns1 = getenv("DNS1");
+        char *dns2 = getenv("DNS2");
+
+        snprintf(dns, sizeof(dns), "%s %s", dns1 ? dns1 : "", dns2 ? dns2 : "");
+        property_set("vpn.dns", dns);
+        property_set("vpn.via", argv[1]);
+    }
+    return 0;
+}
diff --git a/cmds/keystore/keystore.cpp b/cmds/keystore/keystore.cpp
index bbd1a1b..4b4b9b9 100644
--- a/cmds/keystore/keystore.cpp
+++ b/cmds/keystore/keystore.cpp
@@ -708,11 +708,10 @@
     uid_t euid;
     uint32_t perms;
 } users[] = {
-    {AID_SYSTEM,   ~0,         ~GET},
+    {AID_SYSTEM,   ~0,         ~0},
     {AID_VPN,      AID_SYSTEM, GET},
     {AID_WIFI,     AID_SYSTEM, GET},
     {AID_ROOT,     AID_SYSTEM, GET},
-    {AID_KEYCHAIN, AID_SYSTEM, TEST | GET | SAW},
     {~0,           ~0,         TEST | GET | INSERT | DELETE | EXIST | SAW},
 };
 
diff --git a/cmds/keystore/test-keystore b/cmds/keystore/test-keystore
index 82b276f..3be51b3 100755
--- a/cmds/keystore/test-keystore
+++ b/cmds/keystore/test-keystore
@@ -116,11 +116,12 @@
     expect "1 No error"
     expect "baz"
 
-    log "system does not have access to read any keys"
+    log "get baz"
     keystore system g baz
-    expect "6 Permission denied"
-    
-    log "however, root can read system user keys (as can wifi or vpn users)"
+    expect "1 No error"
+    expect "quux"
+
+    log "root can read system user keys (as can wifi or vpn users)"
     keystore root g baz
     expect "1 No error"
     expect "quux"
diff --git a/cmds/runtime/Android.mk b/cmds/runtime/Android.mk
deleted file mode 100644
index 6a72d10..0000000
--- a/cmds/runtime/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-ifeq ($(TARGET_SIMULATOR),true)
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	ServiceManager.cpp \
-	SignalHandler.cpp \
-	main_runtime.cpp 
-
-LOCAL_SHARED_LIBRARIES := \
-	libutils \
-	libbinder \
-	libandroid_runtime \
-	libcutils \
-	libui \
-	libsystem_server \
-	libhardware_legacy
-
-LOCAL_C_INCLUDES := \
-	$(JNI_H_INCLUDE)
-
-ifeq ($(TARGET_OS),linux)
-	LOCAL_CFLAGS += -DXP_UNIX
-endif
-
-LOCAL_MODULE:= runtime
-
-include $(BUILD_EXECUTABLE)
-endif
diff --git a/cmds/runtime/MODULE_LICENSE_APACHE2 b/cmds/runtime/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/cmds/runtime/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/cmds/runtime/NOTICE b/cmds/runtime/NOTICE
deleted file mode 100644
index c5b1efa..0000000
--- a/cmds/runtime/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
-   Copyright (c) 2005-2008, 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.
-
-   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.
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
diff --git a/cmds/runtime/ServiceManager.cpp b/cmds/runtime/ServiceManager.cpp
deleted file mode 100644
index b2bef07..0000000
--- a/cmds/runtime/ServiceManager.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// Copyright 2005 The Android Open Source Project
-//
-
-#define LOG_TAG "ServiceManager"
-
-#include "ServiceManager.h"
-#include "SignalHandler.h"
-
-#include <utils/Debug.h>
-#include <utils/Log.h>
-#include <binder/Parcel.h>
-#include <utils/String8.h>
-#include <binder/ProcessState.h>
-
-#include <private/utils/Static.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-
-namespace android {
-
-BServiceManager::BServiceManager()
-{
-}
-
-sp<IBinder> BServiceManager::getService(const String16& name) const
-{
-    AutoMutex _l(mLock);
-    ssize_t i = mServices.indexOfKey(name);
-    LOGV("ServiceManager: getService(%s) -> %d\n", String8(name).string(), i);
-    if (i >= 0) return mServices.valueAt(i);
-    return NULL;
-}
-
-sp<IBinder> BServiceManager::checkService(const String16& name) const
-{
-    AutoMutex _l(mLock);
-    ssize_t i = mServices.indexOfKey(name);
-    LOGV("ServiceManager: getService(%s) -> %d\n", String8(name).string(), i);
-    if (i >= 0) return mServices.valueAt(i);
-    return NULL;
-}
-
-status_t BServiceManager::addService(const String16& name, const sp<IBinder>& service)
-{
-    AutoMutex _l(mLock);
-    LOGI("ServiceManager: addService(%s, %p)\n", String8(name).string(), service.get());
-    const ssize_t res = mServices.add(name, service);
-    if (res >= NO_ERROR) {
-        mChanged.broadcast();
-        return NO_ERROR;
-    }
-    return res;
-}
-
-Vector<String16> BServiceManager::listServices()
-{
-    Vector<String16> res;
-
-    AutoMutex _l(mLock);
-    const size_t N = mServices.size();
-    for (size_t i=0; i<N; i++) {
-        res.add(mServices.keyAt(i));
-    }
-
-    return res;
-}
-
-}; // namespace android
diff --git a/cmds/runtime/ServiceManager.h b/cmds/runtime/ServiceManager.h
deleted file mode 100644
index 090ca6d..0000000
--- a/cmds/runtime/ServiceManager.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Copyright 2005 The Android Open Source Project
-//
-#ifndef ANDROID_SERVICE_MANAGER_H
-#define ANDROID_SERVICE_MANAGER_H
-
-#include <binder/IServiceManager.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------
-
-class BServiceManager : public BnServiceManager
-{
-public:
-                                BServiceManager();
-    
-    virtual sp<IBinder>         getService( const String16& name) const;
-    virtual sp<IBinder>         checkService( const String16& name) const;
-    virtual status_t            addService( const String16& name,
-                                            const sp<IBinder>& service);
-    virtual Vector<String16>    listServices();
-
-    
-private:
-    mutable Mutex               mLock;
-    mutable Condition           mChanged;
-    sp<IPermissionController>   mPermissionController;
-    KeyedVector<String16, sp<IBinder> > mServices;
-};
-
-// ----------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_SERVICE_MANAGER_H
diff --git a/cmds/runtime/SignalHandler.cpp b/cmds/runtime/SignalHandler.cpp
deleted file mode 100644
index cccaabf..0000000
--- a/cmds/runtime/SignalHandler.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-//
-// Copyright 2005 The Android Open Source Project
-//
-
-#define LOG_TAG "SignalHandler"
-
-#include "SignalHandler.h"
-
-#include <utils/Atomic.h>
-#include <utils/Debug.h>
-#include <utils/Log.h>
-
-#include <errno.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-namespace android {
-
-class SignalHandler::ProcessThread : public Thread
-{
-public:
-    ProcessThread(SignalHandler& sh)
-        : Thread(false)
-        , mOwner(sh)
-    {
-    }
-
-    virtual bool threadLoop()
-    {
-        char buffer[32];
-        read(mOwner.mAvailMsg[0], buffer, sizeof(buffer));
-
-        LOGV("Signal command processing thread woke up!");
-
-        if (mOwner.mLostCommands) {
-            LOGE("Lost %d signals!", mOwner.mLostCommands);
-            mOwner.mLostCommands = 0;
-        }
-
-        int cur;
-        while ((cur=mOwner.mCommandBottom) != mOwner.mCommandTop) {
-            if (mOwner.mCommands[cur].filled == 0) {
-                LOGV("Command at %d is not yet filled", cur);
-                break;
-            }
-
-            LOGV("Processing command at %d, top is %d",
-                 cur, mOwner.mCommandTop);
-            processCommand(mOwner.mCommands[cur]);
-            mOwner.mCommands[cur].filled = 0;
-
-            int next = mOwner.mCommandBottom+1;
-            if (next >= COMMAND_QUEUE_SIZE) {
-                next = 0;
-            }
-
-            mOwner.mCommandBottom = next;
-        }
-
-        return true;
-    }
-
-    void processCommand(const CommandEntry& entry)
-    {
-        switch (entry.signum) {
-        case SIGCHLD: {
-            mOwner.mLock.lock();
-            ssize_t i = mOwner.mChildHandlers.indexOfKey(entry.info.si_pid);
-            ChildHandler ch;
-            if (i >= 0) {
-                ch = mOwner.mChildHandlers.valueAt(i);
-                mOwner.mChildHandlers.removeItemsAt(i);
-            }
-            mOwner.mLock.unlock();
-
-            LOGD("SIGCHLD: pid=%d, handle index=%d", entry.info.si_pid, i);
-
-            if (i >= 0) {
-                int res = waitpid(entry.info.si_pid, NULL, WNOHANG);
-                LOGW_IF(res == 0,
-                        "Received SIGCHLD, but pid %d is not yet stopped",
-                        entry.info.si_pid);
-                if (ch.handler) {
-                    ch.handler(entry.info.si_pid, ch.userData);
-                }
-            } else {
-                LOGW("Unhandled SIGCHLD for pid %d", entry.info.si_pid);
-            }
-        } break;
-        }
-    }
-
-    SignalHandler& mOwner;
-};
-
-
-Mutex SignalHandler::mInstanceLock;
-SignalHandler* SignalHandler::mInstance = NULL;
-
-status_t SignalHandler::setChildHandler(pid_t childPid,
-                                        int tag,
-                                        child_callback_t handler,
-                                        void* userData)
-{
-    SignalHandler* const self = getInstance();
-
-    self->mLock.lock();
-
-    // First make sure this child hasn't already exited.
-    pid_t res = waitpid(childPid, NULL, WNOHANG);
-    if (res != 0) {
-        if (res < 0) {
-            LOGW("setChildHandler waitpid of %d failed: %d (%s)",
-                 childPid, res, strerror(errno));
-        } else {
-            LOGW("setChildHandler waitpid of %d said %d already dead",
-                 childPid, res);
-        }
-
-        // Some kind of error...  just handle the exit now.
-        self->mLock.unlock();
-
-        if (handler) {
-            handler(childPid, userData);
-        }
-
-        // Return an error code -- 0 means it already exited.
-        return (status_t)res;
-    }
-
-    ChildHandler entry;
-    entry.childPid = childPid;
-    entry.tag = tag;
-    entry.handler = handler;
-    entry.userData = userData;
-
-    // Note: this replaces an existing entry for this pid, if there already
-    // is one.  This is the required behavior.
-    LOGD("setChildHandler adding pid %d, tag %d, handler %p, data %p",
-         childPid, tag, handler, userData);
-    self->mChildHandlers.add(childPid, entry);
-
-    self->mLock.unlock();
-
-    return NO_ERROR;
-}
-
-void SignalHandler::killAllChildren(int tag)
-{
-    SignalHandler* const self = getInstance();
-
-    AutoMutex _l (self->mLock);
-    const size_t N = self->mChildHandlers.size();
-    for (size_t i=0; i<N; i++) {
-        const ChildHandler& ch(self->mChildHandlers.valueAt(i));
-        if (tag == 0 || ch.tag == tag) {
-            const pid_t pid = ch.childPid;
-            LOGI("Killing child %d (tag %d)\n", pid, ch.tag);
-            kill(pid, SIGKILL);
-        }
-    }
-}
-
-SignalHandler::SignalHandler()
-    : mCommandTop(0)
-    , mCommandBottom(0)
-    , mLostCommands(0)
-{
-    memset(mCommands, 0, sizeof(mCommands));
-
-    int res = pipe(mAvailMsg);
-    LOGE_IF(res != 0, "Unable to create signal handler pipe: %s", strerror(errno));
-
-    mProcessThread = new ProcessThread(*this);
-    mProcessThread->run("SignalHandler", PRIORITY_HIGHEST);
-
-    struct sigaction sa;
-    memset(&sa, 0, sizeof(sa));
-    sa.sa_sigaction = sigAction;
-    sa.sa_flags = SA_NOCLDSTOP|SA_SIGINFO;
-    sigaction(SIGCHLD, &sa, NULL);
-}
-
-SignalHandler::~SignalHandler()
-{
-}
-
-SignalHandler* SignalHandler::getInstance()
-{
-    AutoMutex _l(mInstanceLock);
-    if (mInstance == NULL) {
-        mInstance = new SignalHandler();
-    }
-    return mInstance;
-}
-
-void SignalHandler::sigAction(int signum, siginfo_t* info, void*)
-{
-    static const char wakeupMsg[1] = { 0xff };
-
-    // If our signal handler is being called, then we know we have
-    // already initialized the SignalHandler class and thus mInstance
-    // is valid.
-    SignalHandler* const self = mInstance;
-
-    // XXX This is not safe!
-    #if 0
-    LOGV("Signal %d: signo=%d, errno=%d, code=%d, pid=%d\n",
-           signum,
-           info->si_signo, info->si_errno, info->si_code,
-           info->si_pid);
-    #endif
-
-    int32_t oldTop, newTop;
-
-    // Find the next command slot...
-    do {
-        oldTop = self->mCommandTop;
-
-        newTop = oldTop + 1;
-        if (newTop >= COMMAND_QUEUE_SIZE) {
-            newTop = 0;
-        }
-
-        if (newTop == self->mCommandBottom) {
-            // The buffer is filled up!  Ouch!
-            // XXX This is not safe!
-            #if 0
-            LOGE("Command buffer overflow!  newTop=%d\n", newTop);
-            #endif
-            android_atomic_add(1, &self->mLostCommands);
-            write(self->mAvailMsg[1], wakeupMsg, sizeof(wakeupMsg));
-            return;
-        }
-    } while(android_atomic_cmpxchg(oldTop, newTop, &(self->mCommandTop)));
-
-    // Fill in the command data...
-    self->mCommands[oldTop].signum = signum;
-    self->mCommands[oldTop].info = *info;
-
-    // And now make this command available.
-    self->mCommands[oldTop].filled = 1;
-
-    // Wake up the processing thread.
-    write(self->mAvailMsg[1], wakeupMsg, sizeof(wakeupMsg));
-}
-
-}; // namespace android
-
diff --git a/cmds/runtime/SignalHandler.h b/cmds/runtime/SignalHandler.h
deleted file mode 100644
index 7f4ef8e..0000000
--- a/cmds/runtime/SignalHandler.h
+++ /dev/null
@@ -1,137 +0,0 @@
-//
-// Copyright 2005 The Android Open Source Project
-//
-#ifndef ANDROID_SIGNAL_HANDLER_H
-#define ANDROID_SIGNAL_HANDLER_H
-
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-
-#include <signal.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------
-
-enum {
-    DEFAULT_PROCESS_TAG = 1
-};
-
-class SignalHandler
-{
-public:
-    typedef void (*child_callback_t)(pid_t child, void* userData);
-
-    /**
-     * Set a handler for when a child process exits.  By calling
-     * this, a waitpid() will be done when the child exits to remove
-     * it from the zombie state.  You can also optionally specify a
-     * handler to be called when the child exits.
-     * 
-     * If there is already a handler for this child process, it is
-     * replaced by this new handler.  In this case the old handler's
-     * function is not called.
-     * 
-     * @param childPid Process ID of child to watch.
-     * @param childTag User-defined tag for this child.  Must be
-     *                 greater than zero.
-     * @param handler If non-NULL, this will be called when the
-     *                child exits.  It may be called in either a
-     *                separate signal handling thread, or
-     *                immediately if the child has already exited.
-     * @param userData Propageted as-is to handler.
-     * 
-     * @return status_t NO_ERROR if all is well.
-     */
-    static status_t             setChildHandler(pid_t childPid,
-                                                int childTag = DEFAULT_PROCESS_TAG,
-                                                child_callback_t handler = NULL,
-                                                void* userData = NULL);
-
-    /**
-     * Kill all of the child processes for which we have a waiting
-     * handler, whose tag is the given value.  If tag is 0, all
-     * children are killed.
-     * 
-     * @param tag
-     */
-    static void                 killAllChildren(int tag = 0);
-
-private:
-                                SignalHandler();
-                                ~SignalHandler();
-
-    static SignalHandler*       getInstance();
-
-    static void                 sigAction(int, siginfo_t*, void*);
-
-    // --------------------------------------------------
-    // Shared state...  all of this is protected by mLock.
-    // --------------------------------------------------
-
-    mutable Mutex                       mLock;
-
-    struct ChildHandler
-    {
-        pid_t childPid;
-        int tag;
-        child_callback_t handler;
-        void* userData;
-    };
-    KeyedVector<pid_t, ChildHandler>    mChildHandlers;
-
-    // --------------------------------------------------
-    // Commmand queue...  data is inserted by the signal
-    // handler using atomic ops, and retrieved by the
-    // signal processing thread.  Because these are touched
-    // by the signal handler, no lock is used.
-    // --------------------------------------------------
-
-    enum {
-        COMMAND_QUEUE_SIZE = 64
-    };
-    struct CommandEntry
-    {
-        int filled;
-        int signum;
-        siginfo_t info;
-    };
-
-    // The top of the queue.  This is incremented atomically by the
-    // signal handler before placing a command in the queue.
-    volatile int32_t                    mCommandTop;
-
-    // The bottom of the queue.  Only modified by the processing
-    // thread; the signal handler reads it only to determine if the
-    // queue is full.
-    int32_t                             mCommandBottom;
-
-    // Incremented each time we receive a signal and don't have room
-    // for it on the command queue.
-    volatile int32_t                    mLostCommands;
-
-    // The command processing thread.
-    class ProcessThread;
-    sp<Thread>                          mProcessThread;
-
-    // Pipe used to tell command processing thread when new commands.
-    // are available.  The thread blocks on the read end, the signal
-    // handler writes when it enqueues new commands.
-    int                                 mAvailMsg[2];
-
-    // The commands.
-    CommandEntry                        mCommands[COMMAND_QUEUE_SIZE];
-
-    // --------------------------------------------------
-    // Singleton.
-    // --------------------------------------------------
-
-    static Mutex                        mInstanceLock;
-    static SignalHandler*               mInstance;
-};
-
-// ----------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_SIGNAL_HANDLER_H
diff --git a/cmds/runtime/main_runtime.cpp b/cmds/runtime/main_runtime.cpp
deleted file mode 100644
index dbff095..0000000
--- a/cmds/runtime/main_runtime.cpp
+++ /dev/null
@@ -1,515 +0,0 @@
-//
-// Copyright 2005 The Android Open Source Project
-//
-// Main entry point for runtime.
-//
-
-#include "ServiceManager.h"
-#include "SignalHandler.h"
-
-#include <utils/threads.h>
-#include <utils/Errors.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <utils/Log.h>
-#include <cutils/zygote.h>
-
-#include <cutils/properties.h>
-
-#include <private/utils/Static.h>
-
-#include <surfaceflinger/ISurfaceComposer.h>
-
-#include <android_runtime/AndroidRuntime.h>
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <getopt.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <linux/capability.h>
-#include <linux/ioctl.h>
-#ifdef HAVE_ANDROID_OS
-# include <linux/android_alarm.h>
-#endif
-
-#undef LOG_TAG
-#define LOG_TAG "runtime"
-
-static const char* ZYGOTE_ARGV[] = {
-    "--setuid=1000",
-    "--setgid=1000",
-    "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",
-    /* CAP_SYS_TTY_CONFIG & CAP_SYS_RESOURCE & CAP_NET_BROADCAST &
-     * CAP_NET_ADMIN & CAP_NET_RAW & CAP_NET_BIND_SERVICE  & CAP_KILL &
-     * CAP_SYS_BOOT CAP_SYS_NICE
-     */
-    "--capabilities=96549920,96549920",
-    "--runtime-init",
-    "--nice-name=system_server",
-    "com.android.server.SystemServer"
-};
-
-using namespace android;
-
-extern "C" status_t system_init();
-
-enum {
-    SYSTEM_PROCESS_TAG = DEFAULT_PROCESS_TAG+1
-};
-
-extern Mutex gEventQMutex;
-extern Condition gEventQCondition;
-
-namespace android {
-
-extern void set_finish_init_func(void (*func)());
-
-
-/**
- * This class is used to kill this process (runtime) when the system_server dies.
- */
-class GrimReaper : public IBinder::DeathRecipient {
-public:
-    GrimReaper() { }
-
-    virtual void binderDied(const wp<IBinder>& who)
-    {
-        LOGI("Grim Reaper killing runtime...");
-        kill(getpid(), SIGKILL);
-    }
-};
-
-extern void QuickTests();
-
-/*
- * Print usage info.
- */
-static void usage(const char* argv0)
-{
-    fprintf(stderr,
-        "Usage: runtime [-g gamma] [-l logfile] [-n] [-s]\n"
-        "               [-j app-component] [-v app-verb] [-d app-data]\n"
-        "\n"
-        "-l: File to send log messages to\n"
-        "-n: Don't print to stdout/stderr\n"
-        "-s: Force single-process mode\n"
-        "-j: Custom home app component name\n"
-        "-v: Custom home app intent verb\n"
-        "-d: Custom home app intent data\n"
-    );
-    exit(1);
-}
-
-// Selected application to run.
-static const char* gInitialApplication = NULL;
-static const char* gInitialVerb = NULL;
-static const char* gInitialData = NULL;
-
-static void writeStringToParcel(Parcel& parcel, const char* str)
-{
-    if (str) {
-        parcel.writeString16(String16(str));
-    } else {
-        parcel.writeString16(NULL, 0);
-    }
-}
-
-/*
- * Starting point for program logic.
- *
- * Returns with an exit status code (0 on success, nonzero on error).
- */
-static int run(sp<ProcessState>& proc)
-{
-    // Temporary hack to call startRunning() on the activity manager.
-    sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> am;
-    while ((am = sm->getService(String16("activity"))) == NULL) {
-        LOGI("Waiting for activity manager...");
-    }
-    Parcel data, reply;
-    // XXX Need to also supply a package name for this to work again.
-    // IActivityManager::getInterfaceDescriptor() is the token for invoking on this interface;
-    // hardcoding it here avoids having to link with the full Activity Manager library
-    data.writeInterfaceToken(String16("android.app.IActivityManager"));
-    writeStringToParcel(data, NULL);
-    writeStringToParcel(data, gInitialApplication);
-    writeStringToParcel(data, gInitialVerb);
-    writeStringToParcel(data, gInitialData);
-LOGI("run() sending FIRST_CALL_TRANSACTION to activity manager");
-    am->transact(IBinder::FIRST_CALL_TRANSACTION, data, &reply);
-
-    if (proc->supportsProcesses()) {
-        // Now we link to the Activity Manager waiting for it to die. If it does kill ourself.
-        // initd will restart this process and bring the system back up.
-        sp<GrimReaper> grim = new GrimReaper();
-        am->linkToDeath(grim, grim.get(), 0);
-
-        // Now join the thread pool. Note this is needed so that the message enqueued in the driver
-        // for the linkToDeath gets processed.
-        IPCThreadState::self()->joinThreadPool();
-    } else {
-        // Keep this thread running forever...
-        while (1) {
-            usleep(100000);
-        }
-    }
-    return 1;
-}
-
-
-};  // namespace android
-
-
-/*
- * Post-system-process initialization.
- *
- * This function continues initialization after the system process
- * has been initialized.  It needs to be separate because the system
- * initialization needs to care of starting the Android runtime if it is not
- * running in its own process, which doesn't return until the runtime is
- * being shut down.  So it will call back to here from inside of Dalvik,
- * to allow us to continue booting up.
- */
-static void finish_system_init(sp<ProcessState>& proc)
-{
-    // If we are running multiprocess, we now need to have the
-    // thread pool started here.  We don't do this in boot_init()
-    // because when running single process we need to start the
-    // thread pool after the Android runtime has been started (so
-    // the pool uses Dalvik threads).
-    if (proc->supportsProcesses()) {
-        proc->startThreadPool();
-    }
-}
-
-
-// This function can be used to enforce security to different
-// root contexts.  For now, we just give every access.
-static bool contextChecker(
-    const String16& name, const sp<IBinder>& caller, void* userData)
-{
-    return true;
-}
-
-/*
- * Initialization of boot services.
- *
- * This is where we perform initialization of all of our low-level
- * boot services.  Most importantly, here we become the context
- * manager and use that to publish the service manager that will provide
- * access to all other services.
- */
-static void boot_init()
-{
-    LOGI("Entered boot_init()!\n");
-
-    sp<ProcessState> proc(ProcessState::self());
-    LOGD("ProcessState: %p\n", proc.get());
-    proc->becomeContextManager(contextChecker, NULL);
-
-    if (proc->supportsProcesses()) {
-        LOGI("Binder driver opened.  Multiprocess enabled.\n");
-    } else {
-        LOGI("Binder driver not found.  Processes not supported.\n");
-    }
-
-    sp<BServiceManager> sm = new BServiceManager;
-    proc->setContextObject(sm);
-}
-
-/*
- * Redirect stdin/stdout/stderr to /dev/null.
- */
-static void redirectStdFds(void)
-{
-    int fd = open("/dev/null", O_RDWR, 0);
-    if (fd < 0) {
-        LOGW("Unable to open /dev/null: %s\n", strerror(errno));
-    } else {
-        dup2(fd, 0);
-        dup2(fd, 1);
-        dup2(fd, 2);
-        close(fd);
-    }
-}
-
-static int hasDir(const char* dir)
-{
-    struct stat s;
-    int res = stat(dir, &s);
-    if (res == 0) {
-        return S_ISDIR(s.st_mode);
-    }
-    return 0;
-}
-
-static void validateTime()
-{
-#if HAVE_ANDROID_OS
-    int fd;
-    int res;
-    time_t min_time = 1167652800; // jan 1 2007, type 'date -ud "1/1 12:00" +%s' to get value for current year
-    struct timespec ts;
-
-    fd = open("/dev/alarm", O_RDWR);
-    if(fd < 0) {
-        LOGW("Unable to open alarm driver: %s\n", strerror(errno));
-        return;
-    }
-    res = ioctl(fd, ANDROID_ALARM_GET_TIME(ANDROID_ALARM_RTC_WAKEUP), &ts);
-    if(res < 0) {
-        LOGW("Unable to read rtc, %s\n", strerror(errno));
-    }
-    else if(ts.tv_sec >= min_time) {
-        goto done;
-    }
-    LOGW("Invalid time detected, %ld set to %ld\n", ts.tv_sec, min_time);
-    ts.tv_sec = min_time;
-    ts.tv_nsec = 0;
-    res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts);
-    if(res < 0) {
-        LOGW("Unable to set rtc to %ld: %s\n", ts.tv_sec, strerror(errno));
-    }
-done:
-    close(fd);
-#endif
-}
-
-#ifndef HAVE_ANDROID_OS
-class QuickRuntime : public AndroidRuntime
-{
-public:
-    QuickRuntime() {}
-
-    virtual void onStarted()
-    {
-        printf("QuickRuntime: onStarted\n");
-    }
-};
-#endif
-
-static status_t start_process(const char* name);
-
-static void restart_me(pid_t child, void* userData)
-{
-    start_process((const char*)userData);
-}
-
-static status_t start_process(const char* name)
-{
-    String8 path(name);
-    Vector<const char*> args;
-    String8 leaf(path.getPathLeaf());
-    String8 parentDir(path.getPathDir());
-    args.insertAt(leaf.string(), 0);
-    args.add(parentDir.string());
-    args.add(NULL);
-    pid_t child = fork();
-    if (child < 0) {
-        status_t err = errno;
-        LOGE("*** fork of child %s failed: %s", leaf.string(), strerror(err));
-        return -errno;
-    } else if (child == 0) {
-        LOGI("Executing: %s", path.string());
-        execv(path.string(), const_cast<char**>(args.array()));
-        int err = errno;
-        LOGE("Exec failed: %s\n", strerror(err));
-        _exit(err);
-    } else {
-        SignalHandler::setChildHandler(child, DEFAULT_PROCESS_TAG,
-                restart_me, (void*)name);
-    }
-    return -errno;
-}
-
-/*
- * Application entry point.
- *
- * Parse arguments, set some values, and pass control off to Run().
- *
- * This is redefined to "SDL_main" on SDL simulator builds, and
- * "runtime_main" on wxWidgets builds.
- */
-extern "C"
-int main(int argc, char* const argv[])
-{
-    bool singleProcess = false;
-    const char* logFile = NULL;
-    int ic;
-    int result = 1;
-    pid_t systemPid;
-
-    sp<ProcessState> proc;
-
-#ifndef HAVE_ANDROID_OS
-    /* Set stdout/stderr to unbuffered for MinGW/MSYS. */
-    //setvbuf(stdout, NULL, _IONBF, 0);
-    //setvbuf(stderr, NULL, _IONBF, 0);
-
-    LOGI("commandline args:\n");
-    for (int i = 0; i < argc; i++)
-        LOGI("  %2d: '%s'\n", i, argv[i]);
-#endif
-
-    while (1) {
-        ic = getopt(argc, argv, "g:j:v:d:l:ns");
-        if (ic < 0)
-            break;
-
-        switch (ic) {
-        case 'g':
-            break;
-        case 'j':
-            gInitialApplication = optarg;
-            break;
-        case 'v':
-            gInitialVerb = optarg;
-            break;
-        case 'd':
-            gInitialData = optarg;
-            break;
-        case 'l':
-            logFile = optarg;
-            break;
-        case 'n':
-            redirectStdFds();
-            break;
-        case 's':
-            singleProcess = true;
-            break;
-        case '?':
-        default:
-            LOGE("runtime: unrecognized flag -%c\n", ic);
-            usage(argv[0]);
-            break;
-        }
-    }
-    if (optind < argc) {
-        LOGE("runtime: extra stuff: %s\n", argv[optind]);
-        usage(argv[0]);
-    }
-
-    if (singleProcess) {
-        ProcessState::setSingleProcess(true);
-    }
-
-    if (logFile != NULL) {
-        android_logToFile(NULL, logFile);
-    }
-
-    /*
-     * Set up ANDROID_* environment variables.
-     *
-     * TODO: the use of $ANDROID_PRODUCT_OUT will go away soon.
-     */
-    static const char* kSystemDir = "/system";
-    static const char* kDataDir = "/data";
-    static const char* kAppSubdir = "/app";
-    const char* out = NULL;
-#ifndef HAVE_ANDROID_OS
-    //out = getenv("ANDROID_PRODUCT_OUT");
-#endif
-    if (out == NULL)
-        out = "";
-
-    char* systemDir = (char*) malloc(strlen(out) + strlen(kSystemDir) +1);
-    char* dataDir = (char*) malloc(strlen(out) + strlen(kDataDir) +1);
-
-    sprintf(systemDir, "%s%s", out, kSystemDir);
-    sprintf(dataDir, "%s%s", out, kDataDir);
-    setenv("ANDROID_ROOT", systemDir, 1);
-    setenv("ANDROID_DATA", dataDir, 1);
-
-    char* assetDir = (char*) malloc(strlen(systemDir) + strlen(kAppSubdir) +1);
-    sprintf(assetDir, "%s%s", systemDir, kAppSubdir);
-
-    LOGI("Startup: sys='%s' asset='%s' data='%s'\n",
-        systemDir, assetDir, dataDir);
-    free(systemDir);
-    free(dataDir);
-
-#ifdef HAVE_ANDROID_OS
-    /* set up a process group for easier killing on the device */
-    setpgid(0, getpid());
-#endif
-
-    // Change to asset dir.  This is only necessary if we've changed to
-    // a different directory, but there's little harm in doing it regardless.
-    //
-    // Expecting assets to live in the current dir is not a great idea,
-    // because some of our code or one of our libraries could change the
-    // directory out from under us.  Preserve the behavior for now.
-    if (chdir(assetDir) != 0) {
-        LOGW("WARNING: could not change dir to '%s': %s\n",
-             assetDir, strerror(errno));
-    }
-    free(assetDir);
-
-#if 0
-    // Hack to keep libc from beating the filesystem to death.  It's
-    // hitting /etc/localtime frequently,
-    //
-    // This statement locks us into Pacific time.  We could do better,
-    // but there's not much point until we're sure that the library
-    // can't be changed to do more along the lines of what we want.
-#ifndef XP_WIN
-    setenv("TZ", "PST+8PDT,M4.1.0/2,M10.5.0/2", true);
-#endif
-#endif
-
-    /* track our progress through the boot sequence */
-    const int LOG_BOOT_PROGRESS_START = 3000;
-    LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
-        ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
-
-    validateTime();
-
-    proc = ProcessState::self();
-
-    boot_init();
-
-    /* If we are in multiprocess mode, have zygote spawn the system
-     * server process and call system_init(). If we are running in
-     * single process mode just call system_init() directly.
-     */
-    if (proc->supportsProcesses()) {
-        // If stdio logging is on, system_server should not inherit our stdio
-        // The dalvikvm instance will copy stdio to the log on its own
-        char propBuf[PROPERTY_VALUE_MAX];
-        bool logStdio = false;
-        property_get("log.redirect-stdio", propBuf, "");
-        logStdio = (strcmp(propBuf, "true") == 0);
-
-        zygote_run_oneshot((int)(!logStdio),
-                sizeof(ZYGOTE_ARGV) / sizeof(ZYGOTE_ARGV[0]),
-                ZYGOTE_ARGV);
-
-        //start_process("/system/bin/mediaserver");
-
-    } else {
-#ifndef HAVE_ANDROID_OS
-        QuickRuntime* runt = new QuickRuntime();
-        runt->start("com/android/server/SystemServer",
-                    "" /* spontaneously fork system server from zygote */);
-#endif
-    }
-
-    //printf("+++ post-zygote\n");
-
-    finish_system_init(proc);
-    run(proc);
-
-bail:
-    if (proc != NULL) {
-        proc->setContextObject(NULL);
-    }
-
-    return 0;
-}
diff --git a/cmds/stagefright/recordvideo.cpp b/cmds/stagefright/recordvideo.cpp
index 1264215..c402286 100644
--- a/cmds/stagefright/recordvideo.cpp
+++ b/cmds/stagefright/recordvideo.cpp
@@ -34,7 +34,7 @@
     fprintf(stderr, "usage: %s\n", me);
     fprintf(stderr, "       -h(elp)\n");
     fprintf(stderr, "       -b bit rate in bits per second (default: 300000)\n");
-    fprintf(stderr, "       -c YUV420 color format: [0] semi planar or [1] planar (default: 1)\n");
+    fprintf(stderr, "       -c YUV420 color format: [0] semi planar or [1] planar or other omx YUV420 color format (default: 1)\n");
     fprintf(stderr, "       -f frame rate in frames per second (default: 30)\n");
     fprintf(stderr, "       -i I frame interval in seconds (default: 1)\n");
     fprintf(stderr, "       -n number of frames to be recorded (default: 300)\n");
@@ -59,11 +59,6 @@
           mSize((width * height * 3) / 2) {
 
         mGroup.add_buffer(new MediaBuffer(mSize));
-
-        // Check the color format to make sure
-        // that the buffer size mSize it set correctly above.
-        CHECK(colorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
-              colorFormat == OMX_COLOR_FormatYUV420Planar);
     }
 
     virtual sp<MetaData> getFormat() {
@@ -144,9 +139,13 @@
         case kYUV420P:
             return OMX_COLOR_FormatYUV420Planar;
         default:
-            fprintf(stderr, "Unsupported color: %d\n", color);
-            return -1;
+            fprintf(stderr, "Custom OMX color format: %d\n", color);
+            if (color == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar ||
+                color == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
+                return color;
+            }
     }
+    return -1;
 }
 
 int main(int argc, char **argv) {
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
index 289665f..6fa66cf 100644
--- a/cmds/stagefright/sf2.cpp
+++ b/cmds/stagefright/sf2.cpp
@@ -29,6 +29,7 @@
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
+#include <media/stagefright/NativeWindowWrapper.h>
 #include <media/stagefright/Utils.h>
 
 #include <surfaceflinger/ISurfaceComposer.h>
@@ -39,10 +40,12 @@
 using namespace android;
 
 struct Controller : public AHandler {
-    Controller(const char *uri, bool decodeAudio, const sp<Surface> &surface)
+    Controller(const char *uri, bool decodeAudio,
+               const sp<Surface> &surface, bool renderToSurface)
         : mURI(uri),
           mDecodeAudio(decodeAudio),
           mSurface(surface),
+          mRenderToSurface(renderToSurface),
           mCodec(new ACodec) {
         CHECK(!mDecodeAudio || mSurface == NULL);
     }
@@ -97,7 +100,8 @@
                 sp<AMessage> format = makeFormat(mSource->getFormat());
 
                 if (mSurface != NULL) {
-                    format->setObject("surface", mSurface);
+                    format->setObject(
+                            "native-window", new NativeWindowWrapper(mSurface));
                 }
 
                 mCodec->initiateSetup(format);
@@ -220,6 +224,7 @@
     AString mURI;
     bool mDecodeAudio;
     sp<Surface> mSurface;
+    bool mRenderToSurface;
     sp<ACodec> mCodec;
     sp<MediaSource> mSource;
 
@@ -451,7 +456,7 @@
                 inBuffer->release();
                 inBuffer = NULL;
 
-                // break;  // Don't coalesce
+                break;  // Don't coalesce
             }
 
             LOGV("coalesced %d input buffers", n);
@@ -479,6 +484,10 @@
         sp<AMessage> reply;
         CHECK(msg->findMessage("reply", &reply));
 
+        if (mRenderToSurface) {
+            reply->setInt32("render", 1);
+        }
+
         reply->post();
     }
 
@@ -491,7 +500,8 @@
     fprintf(stderr, "       -a(udio)\n");
 
     fprintf(stderr,
-            "       -s(surface) Allocate output buffers on a surface.\n");
+            "       -S(urface) Allocate output buffers on a surface.\n"
+            "       -R(ender)  Render surface-allocated buffers.\n");
 }
 
 int main(int argc, char **argv) {
@@ -499,18 +509,23 @@
 
     bool decodeAudio = false;
     bool useSurface = false;
+    bool renderToSurface = false;
 
     int res;
-    while ((res = getopt(argc, argv, "has")) >= 0) {
+    while ((res = getopt(argc, argv, "haSR")) >= 0) {
         switch (res) {
             case 'a':
                 decodeAudio = true;
                 break;
 
-            case 's':
+            case 'S':
                 useSurface = true;
                 break;
 
+            case 'R':
+                renderToSurface = true;
+                break;
+
             case '?':
             case 'h':
             default:
@@ -553,16 +568,18 @@
         CHECK(control != NULL);
         CHECK(control->isValid());
 
-        CHECK_EQ(composerClient->openTransaction(), (status_t)OK);
+        SurfaceComposerClient::openGlobalTransaction();
         CHECK_EQ(control->setLayer(30000), (status_t)OK);
         CHECK_EQ(control->show(), (status_t)OK);
-        CHECK_EQ(composerClient->closeTransaction(), (status_t)OK);
+        SurfaceComposerClient::closeGlobalTransaction();
 
         surface = control->getSurface();
         CHECK(surface != NULL);
     }
 
-    sp<Controller> controller = new Controller(argv[0], decodeAudio, surface);
+    sp<Controller> controller =
+        new Controller(argv[0], decodeAudio, surface, renderToSurface);
+
     looper->registerHandler(controller);
 
     controller->startAsync();
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index d7b1e71..1a5b7f3 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -74,8 +74,6 @@
 
 static sp<ANativeWindow> gSurface;
 
-#define USE_SURFACE_COMPOSER 0
-
 static int64_t getNowUs() {
     struct timeval tv;
     gettimeofday(&tv, NULL);
@@ -579,6 +577,7 @@
     fprintf(stderr, "       -x display a histogram of decoding times/fps "
                     "(video only)\n");
     fprintf(stderr, "       -S allocate buffers from a surface\n");
+    fprintf(stderr, "       -T allocate buffers from a surface texture\n");
 }
 
 int main(int argc, char **argv) {
@@ -590,6 +589,7 @@
     bool extractThumbnail = false;
     bool seekTest = false;
     bool useSurfaceAlloc = false;
+    bool useSurfaceTexAlloc = false;
     gNumRepetitions = 1;
     gMaxNumFrames = 0;
     gReproduceBug = -1;
@@ -604,7 +604,7 @@
     sp<LiveSession> liveSession;
 
     int res;
-    while ((res = getopt(argc, argv, "han:lm:b:ptsrow:kxS")) >= 0) {
+    while ((res = getopt(argc, argv, "han:lm:b:ptsrow:kxST")) >= 0) {
         switch (res) {
             case 'a':
             {
@@ -695,6 +695,12 @@
                 break;
             }
 
+            case 'T':
+            {
+                useSurfaceTexAlloc = true;
+                break;
+            }
+
             case '?':
             case 'h':
             default:
@@ -843,34 +849,35 @@
     sp<SurfaceComposerClient> composerClient;
     sp<SurfaceControl> control;
 
-    if (useSurfaceAlloc && !audioOnly) {
-#if USE_SURFACE_COMPOSER
-        composerClient = new SurfaceComposerClient;
-        CHECK_EQ(composerClient->initCheck(), (status_t)OK);
+    if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) {
+        if (useSurfaceAlloc) {
+            composerClient = new SurfaceComposerClient;
+            CHECK_EQ(composerClient->initCheck(), (status_t)OK);
 
-        control = composerClient->createSurface(
-                getpid(),
-                String8("A Surface"),
-                0,
-                1280,
-                800,
-                PIXEL_FORMAT_RGB_565,
-                0);
+            control = composerClient->createSurface(
+                    String8("A Surface"),
+                    0,
+                    1280,
+                    800,
+                    PIXEL_FORMAT_RGB_565,
+                    0);
 
-        CHECK(control != NULL);
-        CHECK(control->isValid());
+            CHECK(control != NULL);
+            CHECK(control->isValid());
 
-        CHECK_EQ(composerClient->openTransaction(), (status_t)OK);
-        CHECK_EQ(control->setLayer(30000), (status_t)OK);
-        CHECK_EQ(control->show(), (status_t)OK);
-        CHECK_EQ(composerClient->closeTransaction(), (status_t)OK);
+            SurfaceComposerClient::openGlobalTransaction();
+            CHECK_EQ(control->setLayer(30000), (status_t)OK);
+            CHECK_EQ(control->show(), (status_t)OK);
+            SurfaceComposerClient::closeGlobalTransaction();
 
-        gSurface = control->getSurface();
-        CHECK(gSurface != NULL);
-#else
-        sp<SurfaceTexture> texture = new SurfaceTexture(0 /* tex */);
-        gSurface = new SurfaceTextureClient(texture);
-#endif
+            gSurface = control->getSurface();
+            CHECK(gSurface != NULL);
+        } else {
+            CHECK(useSurfaceTexAlloc);
+
+            sp<SurfaceTexture> texture = new SurfaceTexture(0 /* tex */);
+            gSurface = new SurfaceTextureClient(texture);
+        }
     }
 
     DataSource::RegisterDefaultSniffers();
@@ -1061,12 +1068,12 @@
         }
     }
 
-    if (useSurfaceAlloc && !audioOnly) {
+    if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) {
         gSurface.clear();
 
-#if USE_SURFACE_COMPOSER
-        composerClient->dispose();
-#endif
+        if (useSurfaceAlloc) {
+            composerClient->dispose();
+        }
     }
 
     client.disconnect();
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index f780afb..ee91c29 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -20,6 +20,11 @@
 #include <media/mediaplayer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MPEG2TSWriter.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
 
 #include <binder/IServiceManager.h>
 #include <media/IMediaPlayerService.h>
@@ -31,7 +36,7 @@
 using namespace android;
 
 struct MyStreamSource : public BnStreamSource {
-    // Caller retains ownership of fd.
+    // Object assumes ownership of fd.
     MyStreamSource(int fd);
 
     virtual void setListener(const sp<IStreamListener> &listener);
@@ -64,6 +69,8 @@
 }
 
 MyStreamSource::~MyStreamSource() {
+    close(mFd);
+    mFd = -1;
 }
 
 void MyStreamSource::setListener(const sp<IStreamListener> &listener) {
@@ -99,6 +106,143 @@
         mListener->queueBuffer(index, n);
     }
 }
+////////////////////////////////////////////////////////////////////////////////
+
+struct MyConvertingStreamSource : public BnStreamSource {
+    MyConvertingStreamSource(const char *filename);
+
+    virtual void setListener(const sp<IStreamListener> &listener);
+    virtual void setBuffers(const Vector<sp<IMemory> > &buffers);
+
+    virtual void onBufferAvailable(size_t index);
+
+protected:
+    virtual ~MyConvertingStreamSource();
+
+private:
+    Mutex mLock;
+    Condition mCondition;
+
+    sp<IStreamListener> mListener;
+    Vector<sp<IMemory> > mBuffers;
+
+    sp<MPEG2TSWriter> mWriter;
+
+    ssize_t mCurrentBufferIndex;
+    size_t mCurrentBufferOffset;
+
+    List<size_t> mBufferQueue;
+
+    static ssize_t WriteDataWrapper(void *me, const void *data, size_t size);
+    ssize_t writeData(const void *data, size_t size);
+
+    DISALLOW_EVIL_CONSTRUCTORS(MyConvertingStreamSource);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+MyConvertingStreamSource::MyConvertingStreamSource(const char *filename)
+    : mCurrentBufferIndex(-1),
+      mCurrentBufferOffset(0) {
+    sp<DataSource> dataSource = DataSource::CreateFromURI(filename);
+    CHECK(dataSource != NULL);
+
+    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+    CHECK(extractor != NULL);
+
+    mWriter = new MPEG2TSWriter(
+            this, &MyConvertingStreamSource::WriteDataWrapper);
+
+    for (size_t i = 0; i < extractor->countTracks(); ++i) {
+        const sp<MetaData> &meta = extractor->getTrackMetaData(i);
+
+        const char *mime;
+        CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+        if (strncasecmp("video/", mime, 6) && strncasecmp("audio/", mime, 6)) {
+            continue;
+        }
+
+        CHECK_EQ(mWriter->addSource(extractor->getTrack(i)), (status_t)OK);
+    }
+
+    CHECK_EQ(mWriter->start(), (status_t)OK);
+}
+
+MyConvertingStreamSource::~MyConvertingStreamSource() {
+}
+
+void MyConvertingStreamSource::setListener(
+        const sp<IStreamListener> &listener) {
+    mListener = listener;
+}
+
+void MyConvertingStreamSource::setBuffers(
+        const Vector<sp<IMemory> > &buffers) {
+    mBuffers = buffers;
+}
+
+ssize_t MyConvertingStreamSource::WriteDataWrapper(
+        void *me, const void *data, size_t size) {
+    return static_cast<MyConvertingStreamSource *>(me)->writeData(data, size);
+}
+
+ssize_t MyConvertingStreamSource::writeData(const void *data, size_t size) {
+    size_t totalWritten = 0;
+
+    while (size > 0) {
+        Mutex::Autolock autoLock(mLock);
+
+        if (mCurrentBufferIndex < 0) {
+            while (mBufferQueue.empty()) {
+                mCondition.wait(mLock);
+            }
+
+            mCurrentBufferIndex = *mBufferQueue.begin();
+            mCurrentBufferOffset = 0;
+
+            mBufferQueue.erase(mBufferQueue.begin());
+        }
+
+        sp<IMemory> mem = mBuffers.itemAt(mCurrentBufferIndex);
+
+        size_t copy = size;
+        if (copy + mCurrentBufferOffset > mem->size()) {
+            copy = mem->size() - mCurrentBufferOffset;
+        }
+
+        memcpy((uint8_t *)mem->pointer() + mCurrentBufferOffset, data, copy);
+        mCurrentBufferOffset += copy;
+
+        if (mCurrentBufferOffset == mem->size()) {
+            mListener->queueBuffer(mCurrentBufferIndex, mCurrentBufferOffset);
+            mCurrentBufferIndex = -1;
+        }
+
+        data = (const uint8_t *)data + copy;
+        size -= copy;
+
+        totalWritten += copy;
+    }
+
+    return (ssize_t)totalWritten;
+}
+
+void MyConvertingStreamSource::onBufferAvailable(size_t index) {
+    Mutex::Autolock autoLock(mLock);
+
+    mBufferQueue.push_back(index);
+    mCondition.signal();
+
+    if (mWriter->reachedEOS()) {
+        if (mCurrentBufferIndex >= 0) {
+            mListener->queueBuffer(mCurrentBufferIndex, mCurrentBufferOffset);
+            mCurrentBufferIndex = -1;
+        }
+
+        mListener->issueCommand(IStreamListener::EOS, false /* synchronous */);
+    }
+}
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -139,6 +283,8 @@
 int main(int argc, char **argv) {
     android::ProcessState::self()->startThreadPool();
 
+    DataSource::RegisterDefaultSniffers();
+
     if (argc != 2) {
         fprintf(stderr, "Usage: %s filename\n", argv[0]);
         return 1;
@@ -159,10 +305,10 @@
     CHECK(control != NULL);
     CHECK(control->isValid());
 
-    CHECK_EQ(composerClient->openTransaction(), (status_t)OK);
+    SurfaceComposerClient::openGlobalTransaction();
     CHECK_EQ(control->setLayer(30000), (status_t)OK);
     CHECK_EQ(control->show(), (status_t)OK);
-    CHECK_EQ(composerClient->closeTransaction(), (status_t)OK);
+    SurfaceComposerClient::closeGlobalTransaction();
 
     sp<Surface> surface = control->getSurface();
     CHECK(surface != NULL);
@@ -173,17 +319,28 @@
 
     CHECK(service.get() != NULL);
 
-    int fd = open(argv[1], O_RDONLY);
-
-    if (fd < 0) {
-        fprintf(stderr, "Failed to open file '%s'.", argv[1]);
-        return 1;
-    }
-
     sp<MyClient> client = new MyClient;
 
+    sp<IStreamSource> source;
+
+    size_t len = strlen(argv[1]);
+    if (len >= 3 && !strcasecmp(".ts", &argv[1][len - 3])) {
+        int fd = open(argv[1], O_RDONLY);
+
+        if (fd < 0) {
+            fprintf(stderr, "Failed to open file '%s'.", argv[1]);
+            return 1;
+        }
+
+        source = new MyStreamSource(fd);
+    } else {
+        printf("Converting file to transport stream for streaming...\n");
+
+        source = new MyConvertingStreamSource(argv[1]);
+    }
+
     sp<IMediaPlayer> player =
-        service->create(getpid(), client, new MyStreamSource(fd), 0);
+        service->create(getpid(), client, source, 0);
 
     if (player != NULL) {
         player->setVideoSurface(surface);
@@ -196,9 +353,6 @@
         fprintf(stderr, "failed to instantiate player.\n");
     }
 
-    close(fd);
-    fd = -1;
-
     composerClient->dispose();
 
     return 0;
diff --git a/cmds/system_server/library/system_init.cpp b/cmds/system_server/library/system_init.cpp
index a19711e..59360d3 100644
--- a/cmds/system_server/library/system_init.cpp
+++ b/cmds/system_server/library/system_init.cpp
@@ -76,23 +76,6 @@
         SensorService::instantiate();
     }
 
-    // On the simulator, audioflinger et al don't get started the
-    // same way as on the device, and we need to start them here
-    if (!proc->supportsProcesses()) {
-
-        // Start the AudioFlinger
-        AudioFlinger::instantiate();
-
-        // Start the media playback service
-        MediaPlayerService::instantiate();
-
-        // Start the camera service
-        CameraService::instantiate();
-
-        // Start the audio policy service
-        AudioPolicyService::instantiate();
-    }
-
     // And now start the Android runtime.  We have to do this bit
     // of nastiness because the Android runtime initialization requires
     // some of the core system services to already be started.
@@ -117,14 +100,10 @@
     }
     env->CallStaticVoidMethod(clazz, methodId);
 
-    // If running in our own process, just go into the thread
-    // pool.  Otherwise, call the initialization finished
-    // func to let this process continue its initilization.
-    if (proc->supportsProcesses()) {
-        LOGI("System server: entering thread pool.\n");
-        ProcessState::self()->startThreadPool();
-        IPCThreadState::self()->joinThreadPool();
-        LOGI("System server: exiting thread pool.\n");
-    }
+    LOGI("System server: entering thread pool.\n");
+    ProcessState::self()->startThreadPool();
+    IPCThreadState::self()->joinThreadPool();
+    LOGI("System server: exiting thread pool.\n");
+
     return NO_ERROR;
 }
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 164acbc..68c9926 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -31,82 +31,151 @@
  * An accessibility service runs in the background and receives callbacks by the system
  * when {@link AccessibilityEvent}s are fired. Such events denote some state transition
  * in the user interface, for example, the focus has changed, a button has been clicked,
- * etc.
+ * etc. Such a service can optionally request the capability for querying the content
+ * of the active window. Development of an accessibility service requires extends this
+ * class and implements its abstract methods.
  * <p>
- * An accessibility service extends this class and implements its abstract methods. Such
- * a service is declared as any other service in an AndroidManifest.xml but it must also
- * specify that it handles the "android.accessibilityservice.AccessibilityService"
- * {@link android.content.Intent}. Following is an example of such a declaration:
- * <p>
- * <code>
- * &lt;service android:name=".MyAccessibilityService"&gt;<br>
- * &nbsp;&nbsp;&lt;intent-filter&gt;<br>
- * &nbsp;&nbsp;&nbsp;&nbsp;&lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;<br>
- * &nbsp;&nbsp;&lt;/intent-filter&gt;<br>
- * &lt;/service&gt;<br>
- * </code>
+ * <strong>Lifecycle</strong>
  * </p>
  * <p>
- * The lifecycle of an accessibility service is managed exclusively by the system. Starting
- * or stopping an accessibility service is triggered by an explicit user action through
+ * The lifecycle of an accessibility service is managed exclusively by the system and
+ * follows the established service life cycle. Additionally, starting or stopping an
+ * accessibility service is triggered exclusively by an explicit user action through
  * enabling or disabling it in the device settings. After the system binds to a service it
  * calls {@link AccessibilityService#onServiceConnected()}. This method can be
  * overriden by clients that want to perform post binding setup.
  * </p>
  * <p>
+ * <strong>Declaration</strong>
+ * </p>
+ * <p>
+ * An accessibility is declared as any other service in an AndroidManifest.xml but it
+ * must also specify that it handles the "android.accessibilityservice.AccessibilityService"
+ * {@link android.content.Intent}. Failure to declare this intent will cause the system to
+ * ignore the accessibility service. Following is an example declaration:
+ * </p>
+ * <p>
+ * <code>
+ * <pre>
+ *   &lt;service android:name=".MyAccessibilityService"&gt;
+ *     &lt;intent-filter&gt;
+ *       &lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;
+ *     &lt;/intent-filter&gt;
+ *     . . .
+ *   &lt;/service&gt;
+ * </pre>
+ * </code>
+ * </p>
+ * <p>
+ * <strong>Configuration</strong>
+ * </p>
+ * <p>
  * An accessibility service can be configured to receive specific types of accessibility events,
  * listen only to specific packages, get events from each type only once in a given time frame,
  * retrieve window content, specify a settings activity, etc.
  * </p>
+ * <p>
  * There are two approaches for configuring an accessibility service:
+ * </p>
  * <ul>
- *   <li>
- *     Providing a {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring
- *     the service. A service declaration with a meta-data tag is presented below:
- *     <p>
- *       <code>
- *         &lt;service android:name=".MyAccessibilityService"&gt;<br>
- *         &nbsp;&nbsp;&lt;intent-filter&gt;<br>
- *         &nbsp;&nbsp;&nbsp;&nbsp;&lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;<br>
- *         &nbsp;&nbsp;&lt;/intent-filter&gt;<br>
- *         &nbsp;&nbsp;&lt;meta-data android:name="android.accessibilityservice.as" android:resource="@xml/accessibilityservice" /&gt;<br>
- *         &lt;/service&gt;<br>
- *       </code>
- *     </p>
- *     <p>
- *     <strong>
- *       This approach enables setting all accessibility service properties.
- *     </strong>
- *     </p>
- *     <p>
- *       For more details refer to {@link #SERVICE_META_DATA}.
- *     </p>
- *   </li>
- *   <li>
- *     Calling {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. Note
- *     that this method can be called any time to change the service configuration.<br>
- *     <p>
- *     <strong>
- *       This approach enables setting only dynamically configurable accessibility
- *       service properties:
- *       {@link AccessibilityServiceInfo#eventTypes},
- *       {@link AccessibilityServiceInfo#feedbackType},
- *       {@link AccessibilityServiceInfo#flags},
- *       {@link AccessibilityServiceInfo#notificationTimeout},
- *       {@link AccessibilityServiceInfo#packageNames}
- *     </strong>
- *     </p>
- *     <p>
- *       For more details refer to {@link AccessibilityServiceInfo}.
- *     </p>
- *   </li>
+ * <li>
+ * Providing a {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring
+ * the service. A service declaration with a meta-data tag is presented below:
+ * <p>
+ * <code>
+ * <pre>
+ *   &lt;service android:name=".MyAccessibilityService"&gt;
+ *     &lt;intent-filter&gt;
+ *       &lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;
+ *     &lt;/intent-filter&gt;
+ *     &lt;meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibilityservice" /&gt;
+ *   &lt;/service&gt;
+ * </pre>
+ * </code>
+ * </p>
+ * <p>
+ * <strong>Note:</strong>This approach enables setting all properties.
+ * </p>
+ * <p>
+ * For more details refer to {@link #SERVICE_META_DATA} and
+ * <code>&lt;{@link android.R.styleable#AccessibilityService accessibility-service}&gt;</code>..
+ * </p>
+ * </li>
+ * <li>
+ * Calling {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. Note
+ * that this method can be called any time to dynamically change the service configuration.
+ * <p>
+ * <strong>Note:</strong> This approach enables setting only dynamically configurable properties:
+ * {@link AccessibilityServiceInfo#eventTypes},
+ * {@link AccessibilityServiceInfo#feedbackType},
+ * {@link AccessibilityServiceInfo#flags},
+ * {@link AccessibilityServiceInfo#notificationTimeout},
+ * {@link AccessibilityServiceInfo#packageNames}
+ * </p>
+ * <p>
+ * For more details refer to {@link AccessibilityServiceInfo}.
+ * </p>
+ * </li>
  * </ul>
  * <p>
- * An accessibility service can be registered for events in specific packages to provide a
- * specific type of feedback and is notified with a certain timeout after the last event
- * of interest has been fired.
+ * <strong>Retrieving window content</strong>
+ * </p>
+ * <p>
+ * An service can specify in its declaration that it can retrieve the active window
+ * content which is represented as a tree of {@link AccessibilityNodeInfo}. Note that
+ * declaring this capability requires that the service declares its configuration via
+ * an XML resource referenced by {@link #SERVICE_META_DATA}.
+ * </p>
+ * <p>
+ * For security purposes an accessibility service can retrieve only the content of the
+ * currently active window. The currently active window is defined as the window from
+ * which was fired the last event of the following types:
+ * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START},
+ * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END},
+ * {@link AccessibilityEvent#TYPE_VIEW_CLICKED},
+ * {@link AccessibilityEvent#TYPE_VIEW_FOCUSED},
+ * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER},
+ * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT},
+ * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED},
+ * {@link AccessibilityEvent#TYPE_VIEW_SELECTED},
+ * {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED},
+ * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED},
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED},
+ * {@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED},
+ * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}.
+ * In other words, the active window is the one where the user interaction is taking place.
+ * </p>
+ * <p>
+ * The entry point for retrieving window content is through calling
+ * {@link AccessibilityEvent#getSource() AccessibilityEvent.getSource()} of the last received
+ * event of the above types or a previous event from the same window
+ * (see {@link AccessibilityEvent#getWindowId() AccessibilityEvent.getWindowId()}). Invoking
+ * this method will return an {@link AccessibilityNodeInfo} that can be used to traverse the
+ * window content which represented as a tree of such objects.
+ * </p>
+ * <p>
+ * <strong>Note</strong>An accessibility service may have requested to be notified for
+ * a subset of the event types, thus be unaware that the active window has changed. Therefore
+ * accessibility service that would like to retrieve window content should:
+ * <ul>
+ * <li>
+ * Register for all event types with no notification timeout and keep track for the active
+ * window by calling {@link AccessibilityEvent#getWindowId()} of the last received event and
+ * compare this with the {@link AccessibilityNodeInfo#getWindowId()} before calling retrieval
+ * methods on the latter.
+ * </li>
+ * <li>
+ * Prepare that a retrieval method on {@link AccessibilityNodeInfo} may fail since the
+ * active window has changed and the service did not get the accessibility event yet. Note
+ * that it is possible to have a retrieval method failing event adopting the strategy
+ * specified in the previous bullet because the accessibility event dispatch is asynchronous
+ * and crosses process boundaries.
+ * </li>
+ * </ul>
+ * </p>
  * <p>
  * <b>Notification strategy</b>
+ * </p>
  * <p>
  * For each feedback type only one accessibility service is notified. Services are notified
  * in the order of registration. Hence, if two services are registered for the same
@@ -117,9 +186,10 @@
  * registration order. This enables "generic" accessibility services that work reasonably
  * well with most applications to coexist with "polished" ones that are targeted for
  * specific applications.
+ * </p>
  * <p>
  * <b>Event types</b>
- * <p>
+ * </p>
  * {@link AccessibilityEvent#TYPE_VIEW_CLICKED}
  * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}
  * {@link AccessibilityEvent#TYPE_VIEW_FOCUSED}
@@ -127,9 +197,16 @@
  * {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED}
  * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}
  * {@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED}
- *  <p>
- *  <b>Feedback types</b>
- *  <p>
+ * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START}
+ * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END}
+ * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}
+ * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED}
+ * {@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED}
+ * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}
+ * <p>
+ * <b>Feedback types</b>
+ * <p>
  * {@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}
  * {@link AccessibilityServiceInfo#FEEDBACK_HAPTIC}
  * {@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}
@@ -140,10 +217,10 @@
  * @see AccessibilityServiceInfo
  * @see android.view.accessibility.AccessibilityManager
  *
- * Note: The event notification timeout is useful to avoid propagating events to the client
- *       too frequently since this is accomplished via an expensive interprocess call.
- *       One can think of the timeout as a criteria to determine when event generation has
- *       settled down.
+ * <strong>Note:</strong> The event notification timeout is useful to avoid propagating
+ * events to the client too frequently since this is accomplished via an expensive
+ * interprocess call. One can think of the timeout as a criteria to determine when
+ * event generation has settled down.
  */
 public abstract class AccessibilityService extends Service {
     /**
@@ -154,57 +231,25 @@
 
     /**
      * Name under which an AccessibilityService component publishes information
-     * about itself. This meta-data must reference an XML resource containing
-     * an
+     * about itself. This meta-data must reference an XML resource containing an
      * <code>&lt;{@link android.R.styleable#AccessibilityService accessibility-service}&gt;</code>
      * tag. This is a a sample XML file configuring an accessibility service:
      * <p>
      * <code>
-     *   &lt;?xml version="1.0" encoding="utf-8"?&gt;<br>
-     *   &lt;accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"<br>
-     *   &nbsp;&nbsp;android:accessibilityEventTypes="typeViewClicked|typeViewFocused"<br>
-     *   &nbsp;&nbsp;android:packageNames="foo.bar, foo.baz"<br>
-     *   &nbsp;&nbsp;android:accessibilityFeedbackType="feedbackSpoken"<br>
-     *   &nbsp;&nbsp;android:notificationTimeout="100"<br>
-     *   &nbsp;&nbsp;android:accessibilityFlags="flagDefault"<br>
-     *   &nbsp;&nbsp;android:settingsActivity="foo.bar.TestBackActivity"<br>
-     *   &nbsp;&nbsp;. . .<br>
+     * <pre>
+     *   &lt;accessibility-service
+     *     android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
+     *     android:packageNames="foo.bar, foo.baz"
+     *     android:accessibilityFeedbackType="feedbackSpoken"
+     *     android:notificationTimeout="100"
+     *     android:accessibilityFlags="flagDefault"
+     *     android:settingsActivity="foo.bar.TestBackActivity"
+     *     android:canRetrieveWindowContent="true"
+     *     . . .
      *   /&gt;
+     * </pre>
      * </code>
      * </p>
-     * <p>
-     *  <strong>Note:</strong> A service can retrieve only the content of the active window.
-     *          An active window is the source of the most recent event of type
-     *          {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START},
-     *          {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END},
-     *          {@link AccessibilityEvent#TYPE_VIEW_CLICKED},
-     *          {@link AccessibilityEvent#TYPE_VIEW_FOCUSED},
-     *          {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER},
-     *          {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT},
-     *          {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED},
-     *          {@link AccessibilityEvent#TYPE_VIEW_SELECTED},
-     *          {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED},
-     *          {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}.
-     *          Therefore the service should:
-     *          <ul>
-     *            <li>
-     *              Register for all event types with no notification timeout and keep track
-     *              for the active window by calling
-     *              {@link AccessibilityEvent#getWindowId()} of the last received
-     *              event and compare this with the
-     *              {@link AccessibilityNodeInfo#getWindowId()} before calling
-     *              retrieval methods on the latter.
-     *            </li>
-     *            <li>
-     *              Prepare that a retrieval method on {@link AccessibilityNodeInfo} may fail
-     *              since the active window has changed and the service did not get the 
-     *              accessibility event. Note that it is possible to have a retrieval method
-     *              failing event adopting the strategy specified in the previous bullet
-     *              because the accessibility event dispatch is asynchronous and crosses
-     *              process boundaries. 
-     *            </li>
-     *          <ul>
-     * </p>
      */
     public static final String SERVICE_META_DATA = "android.accessibilityservice";
 
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index b9878cd..ef4adca 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -37,13 +37,13 @@
 import java.io.IOException;
 
 /**
- * This class describes an {@link AccessibilityService}. The system
- * notifies an {@link AccessibilityService} for
- * {@link android.view.accessibility.AccessibilityEvent}s
+ * This class describes an {@link AccessibilityService}. The system notifies an
+ * {@link AccessibilityService} for {@link android.view.accessibility.AccessibilityEvent}s
  * according to the information encapsulated in this class.
  *
  * @see AccessibilityService
  * @see android.view.accessibility.AccessibilityEvent
+ * @see android.view.accessibility.AccessibilityManager
  */
 public class AccessibilityServiceInfo implements Parcelable {
 
@@ -93,12 +93,19 @@
      * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED
      * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED
      * @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_EXIT
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED
+     * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED
      */
     public int eventTypes;
 
     /**
      * The package names an {@link AccessibilityService} is interested in. Setting
-     * to null is equivalent to all packages.
+     * to <code>null</code> is equivalent to all packages.
      * <p>
      *   <strong>Can be dynamically set at runtime.</strong>
      * </p>
@@ -125,10 +132,10 @@
      *   <strong>Can be dynamically set at runtime.</strong>.
      * </p>
      * <p>
-     * Note: The event notification timeout is useful to avoid propagating events to the client
-     *       too frequently since this is accomplished via an expensive interprocess call.
-     *       One can think of the timeout as a criteria to determine when event generation has
-     *       settled down
+     * <strong>Note:</strong> The event notification timeout is useful to avoid propagating
+     *       events to the client too frequently since this is accomplished via an expensive
+     *       interprocess call. One can think of the timeout as a criteria to determine when
+     *       event generation has settled down.
      */
     public long notificationTimeout;
 
@@ -159,7 +166,7 @@
     private String mSettingsActivityName;
 
     /**
-     * Flag whether this accessibility service can retrieve screen content.
+     * Flag whether this accessibility service can retrieve window content.
      */
     private boolean mCanRetrieveWindowContent;
 
@@ -296,12 +303,12 @@
     }
 
     /**
-     * Whether this service can retrieve the currently focused window content.
+     * Whether this service can retrieve the current window's content.
      * <p>
      *    <strong>Statically set from
      *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
      * </p>
-     * @return True screen content is retrieved.
+     * @return True window content can be retrieved.
      */
     public boolean getCanRetrieveWindowContent() {
         return mCanRetrieveWindowContent;
diff --git a/core/java/android/accessibilityservice/package.html b/core/java/android/accessibilityservice/package.html
new file mode 100644
index 0000000..0c640d1
--- /dev/null
+++ b/core/java/android/accessibilityservice/package.html
@@ -0,0 +1,22 @@
+<html>
+<body>
+<p>
+  The classes in this package are used for development of accessibility service that
+  provide alternative or augmented feedback to the user.
+</p>
+<p>
+  An {@link android.accessibilityservice.AccessibilityService} runs in the background and
+  receives callbacks by the system when {@link android.view.accessibility.AccessibilityEvent}s
+  are fired. Such events denote some state transition in the user interface, for example, the
+  focus has changed, a button has been clicked, etc. Such a service can optionally request the
+  capability for querying the content of the active window. Development of an accessibility
+  service requires extends this class and implements its abstract methods.
+</p>
+<p>
+  An {@link android.accessibilityservice.AccessibilityServiceInfo} describes an
+  {@link android.accessibilityservice.AccessibilityService}. The system notifies an
+  AccessibilityService for {@link android.view.accessibility.AccessibilityEvent}s
+  according to the information encapsulated in this class.
+</p>
+</body>
+</html>
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 85f40c9..fdf4a3a 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -251,12 +251,13 @@
             IBinder b = data.readStrongBinder();
             IApplicationThread app =
                 b != null ? ApplicationThreadNative.asInterface(b) : null;
+            String packageName = data.readString();
             b = data.readStrongBinder();
             IIntentReceiver rec
                 = b != null ? IIntentReceiver.Stub.asInterface(b) : null;
             IntentFilter filter = IntentFilter.CREATOR.createFromParcel(data);
             String perm = data.readString();
-            Intent intent = registerReceiver(app, rec, filter, perm);
+            Intent intent = registerReceiver(app, packageName, rec, filter, perm);
             reply.writeNoException();
             if (intent != null) {
                 reply.writeInt(1);
@@ -1503,6 +1504,16 @@
             return true;
         }
 
+        case IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IIntentSender r = IIntentSender.Stub.asInterface(
+                data.readStrongBinder());
+            boolean res = isIntentSenderTargetedToPackage(r);
+            reply.writeNoException();
+            reply.writeInt(res ? 1 : 0);
+            return true;
+        }
+
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -1702,7 +1713,7 @@
         reply.recycle();
         return res;
     }
-    public Intent registerReceiver(IApplicationThread caller,
+    public Intent registerReceiver(IApplicationThread caller, String packageName,
             IIntentReceiver receiver,
             IntentFilter filter, String perm) throws RemoteException
     {
@@ -1710,6 +1721,7 @@
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(caller != null ? caller.asBinder() : null);
+        data.writeString(packageName);
         data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
         filter.writeToParcel(data, 0);
         data.writeString(perm);
@@ -3385,5 +3397,18 @@
         reply.recycle();
     }
 
+    public boolean isIntentSenderTargetedToPackage(IIntentSender sender) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(sender.asBinder());
+        mRemote.transact(IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION, data, reply, 0);
+        reply.readException();
+        boolean res = reply.readInt() != 0;
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
+
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1ec7a96..ee04729 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2013,15 +2013,10 @@
         BackupAgent agent = null;
         String classname = data.appInfo.backupAgentName;
 
-        if (data.backupMode == IApplicationThread.BACKUP_MODE_FULL
-                || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL) {
+        // full backup operation but no app-supplied agent?  use the default implementation
+        if (classname == null && (data.backupMode == IApplicationThread.BACKUP_MODE_FULL
+                || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL)) {
             classname = "android.app.backup.FullBackupAgent";
-            if ((data.appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
-                // system packages can supply their own full-backup agent
-                if (data.appInfo.fullBackupAgentName != null) {
-                    classname = data.appInfo.fullBackupAgentName;
-                }
-            }
         }
 
         try {
@@ -4098,11 +4093,6 @@
         });
     }
 
-    private final void detach()
-    {
-        sThreadLocal.set(null);
-    }
-
     public static final ActivityThread systemMain() {
         HardwareRenderer.disable();
         ActivityThread thread = new ActivityThread();
@@ -4110,10 +4100,9 @@
         return thread;
     }
 
-    public final void installSystemProviders(List providers) {
+    public final void installSystemProviders(List<ProviderInfo> providers) {
         if (providers != null) {
-            installContentProviders(mInitialApplication,
-                                    (List<ProviderInfo>)providers);
+            installContentProviders(mInitialApplication, providers);
         }
     }
 
@@ -4152,14 +4141,6 @@
 
         Looper.loop();
 
-        if (Process.supportsProcesses()) {
-            throw new RuntimeException("Main thread loop unexpectedly exited");
-        }
-
-        thread.detach();
-        String name = (thread.mInitialApplication != null)
-            ? thread.mInitialApplication.getPackageName()
-            : "<unknown>";
-        Slog.i(TAG, "Main thread of " + name + " is now exiting");
+        throw new RuntimeException("Main thread loop unexpectedly exited");
     }
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 94a4afa..d2323e7 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -61,7 +61,6 @@
 import android.net.wifi.WifiManager;
 import android.nfc.NfcManager;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.DropBoxManager;
 import android.os.Environment;
@@ -81,7 +80,6 @@
 import android.util.AndroidRuntimeException;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
-import android.view.Display;
 import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityManager;
 import android.view.inputmethod.InputMethodManager;
@@ -142,6 +140,7 @@
             new HashMap<String, SharedPreferencesImpl>();
 
     /*package*/ LoadedApk mPackageInfo;
+    private String mBasePackageName;
     private Resources mResources;
     /*package*/ ActivityThread mMainThread;
     private Context mOuterContext;
@@ -1030,7 +1029,7 @@
         }
         try {
             return ActivityManagerNative.getDefault().registerReceiver(
-                    mMainThread.getApplicationThread(),
+                    mMainThread.getApplicationThread(), mBasePackageName,
                     rd, filter, broadcastPermission);
         } catch (RemoteException e) {
             return null;
@@ -1164,9 +1163,6 @@
             throw new IllegalArgumentException("permission is null");
         }
 
-        if (!Process.supportsProcesses()) {
-            return PackageManager.PERMISSION_GRANTED;
-        }
         try {
             return ActivityManagerNative.getDefault().checkPermission(
                     permission, pid, uid);
@@ -1181,9 +1177,6 @@
             throw new IllegalArgumentException("permission is null");
         }
 
-        if (!Process.supportsProcesses()) {
-            return PackageManager.PERMISSION_GRANTED;
-        }
         int pid = Binder.getCallingPid();
         if (pid != Process.myPid()) {
             return checkPermission(permission, pid,
@@ -1264,9 +1257,6 @@
 
     @Override
     public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
-        if (!Process.supportsProcesses()) {
-            return PackageManager.PERMISSION_GRANTED;
-        }
         try {
             return ActivityManagerNative.getDefault().checkUriPermission(
                     uri, pid, uid, modeFlags);
@@ -1277,9 +1267,6 @@
 
     @Override
     public int checkCallingUriPermission(Uri uri, int modeFlags) {
-        if (!Process.supportsProcesses()) {
-            return PackageManager.PERMISSION_GRANTED;
-        }
         int pid = Binder.getCallingPid();
         if (pid != Process.myPid()) {
             return checkUriPermission(uri, pid,
@@ -1397,7 +1384,7 @@
         if (pi != null) {
             ContextImpl c = new ContextImpl();
             c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
-            c.init(pi, null, mMainThread, mResources);
+            c.init(pi, null, mMainThread, mResources, mBasePackageName);
             if (c.mResources != null) {
                 return c;
             }
@@ -1450,6 +1437,7 @@
      */
     public ContextImpl(ContextImpl context) {
         mPackageInfo = context.mPackageInfo;
+        mBasePackageName = context.mBasePackageName;
         mResources = context.mResources;
         mMainThread = context.mMainThread;
         mContentResolver = context.mContentResolver;
@@ -1458,13 +1446,14 @@
 
     final void init(LoadedApk packageInfo,
             IBinder activityToken, ActivityThread mainThread) {
-        init(packageInfo, activityToken, mainThread, null);
+        init(packageInfo, activityToken, mainThread, null, null);
     }
 
     final void init(LoadedApk packageInfo,
                 IBinder activityToken, ActivityThread mainThread,
-                Resources container) {
+                Resources container, String basePackageName) {
         mPackageInfo = packageInfo;
+        mBasePackageName = basePackageName != null ? basePackageName : packageInfo.mPackageName;
         mResources = mPackageInfo.getResources(mainThread);
 
         if (mResources != null && container != null
@@ -1485,6 +1474,7 @@
 
     final void init(Resources resources, ActivityThread mainThread) {
         mPackageInfo = null;
+        mBasePackageName = null;
         mResources = resources;
         mMainThread = mainThread;
         mContentResolver = new ApplicationContentResolver(this, mainThread);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index e2588cf..9e20764 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -103,7 +103,7 @@
             throws RemoteException;
     public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException;
     public boolean willActivityBeVisible(IBinder token) throws RemoteException;
-    public Intent registerReceiver(IApplicationThread caller,
+    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
             IIntentReceiver receiver, IntentFilter filter,
             String requiredPermission) throws RemoteException;
     public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException;
@@ -361,6 +361,8 @@
     public void registerProcessObserver(IProcessObserver observer) throws RemoteException;
     public void unregisterProcessObserver(IProcessObserver observer) throws RemoteException;
 
+    public boolean isIntentSenderTargetedToPackage(IIntentSender sender) throws RemoteException;
+
     /*
      * Private non-Binder interfaces
      */
@@ -587,4 +589,5 @@
     int REMOVE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+131;
     int REGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+132;
     int UNREGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+133;
+    int IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+134;
 }
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index 8af78fa..087f83c 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -51,7 +51,6 @@
     void doBackup(in ParcelFileDescriptor oldState,
             in ParcelFileDescriptor data,
             in ParcelFileDescriptor newState,
-            boolean storeApk,
             int token, IBackupManager callbackBinder);
 
     /**
@@ -81,6 +80,25 @@
             in ParcelFileDescriptor newState, int token, IBackupManager callbackBinder);
 
     /**
+     * Perform a "full" backup to the given file descriptor.  The output file is presumed
+     * to be a socket or other non-seekable, write-only data sink.  When this method is
+     * called, the app should write all of its files to the output.
+     *
+     * @param data Write-only file to receive the backed-up file content stream.
+     *        The data must be formatted correctly for the resulting archive to be
+     *        legitimate, so that will be tightly controlled by the available API.
+     *
+     * @param token Opaque token identifying this transaction.  This must
+     *        be echoed back to the backup service binder once the agent is
+     *        finished restoring the application based on the restore data
+     *        contents.
+     *
+     * @param callbackBinder Binder on which to indicate operation completion,
+     *        passed here as a convenience to the agent.
+     */
+    void doFullBackup(in ParcelFileDescriptor data, int token, IBackupManager callbackBinder);
+
+    /**
      * Restore a single "file" to the application.  The file was typically obtained from
      * a full-backup dataset.  The agent reads 'size' bytes of file content
      * from the provided file descriptor.
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index cb03d2c..688cdfd 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -19,6 +19,7 @@
 import android.app.SearchableInfo;
 import android.app.ISearchManagerCallback;
 import android.content.ComponentName;
+import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.os.Bundle;
 
@@ -26,6 +27,7 @@
 interface ISearchManager {
    SearchableInfo getSearchableInfo(in ComponentName launchActivity);
    List<SearchableInfo> getSearchablesInGlobalSearch();
+   List<ResolveInfo> getGlobalSearchActivities();
    ComponentName getGlobalSearchActivity();
    ComponentName getWebSearchActivity();
 }
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 5b43b65..b4827cb 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -365,7 +365,7 @@
      * is no longer allowing more intents to be sent through it.
      */
     public void send() throws CanceledException {
-        send(null, 0, null, null, null);
+        send(null, 0, null, null, null, null);
     }
 
     /**
@@ -379,7 +379,7 @@
      * is no longer allowing more intents to be sent through it.
      */
     public void send(int code) throws CanceledException {
-        send(null, code, null, null, null);
+        send(null, code, null, null, null, null);
     }
 
     /**
@@ -399,7 +399,7 @@
      */
     public void send(Context context, int code, Intent intent)
             throws CanceledException {
-        send(context, code, intent, null, null);
+        send(context, code, intent, null, null, null);
     }
 
     /**
@@ -420,7 +420,7 @@
      */
     public void send(int code, OnFinished onFinished, Handler handler)
             throws CanceledException {
-        send(null, code, null, onFinished, handler);
+        send(null, code, null, onFinished, handler, null);
     }
 
     /**
@@ -449,20 +449,64 @@
      * @see #send(int)
      * @see #send(Context, int, Intent)
      * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
+     * @see #send(Context, int, Intent, OnFinished, Handler, String)
      *
      * @throws CanceledException Throws CanceledException if the PendingIntent
      * is no longer allowing more intents to be sent through it.
      */
     public void send(Context context, int code, Intent intent,
             OnFinished onFinished, Handler handler) throws CanceledException {
+        send(context, code, intent, onFinished, handler, null);
+    }
+
+    /**
+     * Perform the operation associated with this PendingIntent, allowing the
+     * caller to specify information about the Intent to use and be notified
+     * when the send has completed.
+     *
+     * <p>For the intent parameter, a PendingIntent
+     * often has restrictions on which fields can be supplied here, based on
+     * how the PendingIntent was retrieved in {@link #getActivity},
+     * {@link #getBroadcast}, or {@link #getService}.
+     *
+     * @param context The Context of the caller.  This may be null if
+     * <var>intent</var> is also null.
+     * @param code Result code to supply back to the PendingIntent's target.
+     * @param intent Additional Intent data.  See {@link Intent#fillIn
+     * Intent.fillIn()} for information on how this is applied to the
+     * original Intent.  Use null to not modify the original Intent.
+     * @param onFinished The object to call back on when the send has
+     * completed, or null for no callback.
+     * @param handler Handler identifying the thread on which the callback
+     * should happen.  If null, the callback will happen from the thread
+     * pool of the process.
+     * @param requiredPermission Name of permission that a recipient of the PendingIntent
+     * is required to hold.  This is only valid for broadcast intents, and
+     * corresponds to the permission argument in
+     * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
+     * If null, no permission is required.
+     *
+     * @see #send()
+     * @see #send(int)
+     * @see #send(Context, int, Intent)
+     * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
+     * @see #send(Context, int, Intent, OnFinished, Handler)
+     *
+     * @throws CanceledException Throws CanceledException if the PendingIntent
+     * is no longer allowing more intents to be sent through it.
+     */
+    public void send(Context context, int code, Intent intent,
+            OnFinished onFinished, Handler handler, String requiredPermission)
+            throws CanceledException {
         try {
             String resolvedType = intent != null ?
                     intent.resolveTypeIfNeeded(context.getContentResolver())
                     : null;
             int res = mTarget.send(code, intent, resolvedType,
                     onFinished != null
-                    ? new FinishedDispatcher(this, onFinished, handler)
-                    : null);
+                            ? new FinishedDispatcher(this, onFinished, handler)
+                            : null,
+                    requiredPermission);
             if (res < 0) {
                 throw new CanceledException();
             }
@@ -491,6 +535,20 @@
     }
 
     /**
+     * @hide
+     * Check to verify that this PendingIntent targets a specific package.
+     */
+    public boolean isTargetedToPackage() {
+        try {
+            return ActivityManagerNative.getDefault()
+                .isIntentSenderTargetedToPackage(mTarget);
+        } catch (RemoteException e) {
+            // Should never happen.
+            return false;
+        }
+    }
+
+    /**
      * Comparison operator on two PendingIntent objects, such that true
      * is returned then they both represent the same operation from the
      * same package.  This allows you to use {@link #getActivity},
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 41eea2e..42eda02 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -188,8 +188,9 @@
         mSearchPlate = mSearchView.findViewById(com.android.internal.R.id.search_plate);
         mWorkingSpinner = getContext().getResources().
                 getDrawable(com.android.internal.R.drawable.search_spinner);
-        mSearchAutoComplete.setCompoundDrawablesWithIntrinsicBounds(
-                null, null, mWorkingSpinner, null);
+        // TODO: Restore the spinner for slow suggestion lookups
+        // mSearchAutoComplete.setCompoundDrawablesWithIntrinsicBounds(
+        //        null, null, mWorkingSpinner, null);
         setWorking(false);
 
         // pre-hide all the extraneous elements
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index aab087f..7274362 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.pm.ResolveInfo;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
@@ -328,6 +329,15 @@
     public final static String SUGGEST_COLUMN_FLAGS = "suggest_flags";
 
     /**
+     * Column name for suggestions cursor. <i>Optional.</i> This column may be
+     * used to specify the time in (@link System#currentTimeMillis
+     * System.currentTImeMillis()} (wall time in UTC) when an item was last
+     * accessed within the results-providing application. If set, this may be
+     * used to show more-recently-used items first.
+     */
+    public final static String SUGGEST_COLUMN_LAST_ACCESS_HINT = "suggest_last_access_hint";
+
+    /**
      * Column value for suggestion column {@link #SUGGEST_COLUMN_SHORTCUT_ID} when a suggestion
      * should not be stored as a shortcut in global search.
      */
@@ -374,6 +384,17 @@
             = "android.search.action.SEARCHABLES_CHANGED";
 
     /**
+     * Intent action to be broadcast to inform that the global search provider
+     * has changed. Normal components will have no need to handle this intent since
+     * they should be using API methods from this class to access the global search
+     * activity
+     *
+     * @hide
+     */
+    public final static String INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED
+            = "android.search.action.GLOBAL_SEARCH_ACTIVITY_CHANGED";
+
+    /**
      * Intent action broadcasted to inform that the search settings have changed in some way.
      * Either searchables have been enabled or disabled, or a different web search provider
      * has been chosen.
@@ -526,6 +547,21 @@
     }
 
     /**
+     * Returns a list of installed apps that handle the global search
+     * intent.
+     *
+     * @hide
+     */
+    public List<ResolveInfo> getGlobalSearchActivities() {
+        try {
+            return mService.getGlobalSearchActivities();
+        } catch (RemoteException ex) {
+            Log.e(TAG, "getGlobalSearchActivities() failed: " + ex);
+            return null;
+        }
+    }
+
+    /**
      * Gets the name of the global search activity.
      *
      * @hide
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 63f3258..dce0a97 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -20,13 +20,22 @@
 import android.app.backup.IBackupManager;
 import android.content.Context;
 import android.content.ContextWrapper;
+import android.content.pm.ApplicationInfo;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.util.Log;
 
+import java.io.File;
 import java.io.IOException;
+import java.util.HashSet;
+import java.util.LinkedList;
+
+import libcore.io.ErrnoException;
+import libcore.io.Libcore;
+import libcore.io.OsConstants;
+import libcore.io.StructStat;
 
 /**
  * Provides the central interface between an
@@ -87,6 +96,24 @@
     private static final String TAG = "BackupAgent";
     private static final boolean DEBUG = true;
 
+    /** @hide */
+    public static final int TYPE_EOF = 0;
+
+    /**
+     * During a full restore, indicates that the file system object being restored
+     * is an ordinary file.
+     */
+    public static final int TYPE_FILE = 1;
+
+    /**
+     * During a full restore, indicates that the file system object being restored
+     * is a directory.
+     */
+    public static final int TYPE_DIRECTORY = 2;
+
+    /** @hide */
+    public static final int TYPE_SYMLINK = 3;
+
     public BackupAgent() {
         super(null);
     }
@@ -179,18 +206,240 @@
             throws IOException;
 
     /**
-     * @hide
+     * The default implementation backs up the entirety of the application's "owned"
+     * file system trees to the output.
      */
-    public void onRestoreFile(ParcelFileDescriptor data, long size,
-            int type, String domain, String path, long mode, long mtime)
-            throws IOException {
-        // empty stub implementation
+    public void onFullBackup(FullBackupDataOutput data) throws IOException {
+        ApplicationInfo appInfo = getApplicationInfo();
+
+        String rootDir = new File(appInfo.dataDir).getAbsolutePath();
+        String filesDir = getFilesDir().getAbsolutePath();
+        String databaseDir = getDatabasePath("foo").getParentFile().getAbsolutePath();
+        String sharedPrefsDir = getSharedPrefsFile("foo").getParentFile().getAbsolutePath();
+        String cacheDir = getCacheDir().getAbsolutePath();
+        String libDir = (appInfo.nativeLibraryDir != null)
+                ? new File(appInfo.nativeLibraryDir).getAbsolutePath()
+                : null;
+
+        // Filters, the scan queue, and the set of resulting entities
+        HashSet<String> filterSet = new HashSet<String>();
+        String packageName = getPackageName();
+
+        // Okay, start with the app's root tree, but exclude all of the canonical subdirs
+        if (libDir != null) {
+            filterSet.add(libDir);
+        }
+        filterSet.add(cacheDir);
+        filterSet.add(databaseDir);
+        filterSet.add(sharedPrefsDir);
+        filterSet.add(filesDir);
+        fullBackupFileTree(packageName, FullBackup.ROOT_TREE_TOKEN, rootDir, filterSet, data);
+
+        // Now do the same for the files dir, db dir, and shared prefs dir
+        filterSet.add(rootDir);
+        filterSet.remove(filesDir);
+        fullBackupFileTree(packageName, FullBackup.DATA_TREE_TOKEN, filesDir, filterSet, data);
+
+        filterSet.add(filesDir);
+        filterSet.remove(databaseDir);
+        fullBackupFileTree(packageName, FullBackup.DATABASE_TREE_TOKEN, databaseDir, filterSet, data);
+
+        filterSet.add(databaseDir);
+        filterSet.remove(sharedPrefsDir);
+        fullBackupFileTree(packageName, FullBackup.SHAREDPREFS_TREE_TOKEN, sharedPrefsDir, filterSet, data);
     }
 
     /**
-     * Package-private, used only for dispatching an extra step during full backup
+     * Write an entire file as part of a full-backup operation.  The file's contents
+     * will be delivered to the backup destination along with the metadata necessary
+     * to place it with the proper location and permissions on the device where the
+     * data is restored.
+     * @hide
+     *
+     * @param context The BackupAgent that is calling this method.  It is an error to
+     *     call it from something other than a running BackupAgent instance.
+     * @param file The file to be backed up.  The file must exist and be readable by
+     *     the caller.
+     * @param output The destination to which the backed-up file data will be sent.
      */
-    void onSaveApk(BackupDataOutput data) {
+    public final void fullBackupFile(File file, FullBackupDataOutput output) {
+        // Look up where all of our various well-defined dir trees live on this device
+        String mainDir;
+        String filesDir;
+        String dbDir;
+        String spDir;
+        String cacheDir;
+        String libDir;
+
+        ApplicationInfo appInfo = getApplicationInfo();
+
+        mainDir = new File(appInfo.dataDir).getAbsolutePath();
+        filesDir = getFilesDir().getAbsolutePath();
+        dbDir = getDatabasePath("foo").getParentFile().getAbsolutePath();
+        spDir = getSharedPrefsFile("foo").getParentFile().getAbsolutePath();
+        cacheDir = getCacheDir().getAbsolutePath();
+        libDir = (appInfo.nativeLibraryDir == null) ? null
+                : new File(appInfo.nativeLibraryDir).getAbsolutePath();
+
+        // Now figure out which well-defined tree the file is placed in, working from
+        // most to least specific.  We also specifically exclude the lib and cache dirs.
+        String filePath = file.getAbsolutePath();
+
+        if (filePath.startsWith(cacheDir) || filePath.startsWith(libDir)) {
+            Log.w(TAG, "lib and cache files are not backed up");
+            return;
+        }
+
+        final String domain;
+        String rootpath = null;
+        if (filePath.startsWith(dbDir)) {
+            domain = FullBackup.DATABASE_TREE_TOKEN;
+            rootpath = dbDir;
+        } else if (filePath.startsWith(spDir)) {
+            domain = FullBackup.SHAREDPREFS_TREE_TOKEN;
+            rootpath = spDir;
+        } else if (filePath.startsWith(filesDir)) {
+            domain = FullBackup.DATA_TREE_TOKEN;
+            rootpath = filesDir;
+        } else if (filePath.startsWith(mainDir)) {
+            domain = FullBackup.ROOT_TREE_TOKEN;
+            rootpath = mainDir;
+        } else {
+            Log.w(TAG, "File " + filePath + " is in an unsupported location; skipping");
+            return;
+        }
+
+        // And now that we know where it lives, semantically, back it up appropriately
+        Log.i(TAG, "backupFile() of " + filePath + " => domain=" + domain
+                + " rootpath=" + rootpath);
+        FullBackup.backupToTar(getPackageName(), domain, null, rootpath, filePath,
+                output.getData());
+    }
+
+    /**
+     * Scan the dir tree (if it actually exists) and process each entry we find.  If the
+     * 'excludes' parameter is non-null, it is consulted each time a new file system entity
+     * is visited to see whether that entity (and its subtree, if appropriate) should be
+     * omitted from the backup process.
+     *
+     * @hide
+     */
+    protected final void fullBackupFileTree(String packageName, String domain, String rootPath,
+            HashSet<String> excludes, FullBackupDataOutput output) {
+        File rootFile = new File(rootPath);
+        if (rootFile.exists()) {
+            LinkedList<File> scanQueue = new LinkedList<File>();
+            scanQueue.add(rootFile);
+
+            while (scanQueue.size() > 0) {
+                File file = scanQueue.remove(0);
+                String filePath = file.getAbsolutePath();
+
+                // prune this subtree?
+                if (excludes != null && excludes.contains(filePath)) {
+                    continue;
+                }
+
+                // If it's a directory, enqueue its contents for scanning.
+                try {
+                    StructStat stat = Libcore.os.lstat(filePath);
+                    if (OsConstants.S_ISLNK(stat.st_mode)) {
+                        if (DEBUG) Log.i(TAG, "Symlink (skipping)!: " + file);
+                        continue;
+                    } else if (OsConstants.S_ISDIR(stat.st_mode)) {
+                        File[] contents = file.listFiles();
+                        if (contents != null) {
+                            for (File entry : contents) {
+                                scanQueue.add(0, entry);
+                            }
+                        }
+                    }
+                } catch (ErrnoException e) {
+                    if (DEBUG) Log.w(TAG, "Error scanning file " + file + " : " + e);
+                    continue;
+                }
+
+                // Finally, back this file up before proceeding
+                FullBackup.backupToTar(packageName, domain, null, rootPath, filePath,
+                        output.getData());
+            }
+        }
+    }
+
+    /**
+     * Handle the data delivered via the given file descriptor during a full restore
+     * operation.  The agent is given the path to the file's original location as well
+     * as its size and metadata.
+     * <p>
+     * The file descriptor can only be read for {@code size} bytes; attempting to read
+     * more data has undefined behavior.
+     * <p>
+     * The default implementation creates the destination file/directory and populates it
+     * with the data from the file descriptor, then sets the file's access mode and
+     * modification time to match the restore arguments.
+     *
+     * @param data A read-only file descriptor from which the agent can read {@code size}
+     *     bytes of file data.
+     * @param size The number of bytes of file content to be restored to the given
+     *     destination.  If the file system object being restored is a directory, {@code size}
+     *     will be zero.
+     * @param destination The File on disk to be restored with the given data.
+     * @param type The kind of file system object being restored.  This will be either
+     *     {@link BackupAgent#TYPE_FILE} or {@link BackupAgent#TYPE_DIRECTORY}.
+     * @param mode The access mode to be assigned to the destination after its data is
+     *     written.  This is in the standard format used by {@code chmod()}.
+     * @param mtime The modification time of the file when it was backed up, suitable to
+     *     be assigned to the file after its data is written.
+     * @throws IOException
+     */
+    public void onRestoreFile(ParcelFileDescriptor data, long size,
+            File destination, int type, long mode, long mtime)
+            throws IOException {
+        FullBackup.restoreFile(data, size, type, mode, mtime, destination);
+    }
+
+    /**
+     * Only specialized platform agents should overload this entry point to support
+     * restores to crazy non-app locations.
+     * @hide
+     */
+    protected void onRestoreFile(ParcelFileDescriptor data, long size,
+            int type, String domain, String path, long mode, long mtime)
+            throws IOException {
+        String basePath = null;
+
+        if (DEBUG) Log.d(TAG, "onRestoreFile() size=" + size + " type=" + type
+                + " domain=" + domain + " relpath=" + path + " mode=" + mode
+                + " mtime=" + mtime);
+
+        // Parse out the semantic domains into the correct physical location
+        if (domain.equals(FullBackup.DATA_TREE_TOKEN)) {
+            basePath = getFilesDir().getAbsolutePath();
+        } else if (domain.equals(FullBackup.DATABASE_TREE_TOKEN)) {
+            basePath = getDatabasePath("foo").getParentFile().getAbsolutePath();
+        } else if (domain.equals(FullBackup.ROOT_TREE_TOKEN)) {
+            basePath = new File(getApplicationInfo().dataDir).getAbsolutePath();
+        } else if (domain.equals(FullBackup.SHAREDPREFS_TREE_TOKEN)) {
+            basePath = getSharedPrefsFile("foo").getParentFile().getAbsolutePath();
+        } else if (domain.equals(FullBackup.CACHE_TREE_TOKEN)) {
+            basePath = getCacheDir().getAbsolutePath();
+        } else {
+            // Not a supported location
+            Log.i(TAG, "Data restored from non-app domain " + domain + ", ignoring");
+        }
+
+        // Now that we've figured out where the data goes, send it on its way
+        if (basePath != null) {
+            File outFile = new File(basePath, path);
+            if (DEBUG) Log.i(TAG, "[" + domain + " : " + path + "] mapped to " + outFile.getPath());
+            onRestoreFile(data, size, outFile, type, mode, mtime);
+        } else {
+            // Not a supported output location?  We need to consume the data
+            // anyway, so just use the default "copy the data out" implementation
+            // with a null destination.
+            if (DEBUG) Log.i(TAG, "[ skipping data from unsupported domain " + domain + "]");
+            FullBackup.restoreFile(data, size, type, mode, mtime, null);
+        }
     }
 
     // ----- Core implementation -----
@@ -215,7 +464,6 @@
         public void doBackup(ParcelFileDescriptor oldState,
                 ParcelFileDescriptor data,
                 ParcelFileDescriptor newState,
-                boolean storeApk,
                 int token, IBackupManager callbackBinder) throws RemoteException {
             // Ensure that we're running with the app's normal permission level
             long ident = Binder.clearCallingIdentity();
@@ -223,10 +471,6 @@
             if (DEBUG) Log.v(TAG, "doBackup() invoked");
             BackupDataOutput output = new BackupDataOutput(data.getFileDescriptor());
 
-            if (storeApk) {
-                onSaveApk(output);
-            }
-
             try {
                 BackupAgent.this.onBackup(oldState, output, newState);
             } catch (IOException ex) {
@@ -273,6 +517,32 @@
         }
 
         @Override
+        public void doFullBackup(ParcelFileDescriptor data,
+                int token, IBackupManager callbackBinder) {
+            // Ensure that we're running with the app's normal permission level
+            long ident = Binder.clearCallingIdentity();
+
+            if (DEBUG) Log.v(TAG, "doFullBackup() invoked");
+
+            try {
+                BackupAgent.this.onFullBackup(new FullBackupDataOutput(data));
+            } catch (IOException ex) {
+                Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
+                throw new RuntimeException(ex);
+            } catch (RuntimeException ex) {
+                Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
+                throw ex;
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+                try {
+                    callbackBinder.opComplete(token);
+                } catch (RemoteException e) {
+                    // we'll time out anyway, so we're safe
+                }
+            }
+        }
+
+        @Override
         public void doRestoreFile(ParcelFileDescriptor data, long size,
                 int type, String domain, String path, long mode, long mtime,
                 int token, IBackupManager callbackBinder) throws RemoteException {
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index 3b70e19..d7f1c9f 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -16,6 +16,9 @@
 
 package android.app.backup;
 
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
@@ -29,7 +32,8 @@
 
 /**
  * Global constant definitions et cetera related to the full-backup-to-fd
- * binary format.
+ * binary format.  Nothing in this namespace is part of any API; it's all
+ * hidden details of the current implementation gathered into one location.
  *
  * @hide
  */
@@ -52,18 +56,41 @@
     public static final String FULL_RESTORE_INTENT_ACTION = "fullrest";
     public static final String CONF_TOKEN_INTENT_EXTRA = "conftoken";
 
-    public static final int TYPE_EOF = 0;
-    public static final int TYPE_FILE = 1;
-    public static final int TYPE_DIRECTORY = 2;
-    public static final int TYPE_SYMLINK = 3;
-
+    /**
+     * @hide
+     */
     static public native int backupToTar(String packageName, String domain,
             String linkdomain, String rootpath, String path, BackupDataOutput output);
 
-    static public void restoreToFile(ParcelFileDescriptor data,
-            long size, int type, long mode, long mtime, File outFile,
-            boolean doChmod) throws IOException {
-        if (type == FullBackup.TYPE_DIRECTORY) {
+    /**
+     * Copy data from a socket to the given File location on permanent storage.  The
+     * modification time and access mode of the resulting file will be set if desired.
+     * If the {@code type} parameter indicates that the result should be a directory,
+     * the socket parameter may be {@code null}; even if it is valid, no data will be
+     * read from it in this case.
+     * <p>
+     * If the {@code mode} argument is negative, then the resulting output file will not
+     * have its access mode or last modification time reset as part of this operation.
+     *
+     * @param data Socket supplying the data to be copied to the output file.  If the
+     *    output is a directory, this may be {@code null}.
+     * @param size Number of bytes of data to copy from the socket to the file.  At least
+     *    this much data must be available through the {@code data} parameter.
+     * @param type Must be either {@link BackupAgent#TYPE_FILE} for ordinary file data
+     *    or {@link BackupAgent#TYPE_DIRECTORY} for a directory.
+     * @param mode Unix-style file mode (as used by the chmod(2) syscall) to be set on
+     *    the output file or directory.  If this parameter is negative then neither
+     *    the mode nor the mtime parameters will be used.
+     * @param mtime A timestamp in the standard Unix epoch that will be imposed as the
+     *    last modification time of the output file.  if the {@code mode} parameter is
+     *    negative then this parameter will be ignored.
+     * @param outFile Location within the filesystem to place the data.  This must point
+     *    to a location that is writeable by the caller, prefereably using an absolute path.
+     * @throws IOException
+     */
+    static public void restoreFile(ParcelFileDescriptor data,
+            long size, int type, long mode, long mtime, File outFile) throws IOException {
+        if (type == BackupAgent.TYPE_DIRECTORY) {
             // Canonically a directory has no associated content, so we don't need to read
             // anything from the pipe in this case.  Just create the directory here and
             // drop down to the final metadata adjustment.
@@ -117,7 +144,7 @@
         }
 
         // Now twiddle the state to match the backup, assuming all went well
-        if (doChmod && outFile != null) {
+        if (mode >= 0 && outFile != null) {
             try {
                 Libcore.os.chmod(outFile.getPath(), (int)mode);
             } catch (ErrnoException e) {
diff --git a/core/java/android/app/backup/FullBackupAgent.java b/core/java/android/app/backup/FullBackupAgent.java
index df1c363..faea76a 100644
--- a/core/java/android/app/backup/FullBackupAgent.java
+++ b/core/java/android/app/backup/FullBackupAgent.java
@@ -16,210 +16,26 @@
 
 package android.app.backup;
 
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Environment;
 import android.os.ParcelFileDescriptor;
-import android.util.Log;
-
-import libcore.io.Libcore;
-import libcore.io.ErrnoException;
-import libcore.io.OsConstants;
-import libcore.io.StructStat;
-
-import java.io.File;
 import java.io.IOException;
-import java.util.HashSet;
-import java.util.LinkedList;
 
 /**
- * Backs up an application's entire /data/data/&lt;package&gt;/... file system.  This
- * class is used by the desktop full backup mechanism and is not intended for direct
- * use by applications.
+ * Simple concrete class that merely provides the default BackupAgent full backup/restore
+ * implementations for applications that do not supply their own.
  * 
  * {@hide}
  */
 
 public class FullBackupAgent extends BackupAgent {
-    // !!! TODO: turn off debugging
-    private static final String TAG = "FullBackupAgent";
-    private static final boolean DEBUG = true;
-
-    PackageManager mPm;
-
-    private String mMainDir;
-    private String mFilesDir;
-    private String mDatabaseDir;
-    private String mSharedPrefsDir;
-    private String mCacheDir;
-    private String mLibDir;
-
-    private File NULL_FILE;
-
-    @Override
-    public void onCreate() {
-        NULL_FILE = new File("/dev/null");
-
-        mPm = getPackageManager();
-        try {
-            ApplicationInfo appInfo = mPm.getApplicationInfo(getPackageName(), 0);
-            mMainDir = new File(appInfo.dataDir).getAbsolutePath();
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.e(TAG, "Unable to find package " + getPackageName());
-            throw new RuntimeException(e);
-        }
-
-        mFilesDir = getFilesDir().getAbsolutePath();
-        mDatabaseDir = getDatabasePath("foo").getParentFile().getAbsolutePath();
-        mSharedPrefsDir = getSharedPrefsFile("foo").getParentFile().getAbsolutePath();
-        mCacheDir = getCacheDir().getAbsolutePath();
-
-        ApplicationInfo app = getApplicationInfo();
-        mLibDir = (app.nativeLibraryDir != null)
-                ? new File(app.nativeLibraryDir).getAbsolutePath()
-                : null;
-    }
-
     @Override
     public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
             ParcelFileDescriptor newState) throws IOException {
-        // Filters, the scan queue, and the set of resulting entities
-        HashSet<String> filterSet = new HashSet<String>();
-        String packageName = getPackageName();
-
-        // Okay, start with the app's root tree, but exclude all of the canonical subdirs
-        if (mLibDir != null) {
-            filterSet.add(mLibDir);
-        }
-        filterSet.add(mCacheDir);
-        filterSet.add(mDatabaseDir);
-        filterSet.add(mSharedPrefsDir);
-        filterSet.add(mFilesDir);
-        processTree(packageName, FullBackup.ROOT_TREE_TOKEN, mMainDir, filterSet, data);
-
-        // Now do the same for the files dir, db dir, and shared prefs dir
-        filterSet.add(mMainDir);
-        filterSet.remove(mFilesDir);
-        processTree(packageName, FullBackup.DATA_TREE_TOKEN, mFilesDir, filterSet, data);
-
-        filterSet.add(mFilesDir);
-        filterSet.remove(mDatabaseDir);
-        processTree(packageName, FullBackup.DATABASE_TREE_TOKEN, mDatabaseDir, filterSet, data);
-
-        filterSet.add(mDatabaseDir);
-        filterSet.remove(mSharedPrefsDir);
-        processTree(packageName, FullBackup.SHAREDPREFS_TREE_TOKEN, mSharedPrefsDir, filterSet, data);
+        // Doesn't do incremental backup/restore
     }
 
-    // Scan the dir tree (if it actually exists) and process each entry we find.  If the
-    // 'excludes' parameter is non-null, it is consulted each time a new file system entity
-    // is visited to see whether that entity (and its subtree, if appropriate) should be
-    // omitted from the backup process.
-    protected void processTree(String packageName, String domain, String rootPath,
-            HashSet<String> excludes, BackupDataOutput data) {
-        File rootFile = new File(rootPath);
-        if (rootFile.exists()) {
-            LinkedList<File> scanQueue = new LinkedList<File>();
-            scanQueue.add(rootFile);
-
-            while (scanQueue.size() > 0) {
-                File file = scanQueue.remove(0);
-                String filePath = file.getAbsolutePath();
-
-                // prune this subtree?
-                if (excludes != null && excludes.contains(filePath)) {
-                    continue;
-                }
-
-                // If it's a directory, enqueue its contents for scanning.
-                try {
-                    StructStat stat = Libcore.os.lstat(filePath);
-                    if (OsConstants.S_ISLNK(stat.st_mode)) {
-                        if (DEBUG) Log.i(TAG, "Symlink (skipping)!: " + file);
-                        continue;
-                    } else if (OsConstants.S_ISDIR(stat.st_mode)) {
-                        File[] contents = file.listFiles();
-                        if (contents != null) {
-                            for (File entry : contents) {
-                                scanQueue.add(0, entry);
-                            }
-                        }
-                    }
-                } catch (ErrnoException e) {
-                    if (DEBUG) Log.w(TAG, "Error scanning file " + file + " : " + e);
-                    continue;
-                }
-
-                // Finally, back this file up before proceeding
-                FullBackup.backupToTar(packageName, domain, null, rootPath, filePath, data);
-            }
-        }
-    }
-
-    @Override
-    void onSaveApk(BackupDataOutput data) {
-        ApplicationInfo app = getApplicationInfo();
-        if (DEBUG) Log.i(TAG, "APK flags: system=" + ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0)
-                + " updated=" + ((app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)
-                + " locked=" + ((app.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) );
-        if (DEBUG) Log.i(TAG, "codepath: " + getPackageCodePath());
-
-        // Forward-locked apps, system-bundled .apks, etc are filtered out before we get here
-        final String pkgName = getPackageName();
-        final String apkDir = new File(getPackageCodePath()).getParent();
-        FullBackup.backupToTar(pkgName, FullBackup.APK_TREE_TOKEN, null,
-                apkDir, getPackageCodePath(), data);
-
-        // Save associated .obb content if it exists and we did save the apk
-        // check for .obb and save those too
-        final File obbDir = Environment.getExternalStorageAppObbDirectory(pkgName);
-        if (obbDir != null) {
-            if (DEBUG) Log.i(TAG, "obb dir: " + obbDir.getAbsolutePath());
-            File[] obbFiles = obbDir.listFiles();
-            if (obbFiles != null) {
-                final String obbDirName = obbDir.getAbsolutePath();
-                for (File obb : obbFiles) {
-                    FullBackup.backupToTar(pkgName, FullBackup.OBB_TREE_TOKEN, null,
-                            obbDirName, obb.getAbsolutePath(), data);
-                }
-            }
-        }
-    }
-
-    /**
-     * Dummy -- We're never used for restore of an incremental dataset
-     */
     @Override
     public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
             throws IOException {
-    }
-
-    /**
-     * Restore the described file from the given pipe.
-     */
-    @Override
-    public void onRestoreFile(ParcelFileDescriptor data, long size,
-            int type, String domain, String relpath, long mode, long mtime) 
-            throws IOException {
-        String basePath = null;
-        File outFile = null;
-
-        if (DEBUG) Log.d(TAG, "onRestoreFile() size=" + size + " type=" + type
-                + " domain=" + domain + " relpath=" + relpath + " mode=" + mode
-                + " mtime=" + mtime);
-
-        // Parse out the semantic domains into the correct physical location
-        if (domain.equals(FullBackup.DATA_TREE_TOKEN)) basePath = mFilesDir;
-        else if (domain.equals(FullBackup.DATABASE_TREE_TOKEN)) basePath = mDatabaseDir;
-        else if (domain.equals(FullBackup.ROOT_TREE_TOKEN)) basePath = mMainDir;
-        else if (domain.equals(FullBackup.SHAREDPREFS_TREE_TOKEN)) basePath = mSharedPrefsDir;
-
-        // Not a supported output location?  We need to consume the data
-        // anyway, so send it to /dev/null
-        outFile = (basePath != null) ? new File(basePath, relpath) : null;
-        if (DEBUG) Log.i(TAG, "[" + domain + " : " + relpath + "] mapped to " + outFile.getPath());
-
-        // Now that we've figured out where the data goes, send it on its way
-        FullBackup.restoreToFile(data, size, type, mode, mtime, outFile, true);
+        // Doesn't do incremental backup/restore
     }
 }
diff --git a/core/java/android/app/backup/FullBackupDataOutput.java b/core/java/android/app/backup/FullBackupDataOutput.java
new file mode 100644
index 0000000..99dab1f
--- /dev/null
+++ b/core/java/android/app/backup/FullBackupDataOutput.java
@@ -0,0 +1,21 @@
+package android.app.backup;
+
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Provides the interface through which a {@link BackupAgent} writes entire files
+ * to a full backup data set, via its {@link BackupAgent#onFullBackup(FullBackupDataOutput)}
+ * method.
+ */
+public class FullBackupDataOutput {
+    // Currently a name-scoping shim around BackupDataOutput
+    private BackupDataOutput mData;
+
+    /** @hide */
+    public FullBackupDataOutput(ParcelFileDescriptor fd) {
+        mData = new BackupDataOutput(fd.getFileDescriptor());
+    }
+
+    /** @hide */
+    public BackupDataOutput getData() { return mData; }
+}
diff --git a/core/java/android/app/backup/IRestoreSession.aidl b/core/java/android/app/backup/IRestoreSession.aidl
index 1dddbb0..14731ee 100644
--- a/core/java/android/app/backup/IRestoreSession.aidl
+++ b/core/java/android/app/backup/IRestoreSession.aidl
@@ -52,6 +52,25 @@
     int restoreAll(long token, IRestoreObserver observer);
 
     /**
+     * Restore select packages from the given set onto the device, replacing the
+     * current data of any app contained in the set with the data previously
+     * backed up.
+     *
+     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+     *
+     * @return Zero on success, nonzero on error. The observer will only receive
+     *   progress callbacks if this method returned zero.
+     * @param token The token from {@link getAvailableRestoreSets()} corresponding to
+     *   the restore set that should be used.
+     * @param observer If non-null, this binder points to an object that will receive
+     *   progress callbacks during the restore operation.
+     * @param packages The set of packages for which to attempt a restore.  Regardless of
+     *   the contents of the actual back-end dataset named by {@code token}, only
+     *   applications mentioned in this list will have their data restored.
+     */
+    int restoreSome(long token, IRestoreObserver observer, in String[] packages);
+
+    /**
      * Restore a single application from backup.  The data will be restored from the
      * current backup dataset if the given package has stored data there, or from
      * the dataset used during the last full device setup operation if the current
diff --git a/core/java/android/app/backup/RestoreSession.java b/core/java/android/app/backup/RestoreSession.java
index 24ddb99..7181c61 100644
--- a/core/java/android/app/backup/RestoreSession.java
+++ b/core/java/android/app/backup/RestoreSession.java
@@ -87,6 +87,40 @@
     }
 
     /**
+     * Restore select packages from the given set onto the device, replacing the
+     * current data of any app contained in the set with the data previously
+     * backed up.
+     *
+     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+     *
+     * @return Zero on success, nonzero on error. The observer will only receive
+     *   progress callbacks if this method returned zero.
+     * @param token The token from {@link getAvailableRestoreSets()} corresponding to
+     *   the restore set that should be used.
+     * @param observer If non-null, this binder points to an object that will receive
+     *   progress callbacks during the restore operation.
+     * @param packages The set of packages for which to attempt a restore.  Regardless of
+     *   the contents of the actual back-end dataset named by {@code token}, only
+     *   applications mentioned in this list will have their data restored.
+     *
+     * @hide
+     */
+    public int restoreSome(long token, RestoreObserver observer, String[] packages) {
+        int err = -1;
+        if (mObserver != null) {
+            Log.d(TAG, "restoreAll() called during active restore");
+            return -1;
+        }
+        mObserver = new RestoreObserverWrapper(mContext, observer);
+        try {
+            err = mBinder.restoreSome(token, mObserver, packages);
+        } catch (RemoteException e) {
+            Log.d(TAG, "Can't contact server to restore packages");
+        }
+        return err;
+    }
+
+    /**
      * Restore a single application from backup.  The data will be restored from the
      * current backup dataset if the given package has stored data there, or from
      * the dataset used during the last full device setup operation if the current
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 61d3707..96f3290 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -423,7 +423,24 @@
         return false;
     }
 
-     /**
+    /**
+     * Allow or disallow incoming connection
+     * @param device Sink
+     * @param value True / False
+     * @return Success or Failure of the binder call.
+     * @hide
+     */
+    public boolean allowIncomingConnect(BluetoothDevice device, boolean value) {
+        if (DBG) log("allowIncomingConnect(" + device + ":" + value + ")");
+        try {
+            return mService.allowIncomingConnect(device, value);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+            return false;
+        }
+    }
+
+    /**
      * Helper for converting a state to a string.
      *
      * For debug use only - strings are not internationalized.
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 254e2f8..d9525a3 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -276,6 +276,70 @@
     public static final String ACTION_PAIRING_CANCEL =
             "android.bluetooth.device.action.PAIRING_CANCEL";
 
+    /** @hide */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_CONNECTION_ACCESS_REQUEST =
+            "android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST";
+
+    /** @hide */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_CONNECTION_ACCESS_REPLY =
+            "android.bluetooth.device.action.CONNECTION_ACCESS_REPLY";
+
+    /** @hide */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_CONNECTION_ACCESS_CANCEL =
+            "android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL";
+
+    /**
+     * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intent.
+     * @hide
+     */
+    public static final String EXTRA_ACCESS_REQUEST_TYPE =
+        "android.bluetooth.device.extra.ACCESS_REQUEST_TYPE";
+
+    /**@hide*/
+    public static final int REQUEST_TYPE_PROFILE_CONNECTION = 1;
+
+    /**@hide*/
+    public static final int REQUEST_TYPE_PHONEBOOK_ACCESS = 2;
+
+    /**
+     * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents,
+     * Contains package name to return reply intent to.
+     * @hide
+     */
+    public static final String EXTRA_PACKAGE_NAME = "android.bluetooth.device.extra.PACKAGE_NAME";
+
+    /**
+     * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents,
+     * Contains class name to return reply intent to.
+     * @hide
+     */
+    public static final String EXTRA_CLASS_NAME = "android.bluetooth.device.extra.CLASS_NAME";
+
+    /**
+     * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intent.
+     * @hide
+     */
+    public static final String EXTRA_CONNECTION_ACCESS_RESULT =
+        "android.bluetooth.device.extra.CONNECTION_ACCESS_RESULT";
+
+    /**@hide*/
+    public static final int CONNECTION_ACCESS_YES = 1;
+
+    /**@hide*/
+    public static final int CONNECTION_ACCESS_NO = 2;
+
+    /**
+     * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intents,
+     * Contains boolean to indicate if the allowed response is once-for-all so that
+     * next request will be granted without asking user again.
+     * @hide
+     */
+    public static final String EXTRA_ALWAYS_ALLOWED =
+        "android.bluetooth.device.extra.ALWAYS_ALLOWED";
+
     /**
      * A bond attempt succeeded
      * @hide
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index 56f236d..ab3a426 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -22,9 +22,11 @@
 import android.content.IntentFilter;
 import android.os.Message;
 import android.bluetooth.BluetoothAdapter;
+import android.os.PowerManager;
 import android.server.BluetoothA2dpService;
 import android.server.BluetoothService;
 import android.util.Log;
+import android.util.Pair;
 
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
@@ -81,8 +83,18 @@
     public static final int AUTO_CONNECT_PROFILES = 101;
     public static final int TRANSITION_TO_STABLE = 102;
     public static final int CONNECT_OTHER_PROFILES = 103;
+    private static final int CONNECTION_ACCESS_REQUEST_REPLY = 104;
+    private static final int CONNECTION_ACCESS_REQUEST_EXPIRY = 105;
 
     private static final int CONNECT_OTHER_PROFILES_DELAY = 4000; // 4 secs
+    private static final int CONNECTION_ACCESS_REQUEST_EXPIRY_TIMEOUT = 7000; // 7 secs
+    private static final int CONNECTION_ACCESS_UNDEFINED = -1;
+    private static final long INIT_INCOMING_REJECT_TIMER = 1000; // 1 sec
+    private static final long MAX_INCOMING_REJECT_TIMER = 3600 * 1000 * 4; // 4 hours
+
+    private static final String ACCESS_AUTHORITY_PACKAGE = "com.android.settings";
+    private static final String ACCESS_AUTHORITY_CLASS =
+        "com.android.settings.bluetooth.BluetoothPermissionRequest";
 
     private BondedDevice mBondedDevice = new BondedDevice();
     private OutgoingHandsfree mOutgoingHandsfree = new OutgoingHandsfree();
@@ -98,10 +110,16 @@
     private BluetoothHeadset  mHeadsetService;
     private BluetoothPbap     mPbapService;
     private boolean mPbapServiceConnected;
+    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
 
     private BluetoothDevice mDevice;
     private int mHeadsetState = BluetoothProfile.STATE_DISCONNECTED;
     private int mA2dpState = BluetoothProfile.STATE_DISCONNECTED;
+    private long mIncomingRejectTimer;
+    private boolean mConnectionAccessReplyReceived = false;
+    private Pair<Integer, String> mIncomingConnections;
+    private PowerManager.WakeLock mWakeLock;
+    private PowerManager mPowerManager;
 
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -113,6 +131,10 @@
             if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) {
                 int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
                 int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
+                // We trust this device now
+                if (newState == BluetoothHeadset.STATE_CONNECTED) {
+                    setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
+                }
                 mA2dpState = newState;
                 if (oldState == BluetoothA2dp.STATE_CONNECTED &&
                     newState == BluetoothA2dp.STATE_DISCONNECTED) {
@@ -125,7 +147,10 @@
             } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
                 int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
                 int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
-
+                // We trust this device now
+                if (newState == BluetoothHeadset.STATE_CONNECTED) {
+                    setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
+                }
                 mHeadsetState = newState;
                 if (oldState == BluetoothHeadset.STATE_CONNECTED &&
                     newState == BluetoothHeadset.STATE_DISCONNECTED) {
@@ -139,7 +164,10 @@
                 int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
                 int oldState =
                     intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
-
+                // We trust this device now
+                if (newState == BluetoothHeadset.STATE_CONNECTED) {
+                    setTrust(BluetoothDevice.CONNECTION_ACCESS_YES);
+                }
                 if (oldState == BluetoothProfile.STATE_CONNECTED &&
                     newState == BluetoothProfile.STATE_DISCONNECTED) {
                     sendMessage(DISCONNECT_HID_INCOMING);
@@ -152,8 +180,15 @@
                 // This is technically not needed, but we can get stuck sometimes.
                 // For example, if incoming A2DP fails, we are not informed by Bluez
                 sendMessage(TRANSITION_TO_STABLE);
+            } else if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY)) {
+                mWakeLock.release();
+                int val = intent.getIntExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT,
+                                             BluetoothDevice.CONNECTION_ACCESS_NO);
+                Message msg = obtainMessage(CONNECTION_ACCESS_REQUEST_REPLY);
+                msg.arg1 = val;
+                sendMessage(msg);
             }
-      }
+        }
     };
 
     private boolean isPhoneDocked(BluetoothDevice autoConnectDevice) {
@@ -195,6 +230,7 @@
         filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
         filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
         filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
+        filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
 
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
@@ -203,6 +239,14 @@
                                 BluetoothProfile.HEADSET);
         // TODO(): Convert PBAP to the new Profile APIs.
         PbapServiceListener p = new PbapServiceListener();
+
+        mIncomingConnections = mService.getIncomingState(address);
+        mIncomingRejectTimer = readTimerValue();
+        mPowerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK |
+                                              PowerManager.ACQUIRE_CAUSES_WAKEUP |
+                                              PowerManager.ON_AFTER_RELEASE, TAG);
+        mWakeLock.setReferenceCounted(false);
     }
 
     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
@@ -497,6 +541,24 @@
                     // Ignore
                     Log.e(TAG, "Error: Incoming connection with a pending incoming connection");
                     break;
+                case CONNECTION_ACCESS_REQUEST_REPLY:
+                    int val = message.arg1;
+                    mConnectionAccessReplyReceived = true;
+                    boolean value = false;
+                    if (val == BluetoothDevice.CONNECTION_ACCESS_YES) {
+                        value = true;
+                    }
+                    setTrust(val);
+
+                    handleIncomingConnection(CONNECT_HFP_INCOMING, value);
+                    break;
+                case CONNECTION_ACCESS_REQUEST_EXPIRY:
+                    if (!mConnectionAccessReplyReceived) {
+                        handleIncomingConnection(CONNECT_HFP_INCOMING, false);
+                        sendConnectionAccessRemovalIntent();
+                        sendMessage(TRANSITION_TO_STABLE);
+                    }
+                    break;
                 case CONNECT_A2DP_INCOMING:
                     // Serialize the commands.
                     deferMessage(message);
@@ -690,6 +752,25 @@
                 case CONNECT_A2DP_INCOMING:
                     // ignore
                     break;
+                case CONNECTION_ACCESS_REQUEST_REPLY:
+                    int val = message.arg1;
+                    mConnectionAccessReplyReceived = true;
+                    boolean value = false;
+                    if (val == BluetoothDevice.CONNECTION_ACCESS_YES) {
+                        value = true;
+                    }
+                    setTrust(val);
+                    handleIncomingConnection(CONNECT_A2DP_INCOMING, value);
+                    break;
+                case CONNECTION_ACCESS_REQUEST_EXPIRY:
+                    // The check protects the race condition between REQUEST_REPLY
+                    // and the timer expiry.
+                    if (!mConnectionAccessReplyReceived) {
+                        handleIncomingConnection(CONNECT_A2DP_INCOMING, false);
+                        sendConnectionAccessRemovalIntent();
+                        sendMessage(TRANSITION_TO_STABLE);
+                    }
+                    break;
                 case CONNECT_A2DP_OUTGOING:
                     // Defer message and retry
                     deferMessage(message);
@@ -847,6 +928,20 @@
               case DISCONNECT_HID_OUTGOING:
                   deferMessage(message);
                   break;
+              case CONNECTION_ACCESS_REQUEST_REPLY:
+                  mConnectionAccessReplyReceived = true;
+                  int val = message.arg1;
+                  setTrust(val);
+                  handleIncomingConnection(CONNECT_HID_INCOMING,
+                      val == BluetoothDevice.CONNECTION_ACCESS_YES);
+                  break;
+              case CONNECTION_ACCESS_REQUEST_EXPIRY:
+                  if (!mConnectionAccessReplyReceived) {
+                      handleIncomingConnection(CONNECT_HID_INCOMING, false);
+                      sendConnectionAccessRemovalIntent();
+                      sendMessage(TRANSITION_TO_STABLE);
+                  }
+                  break;
               case DISCONNECT_HFP_INCOMING:
                   // Shouldn't happen but if does, we can handle it.
                   // Depends if the headset can handle it.
@@ -891,8 +986,150 @@
         deferMessage(msg);
     }
 
+    private void updateIncomingAllowedTimer() {
+        // Not doing a perfect exponential backoff because
+        // we want two different rates. For all practical
+        // purposes, this is good enough.
+        if (mIncomingRejectTimer == 0) mIncomingRejectTimer = INIT_INCOMING_REJECT_TIMER;
+
+        mIncomingRejectTimer *= 5;
+        if (mIncomingRejectTimer > MAX_INCOMING_REJECT_TIMER) {
+            mIncomingRejectTimer = MAX_INCOMING_REJECT_TIMER;
+        }
+        writeTimerValue(mIncomingRejectTimer);
+    }
+
+    private boolean handleIncomingConnection(int command, boolean accept) {
+        boolean ret = false;
+        Log.i(TAG, "handleIncomingConnection:" + command + ":" + accept);
+        switch (command) {
+            case CONNECT_HFP_INCOMING:
+                if (!accept) {
+                    ret = mHeadsetService.rejectIncomingConnect(mDevice);
+                    sendMessage(TRANSITION_TO_STABLE);
+                    updateIncomingAllowedTimer();
+                } else if (mHeadsetState == BluetoothHeadset.STATE_CONNECTING) {
+                    writeTimerValue(0);
+                    ret =  mHeadsetService.acceptIncomingConnect(mDevice);
+                } else if (mHeadsetState == BluetoothHeadset.STATE_DISCONNECTED) {
+                    writeTimerValue(0);
+                    handleConnectionOfOtherProfiles(command);
+                    ret = mHeadsetService.createIncomingConnect(mDevice);
+                }
+                break;
+            case CONNECT_A2DP_INCOMING:
+                if (!accept) {
+                    ret = mA2dpService.allowIncomingConnect(mDevice, false);
+                    sendMessage(TRANSITION_TO_STABLE);
+                    updateIncomingAllowedTimer();
+                } else {
+                    writeTimerValue(0);
+                    ret = mA2dpService.allowIncomingConnect(mDevice, true);
+                    handleConnectionOfOtherProfiles(command);
+                }
+                break;
+            case CONNECT_HID_INCOMING:
+                if (!accept) {
+                    ret = mService.allowIncomingHidConnect(mDevice, false);
+                    sendMessage(TRANSITION_TO_STABLE);
+                    updateIncomingAllowedTimer();
+                } else {
+                    writeTimerValue(0);
+                    ret = mService.allowIncomingHidConnect(mDevice, true);
+                }
+                break;
+            default:
+                Log.e(TAG, "Waiting for incoming connection but state changed to:" + command);
+                break;
+       }
+       return ret;
+    }
+
+    private void sendConnectionAccessIntent() {
+        mConnectionAccessReplyReceived = false;
+
+        if (!mPowerManager.isScreenOn()) mWakeLock.acquire();
+
+        Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST);
+        intent.setClassName(ACCESS_AUTHORITY_PACKAGE, ACCESS_AUTHORITY_CLASS);
+        intent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
+                        BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION);
+        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
+        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
+    }
+
+    private void sendConnectionAccessRemovalIntent() {
+        mWakeLock.release();
+        Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_CANCEL);
+        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
+        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
+    }
+
+    private int getTrust() {
+        String address = mDevice.getAddress();
+        if (mIncomingConnections != null) return mIncomingConnections.first;
+        return CONNECTION_ACCESS_UNDEFINED;
+    }
+
+
+    private String getStringValue(long value) {
+        StringBuilder sbr = new StringBuilder();
+        sbr.append(Long.toString(System.currentTimeMillis()));
+        sbr.append("-");
+        sbr.append(Long.toString(value));
+        return sbr.toString();
+    }
+
+    private void setTrust(int value) {
+        String second;
+        if (mIncomingConnections == null) {
+            second = getStringValue(INIT_INCOMING_REJECT_TIMER);
+        } else {
+            second = mIncomingConnections.second;
+        }
+
+        mIncomingConnections = new Pair(value, second);
+        mService.writeIncomingConnectionState(mDevice.getAddress(), mIncomingConnections);
+    }
+
+    private void writeTimerValue(long value) {
+        Integer first;
+        if (mIncomingConnections == null) {
+            first = CONNECTION_ACCESS_UNDEFINED;
+        } else {
+            first = mIncomingConnections.first;
+        }
+        mIncomingConnections = new Pair(first, getStringValue(value));
+        mService.writeIncomingConnectionState(mDevice.getAddress(), mIncomingConnections);
+    }
+
+    private long readTimerValue() {
+        if (mIncomingConnections == null)
+            return 0;
+        String value = mIncomingConnections.second;
+        String[] splits = value.split("-");
+        if (splits != null && splits.length == 2) {
+            return Long.parseLong(splits[1]);
+        }
+        return 0;
+    }
+
+    private boolean readIncomingAllowedValue() {
+        if (readTimerValue() == 0) return true;
+        String value = mIncomingConnections.second;
+        String[] splits = value.split("-");
+        if (splits != null && splits.length == 2) {
+            long val1 = Long.parseLong(splits[0]);
+            long val2 = Long.parseLong(splits[1]);
+            if (val1 + val2 <= System.currentTimeMillis()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     synchronized boolean processCommand(int command) {
-        Log.i(TAG, "Processing command:" + command);
+        log("Processing command:" + command);
         switch(command) {
             case  CONNECT_HFP_OUTGOING:
                 if (mHeadsetService == null) {
@@ -904,11 +1141,9 @@
             case CONNECT_HFP_INCOMING:
                 if (mHeadsetService == null) {
                     deferProfileServiceMessage(command);
-                } else if (mHeadsetState == BluetoothHeadset.STATE_CONNECTING) {
-                    return mHeadsetService.acceptIncomingConnect(mDevice);
-                } else if (mHeadsetState == BluetoothHeadset.STATE_DISCONNECTED) {
-                    handleConnectionOfOtherProfiles(command);
-                    return mHeadsetService.createIncomingConnect(mDevice);
+                } else {
+                    processIncomingConnectCommand(command);
+                    return true;
                 }
                 break;
             case CONNECT_A2DP_OUTGOING:
@@ -917,12 +1152,12 @@
                 }
                 break;
             case CONNECT_A2DP_INCOMING:
-                handleConnectionOfOtherProfiles(command);
-                // ignore, Bluez takes care
+                processIncomingConnectCommand(command);
                 return true;
             case CONNECT_HID_OUTGOING:
                 return mService.connectInputDeviceInternal(mDevice);
             case CONNECT_HID_INCOMING:
+                processIncomingConnectCommand(command);
                 return true;
             case DISCONNECT_HFP_OUTGOING:
                 if (mHeadsetService == null) {
@@ -972,6 +1207,8 @@
                 }
                 break;
             case UNPAIR:
+                writeTimerValue(INIT_INCOMING_REJECT_TIMER);
+                setTrust(CONNECTION_ACCESS_UNDEFINED);
                 return mService.removeBondInternal(mDevice.getAddress());
             default:
                 Log.e(TAG, "Error: Unknown Command");
@@ -979,6 +1216,22 @@
         return false;
     }
 
+    private void processIncomingConnectCommand(int command) {
+        // Check if device is already trusted
+        int access = getTrust();
+        if (access == BluetoothDevice.CONNECTION_ACCESS_YES) {
+            handleIncomingConnection(command, true);
+        } else if (access == BluetoothDevice.CONNECTION_ACCESS_NO &&
+                   !readIncomingAllowedValue()) {
+            handleIncomingConnection(command, false);
+        } else {
+            sendConnectionAccessIntent();
+            Message msg = obtainMessage(CONNECTION_ACCESS_REQUEST_EXPIRY);
+            sendMessageDelayed(msg,
+                               CONNECTION_ACCESS_REQUEST_EXPIRY_TIMEOUT);
+        }
+    }
+
     private void handleConnectionOfOtherProfiles(int command) {
         // The white paper recommendations mentions that when there is a
         // link loss, it is the responsibility of the remote device to connect.
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 23724f2..3284361 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -618,6 +618,23 @@
     }
 
     /**
+     * Reject the incoming connection.
+     * @hide
+     */
+    public boolean rejectIncomingConnect(BluetoothDevice device) {
+        if (DBG) log("rejectIncomingConnect");
+        if (mService != null) {
+            try {
+                return mService.rejectIncomingConnect(device);
+            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+        return false;
+    }
+
+    /**
      * Connect to a Bluetooth Headset.
      * Note: This is an internal function and shouldn't be exposed
      *
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index 282b70a..f6757d9 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -308,6 +308,28 @@
         return BluetoothProfile.PRIORITY_OFF;
     }
 
+    /**
+     * Allow or disallow incoming connection
+     * @param device Input device
+     * @param allow true / false
+     * @return Success or Failure of the operation
+     * @hide
+     */
+    public boolean allowIncomingConnect(BluetoothDevice device, boolean allow) {
+        if (DBG) log("allowIncomingConnect(" + device + ", " + allow + ")");
+
+        if (mService == null || !isEnabled() || !isValidDevice(device)) {
+            return false;
+        }
+        try {
+            mService.allowIncomingHidConnect(device, allow);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return false;
+        }
+        return true;
+    }
+
     private boolean isEnabled() {
        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
        return false;
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 83e59e2..acce182 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -62,6 +62,7 @@
     /*package*/ final BluetoothSocket mSocket;
     private Handler mHandler;
     private int mMessage;
+    private final int mChannel;
 
     /**
      * Construct a socket for incoming connections.
@@ -74,6 +75,7 @@
      */
     /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port)
             throws IOException {
+        mChannel = port;
         mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, null);
     }
 
@@ -125,4 +127,12 @@
         mHandler = handler;
         mMessage = message;
     }
+
+    /**
+     * Returns the channel on which this socket is bound.
+     * @hide
+     */
+    public int getChannel() {
+        return mChannel;
+    }
 }
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 496bc85..183772d 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -92,6 +92,7 @@
     int getInputDeviceConnectionState(in BluetoothDevice device);
     boolean setInputDevicePriority(in BluetoothDevice device, int priority);
     int getInputDevicePriority(in BluetoothDevice device);
+    boolean allowIncomingHidConnect(in BluetoothDevice device, boolean value);
 
     boolean isTetheringOn();
     void setBluetoothTethering(boolean value);
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index b4fc366..444dd1e 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -39,4 +39,6 @@
     boolean resumeSink(in BluetoothDevice device);
     boolean connectSinkInternal(in BluetoothDevice device);
     boolean disconnectSinkInternal(in BluetoothDevice device);
+    boolean allowIncomingConnect(in BluetoothDevice device, boolean value);
+
 }
diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl
index 273cda7..ec00527 100644
--- a/core/java/android/bluetooth/IBluetoothHeadset.aidl
+++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl
@@ -42,6 +42,7 @@
     // Internal functions, not be made public
     boolean createIncomingConnect(in BluetoothDevice device);
     boolean acceptIncomingConnect(in BluetoothDevice device);
+    boolean rejectIncomingConnect(in BluetoothDevice device);
     boolean cancelConnectThread();
     boolean connectHeadsetInternal(in BluetoothDevice device);
     boolean disconnectHeadsetInternal(in BluetoothDevice device);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index aecec66..fed6d81 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1029,6 +1029,12 @@
      *
      * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
      *
+     * <p>As of {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, receivers
+     * registered with this method will correctly respect the
+     * {@link Intent#setPackage(String)} specified for an Intent being broadcast.
+     * Prior to that, it would be ignored and delivered to all matching registered
+     * receivers.  Be careful if using this for security.</p>
+     *
      * <p class="note">Note: this method <em>cannot be called from a
      * {@link BroadcastReceiver} component;</em> that is, from a BroadcastReceiver
      * that is declared in an application's manifest.  It is okay, however, to call
@@ -1059,6 +1065,12 @@
      *
      * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
      *
+     * <p>As of {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, receivers
+     * registered with this method will correctly respect the
+     * {@link Intent#setPackage(String)} specified for an Intent being broadcast.
+     * Prior to that, it would be ignored and delivered to all matching registered
+     * receivers.  Be careful if using this for security.</p>
+     *
      * @param receiver The BroadcastReceiver to handle the broadcast.
      * @param filter Selects the Intent broadcasts to be received.
      * @param broadcastPermission String naming a permissions that a
diff --git a/core/java/android/content/IIntentSender.aidl b/core/java/android/content/IIntentSender.aidl
index b7da472..7dbd6f2 100644
--- a/core/java/android/content/IIntentSender.aidl
+++ b/core/java/android/content/IIntentSender.aidl
@@ -22,5 +22,5 @@
 /** @hide */
 interface IIntentSender {
     int send(int code, in Intent intent, String resolvedType,
-            IIntentReceiver finishedReceiver);
+            IIntentReceiver finishedReceiver, String requiredPermission);
 }
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 007a715..4db4bdc 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -154,14 +154,47 @@
      */
     public void sendIntent(Context context, int code, Intent intent,
             OnFinished onFinished, Handler handler) throws SendIntentException {
+        sendIntent(context, code, intent, onFinished, handler, null);
+    }
+
+    /**
+     * Perform the operation associated with this IntentSender, allowing the
+     * caller to specify information about the Intent to use and be notified
+     * when the send has completed.
+     *
+     * @param context The Context of the caller.  This may be null if
+     * <var>intent</var> is also null.
+     * @param code Result code to supply back to the IntentSender's target.
+     * @param intent Additional Intent data.  See {@link Intent#fillIn
+     * Intent.fillIn()} for information on how this is applied to the
+     * original Intent.  Use null to not modify the original Intent.
+     * @param onFinished The object to call back on when the send has
+     * completed, or null for no callback.
+     * @param handler Handler identifying the thread on which the callback
+     * should happen.  If null, the callback will happen from the thread
+     * pool of the process.
+     * @param requiredPermission Name of permission that a recipient of the PendingIntent
+     * is required to hold.  This is only valid for broadcast intents, and
+     * corresponds to the permission argument in
+     * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
+     * If null, no permission is required.
+     *
+     *
+     * @throws SendIntentException Throws CanceledIntentException if the IntentSender
+     * is no longer allowing more intents to be sent through it.
+     */
+    public void sendIntent(Context context, int code, Intent intent,
+            OnFinished onFinished, Handler handler, String requiredPermission)
+            throws SendIntentException {
         try {
             String resolvedType = intent != null ?
                     intent.resolveTypeIfNeeded(context.getContentResolver())
                     : null;
             int res = mTarget.send(code, intent, resolvedType,
                     onFinished != null
-                    ? new FinishedDispatcher(this, onFinished, handler)
-                    : null);
+                            ? new FinishedDispatcher(this, onFinished, handler)
+                            : null,
+                    requiredPermission);
             if (res < 0) {
                 throw new SendIntentException();
             }
diff --git a/core/java/android/content/XmlDocumentProvider.java b/core/java/android/content/XmlDocumentProvider.java
deleted file mode 100644
index 76539c7..0000000
--- a/core/java/android/content/XmlDocumentProvider.java
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (C) 2010 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.content;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.client.methods.HttpGet;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import android.content.ContentResolver.OpenResourceIdResult;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.net.Uri;
-import android.net.http.AndroidHttpClient;
-import android.util.Log;
-import android.widget.CursorAdapter;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.BitSet;
-import java.util.Stack;
-import java.util.regex.Pattern;
-
-/**
- * @hide -- not yet ready to support, should be provided just as a static lib.
- * 
- * A read-only content provider which extracts data out of an XML document.
- *
- * <p>A XPath-like selection pattern is used to select some nodes in the XML document. Each such
- * node will create a row in the {@link Cursor} result.</p>
- *
- * Each row is then populated with columns that are also defined as XPath-like projections. These
- * projections fetch attributes values or text in the matching row node or its children.
- *
- * <p>To add this provider in your application, you should add its declaration to your application
- * manifest:
- * <pre class="prettyprint">
- * &lt;provider android:name="android.content.XmlDocumentProvider" android:authorities="xmldocument" /&gt;
- * </pre>
- * </p>
- *
- * <h2>Node selection syntax</h2>
- * The node selection syntax is made of the concatenation of an arbitrary number (at least one) of
- * <code>/node_name</code> node selection patterns.
- *
- * <p>The <code>/root/child1/child2</code> pattern will for instance match all nodes named
- * <code>child2</code> which are children of a node named <code>child1</code> which are themselves
- * children of a root node named <code>root</code>.</p>
- *
- * Any <code>/</code> separator in the previous expression can be replaced by a <code>//</code>
- * separator instead, which indicated a <i>descendant</i> instead of a child.
- *
- * <p>The <code>//node1//node2</code> pattern will for instance match all nodes named
- * <code>node2</code> which are descendant of a node named <code>node1</code> located anywhere in
- * the document hierarchy.</p>
- *
- * Node names can contain namespaces in the form <code>namespace:node</code>.
- *
- * <h2>Projection syntax</h2>
- * For every selected node, the projection will then extract actual data from this node and its
- * descendant.
- *
- * <p>Use a syntax similar to the selection syntax described above to select the text associated
- * with a child of the selected node. The implicit root of this projection pattern is the selected
- * node. <code>/</code> will hence refer to the text of the selected node, while
- * <code>/child1</code> will fetch the text of its child named <code>child1</code> and
- * <code>//child1</code> will match any <i>descendant</i> named <code>child1</code>. If several
- * nodes match the projection pattern, their texts are appended as a result.</p>
- *
- * A projection can also fetch any node attribute by appending a <code>@attribute_name</code>
- * pattern to the previously described syntax. <code>//child1@price</code> will for instance match
- * the attribute <code>price</code> of any <code>child1</code> descendant.
- *
- * <p>If a projection does not match any node/attribute, its associated value will be an empty
- * string.</p>
- *
- * <h2>Example</h2>
- * Using the following XML document:
- * <pre class="prettyprint">
- * &lt;library&gt;
- *   &lt;book id="EH94"&gt;
- *     &lt;title&gt;The Old Man and the Sea&lt;/title&gt;
- *     &lt;author&gt;Ernest Hemingway&lt;/author&gt;
- *   &lt;/book&gt;
- *   &lt;book id="XX10"&gt;
- *     &lt;title&gt;The Arabian Nights: Tales of 1,001 Nights&lt;/title&gt;
- *   &lt;/book&gt;
- *   &lt;no-id&gt;
- *     &lt;book&gt;
- *       &lt;title&gt;Animal Farm&lt;/title&gt;
- *       &lt;author&gt;George Orwell&lt;/author&gt;
- *     &lt;/book&gt;
- *   &lt;/no-id&gt;
- * &lt;/library&gt;
- * </pre>
- * A selection pattern of <code>/library//book</code> will match the three book entries (while
- * <code>/library/book</code> will only match the first two ones).
- *
- * <p>Defining the projections as <code>/title</code>, <code>/author</code> and <code>@id</code>
- * will retrieve the associated data. Note that the author of the second book as well as the id of
- * the third are empty strings.
- */
-public class XmlDocumentProvider extends ContentProvider {
-    /*
-     * Ideas for improvement:
-     * - Expand XPath-like syntax to allow for [nb] child number selector
-     * - Address the starting . bug in AbstractCursor which prevents a true XPath syntax.
-     * - Provide an alternative to concatenation when several node match (list-like).
-     * - Support namespaces in attribute names.
-     * - Incremental Cursor creation, pagination
-     */
-    private static final String LOG_TAG = "XmlDocumentProvider";
-    private AndroidHttpClient mHttpClient;
-
-    @Override
-    public boolean onCreate() {
-        return true;
-    }
-
-    /**
-     * Query data from the XML document referenced in the URI.
-     *
-     * <p>The XML document can be a local resource or a file that will be downloaded from the
-     * Internet. In the latter case, your application needs to request the INTERNET permission in
-     * its manifest.</p>
-     *
-     * The URI will be of the form <code>content://xmldocument/?resource=R.xml.myFile</code> for a
-     * local resource. <code>xmldocument</code> should match the authority declared for this
-     * provider in your manifest. Internet documents are referenced using
-     * <code>content://xmldocument/?url=</code> followed by an encoded version of the URL of your
-     * document (see {@link Uri#encode(String)}).
-     *
-     * <p>The number of columns of the resulting Cursor is equal to the size of the projection
-     * array plus one, named <code>_id</code> which will contain a unique row id (allowing the
-     * Cursor to be used with a {@link CursorAdapter}). The other columns' names are the projection
-     * patterns.</p>
-     *
-     * @param uri The URI of your local resource or Internet document.
-     * @param projection A set of patterns that will be used to extract data from each selected
-     * node. See class documentation for pattern syntax.
-     * @param selection A selection pattern which will select the nodes that will create the
-     * Cursor's rows. See class documentation for pattern syntax.
-     * @param selectionArgs This parameter is ignored.
-     * @param sortOrder The row order in the resulting cursor is determined from the node order in
-     * the XML document. This parameter is ignored.
-     * @return A Cursor or null in case of error.
-     */
-    @Override
-    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
-            String sortOrder) {
-
-        XmlPullParser parser = null;
-        mHttpClient = null;
-
-        final String url = uri.getQueryParameter("url");
-        if (url != null) {
-            parser = getUriXmlPullParser(url);
-        } else {
-            final String resource = uri.getQueryParameter("resource");
-            if (resource != null) {
-                Uri resourceUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
-                        getContext().getPackageName() + "/" + resource);
-                parser = getResourceXmlPullParser(resourceUri);
-            }
-        }
-
-        if (parser != null) {
-            XMLCursor xmlCursor = new XMLCursor(selection, projection);
-            try {
-                xmlCursor.parseWith(parser);
-                return xmlCursor;
-            } catch (IOException e) {
-                Log.w(LOG_TAG, "I/O error while parsing XML " + uri, e);
-            } catch (XmlPullParserException e) {
-                Log.w(LOG_TAG, "Error while parsing XML " + uri, e);
-            } finally {
-                if (mHttpClient != null) {
-                    mHttpClient.close();
-                }
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Creates an XmlPullParser for the provided URL. Can be overloaded to provide your own parser.
-     * @param url The URL of the XML document that is to be parsed.
-     * @return An XmlPullParser on this document.
-     */
-    protected XmlPullParser getUriXmlPullParser(String url) {
-        XmlPullParser parser = null;
-        try {
-            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
-            factory.setNamespaceAware(true);
-            parser = factory.newPullParser();
-        } catch (XmlPullParserException e) {
-            Log.e(LOG_TAG, "Unable to create XmlPullParser", e);
-            return null;
-        }
-
-        InputStream inputStream = null;
-        try {
-            final HttpGet get = new HttpGet(url);
-            mHttpClient = AndroidHttpClient.newInstance("Android");
-            HttpResponse response = mHttpClient.execute(get);
-            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
-                final HttpEntity entity = response.getEntity();
-                if (entity != null) {
-                    inputStream = entity.getContent();
-                }
-            }
-        } catch (IOException e) {
-            Log.w(LOG_TAG, "Error while retrieving XML file " + url, e);
-            return null;
-        }
-
-        try {
-            parser.setInput(inputStream, null);
-        } catch (XmlPullParserException e) {
-            Log.w(LOG_TAG, "Error while reading XML file from " + url, e);
-            return null;
-        }
-
-        return parser;
-    }
-
-    /**
-     * Creates an XmlPullParser for the provided local resource. Can be overloaded to provide your
-     * own parser.
-     * @param resourceUri A fully qualified resource name referencing a local XML resource.
-     * @return An XmlPullParser on this resource.
-     */
-    protected XmlPullParser getResourceXmlPullParser(Uri resourceUri) {
-        OpenResourceIdResult resourceId;
-        try {
-            resourceId = getContext().getContentResolver().getResourceId(resourceUri);
-            return resourceId.r.getXml(resourceId.id);
-        } catch (FileNotFoundException e) {
-            Log.w(LOG_TAG, "XML resource not found: " + resourceUri.toString(), e);
-            return null;
-        }
-    }
-
-    /**
-     * Returns "vnd.android.cursor.dir/xmldoc".
-     */
-    @Override
-    public String getType(Uri uri) {
-        return "vnd.android.cursor.dir/xmldoc";
-    }
-
-    /**
-     * This ContentProvider is read-only. This method throws an UnsupportedOperationException.
-     **/
-    @Override
-    public Uri insert(Uri uri, ContentValues values) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * This ContentProvider is read-only. This method throws an UnsupportedOperationException.
-     **/
-    @Override
-    public int delete(Uri uri, String selection, String[] selectionArgs) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * This ContentProvider is read-only. This method throws an UnsupportedOperationException.
-     **/
-    @Override
-    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-        throw new UnsupportedOperationException();
-    }
-
-    private static class XMLCursor extends MatrixCursor {
-        private final Pattern mSelectionPattern;
-        private Pattern[] mProjectionPatterns;
-        private String[] mAttributeNames;
-        private String[] mCurrentValues;
-        private BitSet[] mActiveTextDepthMask;
-        private final int mNumberOfProjections;
-
-        public XMLCursor(String selection, String[] projections) {
-            super(projections);
-            // The first column in projections is used for the _ID
-            mNumberOfProjections = projections.length - 1;
-            mSelectionPattern = createPattern(selection);
-            createProjectionPattern(projections);
-        }
-
-        private Pattern createPattern(String input) {
-            String pattern = input.replaceAll("//", "/(.*/|)").replaceAll("^/", "^/") + "$";
-            return Pattern.compile(pattern);
-        }
-
-        private void createProjectionPattern(String[] projections) {
-            mProjectionPatterns = new Pattern[mNumberOfProjections];
-            mAttributeNames = new String[mNumberOfProjections];
-            mActiveTextDepthMask = new BitSet[mNumberOfProjections];
-            // Add a column to store _ID
-            mCurrentValues = new String[mNumberOfProjections + 1];
-
-            for (int i=0; i<mNumberOfProjections; i++) {
-                mActiveTextDepthMask[i] = new BitSet();
-                String projection = projections[i + 1]; // +1 to skip the _ID column
-                int atIndex = projection.lastIndexOf('@', projection.length());
-                if (atIndex >= 0) {
-                    mAttributeNames[i] = projection.substring(atIndex+1);
-                    projection = projection.substring(0, atIndex);
-                } else {
-                    mAttributeNames[i] = null;
-                }
-
-                // Conforms to XPath standard: reference to local context starts with a .
-                if (projection.charAt(0) == '.') {
-                    projection = projection.substring(1);
-                }
-                mProjectionPatterns[i] = createPattern(projection);
-            }
-        }
-
-        public void parseWith(XmlPullParser parser) throws IOException, XmlPullParserException {
-            StringBuilder path = new StringBuilder();
-            Stack<Integer> pathLengthStack = new Stack<Integer>();
-
-            // There are two parsing mode: in root mode, rootPath is updated and nodes matching
-            // selectionPattern are searched for and currentNodeDepth is negative.
-            // When a node matching selectionPattern is found, currentNodeDepth is set to 0 and
-            // updated as children are parsed and projectionPatterns are searched in nodePath.
-            int currentNodeDepth = -1;
-
-            // Index where local selected node path starts from in path
-            int currentNodePathStartIndex = 0;
-
-            int eventType = parser.getEventType();
-            while (eventType != XmlPullParser.END_DOCUMENT) {
-
-                if (eventType == XmlPullParser.START_TAG) {
-                    // Update path
-                    pathLengthStack.push(path.length());
-                    path.append('/');
-                    String prefix = null;
-                    try {
-                        // getPrefix is not supported by local Xml resource parser
-                        prefix = parser.getPrefix();
-                    } catch (RuntimeException e) {
-                        prefix = null;
-                    }
-                    if (prefix != null) {
-                        path.append(prefix);
-                        path.append(':');
-                    }
-                    path.append(parser.getName());
-
-                    if (currentNodeDepth >= 0) {
-                        currentNodeDepth++;
-                    } else {
-                        // A node matching selection is found: initialize child parsing mode
-                        if (mSelectionPattern.matcher(path.toString()).matches()) {
-                            currentNodeDepth = 0;
-                            currentNodePathStartIndex = path.length();
-                            mCurrentValues[0] = Integer.toString(getCount()); // _ID
-                            for (int i = 0; i < mNumberOfProjections; i++) {
-                                // Reset values to default (empty string)
-                                mCurrentValues[i + 1] = "";
-                                mActiveTextDepthMask[i].clear();
-                            }
-                        }
-                    }
-
-                    // This test has to be separated from the previous one as currentNodeDepth can
-                    // be modified above (when a node matching selection is found).
-                    if (currentNodeDepth >= 0) {
-                        final String localNodePath = path.substring(currentNodePathStartIndex);
-                        for (int i = 0; i < mNumberOfProjections; i++) {
-                            if (mProjectionPatterns[i].matcher(localNodePath).matches()) {
-                                String attribute = mAttributeNames[i];
-                                if (attribute != null) {
-                                    mCurrentValues[i + 1] =
-                                        parser.getAttributeValue(null, attribute);
-                                } else {
-                                    mActiveTextDepthMask[i].set(currentNodeDepth, true);
-                                }
-                            }
-                        }
-                    }
-
-                } else if (eventType == XmlPullParser.END_TAG) {
-                    // Pop last node from path
-                    final int length = pathLengthStack.pop();
-                    path.setLength(length);
-
-                    if (currentNodeDepth >= 0) {
-                        if (currentNodeDepth == 0) {
-                            // Leaving a selection matching node: add a new row with results
-                            addRow(mCurrentValues);
-                        } else {
-                            for (int i = 0; i < mNumberOfProjections; i++) {
-                                mActiveTextDepthMask[i].set(currentNodeDepth, false);
-                            }
-                        }
-                        currentNodeDepth--;
-                    }
-
-                } else if ((eventType == XmlPullParser.TEXT) && (!parser.isWhitespace())) {
-                    for (int i = 0; i < mNumberOfProjections; i++) {
-                        if ((currentNodeDepth >= 0) &&
-                            (mActiveTextDepthMask[i].get(currentNodeDepth))) {
-                            mCurrentValues[i + 1] += parser.getText();
-                        }
-                    }
-                }
-
-                eventType = parser.next();
-            }
-        }
-    }
-}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 454cb31..ddb6ef0 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -91,15 +91,6 @@
     public String backupAgentName;
 
     /**
-     * Class implementing the package's *full* backup functionality.  This
-     * is not usable except by system-installed packages.  It can be the same
-     * as the backupAgent.
-     *
-     * @hide
-     */
-    public String fullBackupAgentName;
-
-    /**
      * Value for {@link #flags}: if set, this application is installed in the
      * device's system image.
      */
@@ -555,7 +546,6 @@
         dest.writeInt(installLocation);
         dest.writeString(manageSpaceActivityName);
         dest.writeString(backupAgentName);
-        dest.writeString(fullBackupAgentName);
         dest.writeInt(descriptionRes);
     }
 
@@ -593,7 +583,6 @@
         installLocation = source.readInt();
         manageSpaceActivityName = source.readString();
         backupAgentName = source.readString();
-        fullBackupAgentName = source.readString();
         descriptionRes = source.readInt();
     }
 
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index e927f6c..53d6bb1 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1517,17 +1517,6 @@
             }
         }
 
-        // fullBackupAgent is explicitly handled even if allowBackup is false
-        name = sa.getNonConfigurationString(
-                com.android.internal.R.styleable.AndroidManifestApplication_fullBackupAgent, 0);
-        if (name != null) {
-            ai.fullBackupAgentName = buildClassName(pkgName, name, outError);
-            if (false) {
-                Log.v(TAG, "android:fullBackupAgent=" + ai.fullBackupAgentName
-                        + " from " + pkgName + "+" + name);
-            }
-        }
-
         TypedValue v = sa.peekValue(
                 com.android.internal.R.styleable.AndroidManifestApplication_label);
         if (v != null && (ai.labelRes=v.resourceId) == 0) {
@@ -1573,7 +1562,7 @@
 
         boolean hardwareAccelerated = sa.getBoolean(
                 com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
-                false);
+                owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
 
         if (sa.getBoolean(
                 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
index 11068e5..1205da7 100755
--- a/core/java/android/content/pm/PackageStats.java
+++ b/core/java/android/content/pm/PackageStats.java
@@ -40,6 +40,12 @@
     public long cacheSize;
 
     /**
+     * Size of the secure container on external storage holding the
+     * application's code.
+     */
+    public long externalCodeSize;
+
+    /**
      * Size of the external data used by the application (e.g.,
      * <sdcard>/Android/data/<app>)
      */
@@ -80,6 +86,8 @@
         sb.append(dataSize);
         sb.append(",cacheSize=");
         sb.append(cacheSize);
+        sb.append(",externalCodeSize=");
+        sb.append(externalCodeSize);
         sb.append(",externalDataSize=");
         sb.append(externalDataSize);
         sb.append(",externalCacheSize=");
@@ -100,6 +108,7 @@
         codeSize = source.readLong();
         dataSize = source.readLong();
         cacheSize = source.readLong();
+        externalCodeSize = source.readLong();
         externalDataSize = source.readLong();
         externalCacheSize = source.readLong();
         externalMediaSize = source.readLong();
@@ -111,6 +120,7 @@
         codeSize = pStats.codeSize;
         dataSize = pStats.dataSize;
         cacheSize = pStats.cacheSize;
+        externalCodeSize = pStats.externalCodeSize;
         externalDataSize = pStats.externalDataSize;
         externalCacheSize = pStats.externalCacheSize;
         externalMediaSize = pStats.externalMediaSize;
@@ -126,6 +136,7 @@
         dest.writeLong(codeSize);
         dest.writeLong(dataSize);
         dest.writeLong(cacheSize);
+        dest.writeLong(externalCodeSize);
         dest.writeLong(externalDataSize);
         dest.writeLong(externalCacheSize);
         dest.writeLong(externalMediaSize);
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 0be1776..8a42693 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -288,7 +288,8 @@
      * you can call {@link #reconnect()} to reclaim the camera.
      *
      * <p>This must be done before calling
-     * {@link android.media.MediaRecorder#setCamera(Camera)}.
+     * {@link android.media.MediaRecorder#setCamera(Camera)}. This cannot be
+     * called after recording starts.
      *
      * <p>If you are not recording video, you probably do not need this method.
      *
@@ -301,6 +302,11 @@
      * Camera objects are locked by default unless {@link #unlock()} is
      * called.  Normally {@link #reconnect()} is used instead.
      *
+     * <p>Since API level 13, camera is automatically locked for applications in
+     * {@link android.media.MediaRecorder#start()}. Applications can use the
+     * camera (ex: zoom) after recording starts. There is no need to call this
+     * after recording starts or stops.
+     *
      * <p>If you are not recording video, you probably do not need this method.
      *
      * @throws RuntimeException if the camera cannot be re-locked (for
@@ -315,9 +321,10 @@
      * which will re-acquire the lock and allow you to continue using the
      * camera.
      *
-     * <p>This must be done after {@link android.media.MediaRecorder} is
-     * done recording if {@link android.media.MediaRecorder#setCamera(Camera)}
-     * was used.
+     * <p>Since API level 13, camera is automatically locked for applications in
+     * {@link android.media.MediaRecorder#start()}. Applications can use the
+     * camera (ex: zoom) after recording starts. There is no need to call this
+     * after recording starts or stops.
      *
      * <p>If you are not recording video, you probably do not need this method.
      *
@@ -827,7 +834,9 @@
      * <p>This method is only valid when preview is active (after
      * {@link #startPreview()}).  Preview will be stopped after the image is
      * taken; callers must call {@link #startPreview()} again if they want to
-     * re-start preview or take more pictures.
+     * re-start preview or take more pictures. This should not be called between
+     * {@link android.media.MediaRecorder#start()} and
+     * {@link android.media.MediaRecorder#stop()}.
      *
      * <p>After calling this method, you must not call {@link #startPreview()}
      * or take another picture until the JPEG callback has returned.
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index df8cf9a..e10f218 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -47,6 +47,7 @@
     private static final int DO_APP_PRIVATE_COMMAND = 100;
     private static final int DO_TOGGLE_SOFT_INPUT = 105;
     private static final int DO_FINISH_SESSION = 110;
+    private static final int DO_VIEW_CLICKED = 115;
 
     HandlerCaller mCaller;
     InputMethodSession mInputMethodSession;
@@ -133,6 +134,10 @@
                 mInputMethodSession = null;
                 return;
             }
+            case DO_VIEW_CLICKED: {
+                mInputMethodSession.viewClicked(msg.arg1 == 1);
+                return;
+            }
         }
         Log.w(TAG, "Unhandled message code: " + msg.what);
     }
@@ -167,7 +172,11 @@
                 oldSelStart, oldSelEnd, newSelStart, newSelEnd,
                 candidatesStart, candidatesEnd));
     }
-    
+
+    public void viewClicked(boolean focusChanged) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageI(DO_VIEW_CLICKED, focusChanged ? 1 : 0));
+    }
+
     public void updateCursor(Rect newCursor) {
         mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_UPDATE_CURSOR,
                 newCursor));
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index feb246e..9481a88 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -488,7 +488,15 @@
             InputMethodService.this.onUpdateSelection(oldSelStart, oldSelEnd,
                     newSelStart, newSelEnd, candidatesStart, candidatesEnd);
         }
-        
+
+        @Override
+        public void viewClicked(boolean focusChanged) {
+            if (!isEnabled()) {
+                return;
+            }
+            InputMethodService.this.onViewClicked(focusChanged);
+        }
+
         /**
          * Call {@link InputMethodService#onUpdateCursor
          * InputMethodService.onUpdateCursor()}.
@@ -1609,6 +1617,16 @@
     }
 
     /**
+     * Called when the user tapped or clicked a text view.
+     * IMEs can't rely on this method being called because this was not part of the original IME
+     * protocol, so applications with custom text editing written before this method appeared will
+     * not call to inform the IME of this interaction.
+     * @param focusChanged true if the user changed the focused view by this click.
+     */
+    public void onViewClicked(boolean focusChanged) {
+    }
+
+    /**
      * Called when the application has reported a new location of its text
      * cursor.  This is only called if explicitly requested by the input method.
      * The default implementation does nothing.
diff --git a/core/java/android/net/DnsPinger.java b/core/java/android/net/DnsPinger.java
new file mode 100644
index 0000000..f2d84eb
--- /dev/null
+++ b/core/java/android/net/DnsPinger.java
@@ -0,0 +1,228 @@
+/*
+ * 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.content.Context;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.NetworkUtils;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.util.Slog;
+
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketTimeoutException;
+import java.util.Collection;
+import java.util.Random;
+
+/**
+ * Performs a simple DNS "ping" by sending a "server status" query packet to the
+ * DNS server. As long as the server replies, we consider it a success.
+ * <p>
+ * We do not use a simple hostname lookup because that could be cached and the
+ * 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 {
+    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 DNS_PORT = 53;
+
+    /** Used to generate IDs */
+    private static Random sRandom = new Random();
+
+    private ConnectivityManager mConnectivityManager = null;
+    private Context mContext;
+    private int mConnectionType;
+    private InetAddress mDefaultDns;
+
+    private String TAG;
+
+    /**
+     * @param connectionType The connection type from {@link ConnectivityManager}
+     */
+    public DnsPinger(String TAG, Context context, int connectionType) {
+        mContext = context;
+        mConnectionType = connectionType;
+        if (!ConnectivityManager.isNetworkTypeValid(connectionType)) {
+            Slog.e(TAG, "Invalid connectionType in constructor: " + connectionType);
+        }
+        this.TAG = TAG;
+
+        mDefaultDns = getDefaultDns();
+    }
+
+    /**
+     * @return The first DNS in the link properties of the specified connection
+     *         type or the default system DNS if the link properties has null
+     *         dns set. Should not be null.
+     */
+    public InetAddress getDns() {
+        LinkProperties curLinkProps = getCurrentLinkProperties();
+        if (curLinkProps == null) {
+            Slog.e(TAG, "getCurLinkProperties:: LP for type" + mConnectionType + " is null!");
+            return mDefaultDns;
+        }
+
+        Collection<InetAddress> dnses = curLinkProps.getDnses();
+        if (dnses == null || dnses.size() == 0) {
+            Slog.v(TAG, "getDns::LinkProps has null dns - returning default");
+            return mDefaultDns;
+        }
+
+        return dnses.iterator().next();
+    }
+
+    private LinkProperties getCurrentLinkProperties() {
+        if (mConnectivityManager == null) {
+            mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
+                    Context.CONNECTIVITY_SERVICE);
+        }
+
+        return mConnectivityManager.getLinkProperties(mConnectionType);
+    }
+
+    private InetAddress getDefaultDns() {
+        String dns = Settings.Secure.getString(mContext.getContentResolver(),
+                Settings.Secure.DEFAULT_DNS_SERVER);
+        if (dns == null || dns.length() == 0) {
+            dns = mContext.getResources().getString(
+                    com.android.internal.R.string.config_default_dns_server);
+        }
+        try {
+            return NetworkUtils.numericToInetAddress(dns);
+        } catch (IllegalArgumentException e) {
+            Slog.w(TAG, "getDefaultDns::malformed default dns address");
+            return null;
+        }
+    }
+
+    /**
+     * @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);
+        }
+    }
+}
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 6f92247..a866436 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -53,6 +53,7 @@
     private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
     private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
 
+    private static boolean mLinkUp;
     private LinkProperties mLinkProperties;
     private LinkCapabilities mLinkCapabilities;
     private NetworkInfo mNetworkInfo;
@@ -74,8 +75,25 @@
             mTracker = tracker;
         }
 
-        public void interfaceLinkStatusChanged(String iface, boolean up) {
-            Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down"));
+        public void interfaceStatusChanged(String iface, boolean up) {
+            Log.d(TAG, "Interface status changed: " + iface + (up ? "up" : "down"));
+        }
+
+        public void interfaceLinkStateChanged(String iface, boolean up) {
+            if (mIface.equals(iface) && mLinkUp != up) {
+                Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down"));
+                mLinkUp = up;
+
+                // use DHCP
+                if (up) {
+                    mTracker.reconnect();
+                } else {
+                    NetworkUtils.stopDhcp(mIface);
+                    mTracker.mNetworkInfo.setIsAvailable(false);
+                    mTracker.mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED,
+                                                           null, null);
+                }
+            }
         }
 
         public void interfaceAdded(String iface) {
@@ -91,6 +109,7 @@
         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORKTYPE, "");
         mLinkProperties = new LinkProperties();
         mLinkCapabilities = new LinkCapabilities();
+        mLinkUp = false;
 
         mNetworkInfo.setIsAvailable(false);
         setTeardownRequested(false);
@@ -182,14 +201,11 @@
         // register for notifications from NetworkManagement Service
         IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
         INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
-        mInterfaceObserver = new InterfaceObserver(this);
-        try {
-            service.registerObserver(mInterfaceObserver);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Could not register InterfaceObserver " + e);
-        }
 
-        // connect to an ethernet interface that already exists
+        mInterfaceObserver = new InterfaceObserver(this);
+
+        // enable and try to connect to an ethernet interface that
+        // already exists
         sIfaceMatch = context.getResources().getString(
             com.android.internal.R.string.config_ethernet_iface_regex);
         try {
@@ -197,6 +213,8 @@
             for (String iface : ifaces) {
                 if (iface.matches(sIfaceMatch)) {
                     mIface = iface;
+                    InterfaceConfiguration config = service.getInterfaceConfig(iface);
+                    mLinkUp = config.isActive();
                     reconnect();
                     break;
                 }
@@ -204,6 +222,12 @@
         } catch (RemoteException e) {
             Log.e(TAG, "Could not get list of interfaces " + e);
         }
+
+        try {
+            service.registerObserver(mInterfaceObserver);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not register InterfaceObserver " + e);
+        }
     }
 
     /**
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index fba16e1..d6f5643 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -23,6 +23,7 @@
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 
+import com.android.internal.net.LegacyVpnInfo;
 import com.android.internal.net.VpnConfig;
 
 /**
@@ -101,7 +102,11 @@
 
     void protectVpn(in ParcelFileDescriptor socket);
 
-    String prepareVpn(String packageName);
+    boolean prepareVpn(String oldPackage, String newPackage);
 
     ParcelFileDescriptor establishVpn(in VpnConfig config);
+
+    void startLegacyVpn(in VpnConfig config, in String[] racoon, in String[] mtpd);
+
+    LegacyVpnInfo getLegacyVpnInfo();
 }
diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl
index d30b63d..4436e6e 100644
--- a/core/java/android/net/INetworkManagementEventObserver.aidl
+++ b/core/java/android/net/INetworkManagementEventObserver.aidl
@@ -23,12 +23,21 @@
  */
 interface INetworkManagementEventObserver {
     /**
-     * Interface link status has changed.
+     * Interface configuration status has changed.
      *
      * @param iface The interface.
-     * @param link True if link is up.
+     * @param up True if the interface has been enabled.
      */
-    void interfaceLinkStatusChanged(String iface, boolean link);
+    void interfaceStatusChanged(String iface, boolean up);
+
+    /**
+     * Interface physical-layer link state has changed.  For Ethernet,
+     * this method is invoked when the cable is plugged in or unplugged.
+     *
+     * @param iface The interface.
+     * @param up  True if the physical link-layer connection signal is valid.
+     */
+    void interfaceLinkStateChanged(String iface, boolean up);
 
     /**
      * An interface has been added to the system
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index ae9aa05..0548250 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -33,4 +33,7 @@
     /** Return usage summary per UID for traffic that matches template. */
     NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags);
 
+    /** Force update of statistics. */
+    void forceUpdate();
+
 }
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 91af16d..593b2b7 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -16,14 +16,21 @@
 
 package android.net;
 
+import static android.content.pm.PackageManager.GET_SIGNATURES;
 import static android.text.format.Time.MONTH_DAY;
 
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.Signature;
 import android.os.RemoteException;
 import android.text.format.Time;
 
+import com.google.android.collect.Sets;
+
 import java.io.PrintWriter;
+import java.util.HashSet;
 
 /**
  * Manager for creating and modifying network policy rules.
@@ -42,6 +49,8 @@
     /** Reject traffic on metered networks. */
     public static final int RULE_REJECT_METERED = 0x1;
 
+    private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
+
     /**
      * {@link Intent} action launched when user selects {@link NetworkPolicy}
      * warning notification.
@@ -210,8 +219,37 @@
      * usually to protect critical system services.
      */
     public static boolean isUidValidForPolicy(Context context, int uid) {
-        return (uid >= android.os.Process.FIRST_APPLICATION_UID
-                && uid <= android.os.Process.LAST_APPLICATION_UID);
+        // first, quick-reject non-applications
+        if (uid < android.os.Process.FIRST_APPLICATION_UID
+                || uid > android.os.Process.LAST_APPLICATION_UID) {
+            return false;
+        }
+
+        if (!ALLOW_PLATFORM_APP_POLICY) {
+            final PackageManager pm = context.getPackageManager();
+            final HashSet<Signature> systemSignature;
+            try {
+                systemSignature = Sets.newHashSet(
+                        pm.getPackageInfo("android", GET_SIGNATURES).signatures);
+            } catch (NameNotFoundException e) {
+                throw new RuntimeException("problem finding system signature", e);
+            }
+
+            try {
+                // reject apps signed with platform cert
+                for (String packageName : pm.getPackagesForUid(uid)) {
+                    final HashSet<Signature> packageSignature = Sets.newHashSet(
+                            pm.getPackageInfo(packageName, GET_SIGNATURES).signatures);
+                    if (packageSignature.containsAll(systemSignature)) {
+                        return false;
+                    }
+                }
+            } catch (NameNotFoundException e) {
+            }
+        }
+
+        // nothing found above; we can apply policy to UID
+        return true;
     }
 
     /** {@hide} */
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index ff6e220..dd2945c 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -279,10 +279,17 @@
         return (long) (start + (r.nextFloat() * (end - start)));
     }
 
-    public void dump(String prefix, PrintWriter pw) {
+    public void dump(String prefix, PrintWriter pw, boolean fullHistory) {
         pw.print(prefix);
         pw.print("NetworkStatsHistory: bucketDuration="); pw.println(bucketDuration);
-        for (int i = 0; i < bucketCount; i++) {
+
+        final int start = fullHistory ? 0 : Math.max(0, bucketCount - 32);
+        if (start > 0) {
+            pw.print(prefix);
+            pw.print("  (omitting "); pw.print(start); pw.println(" buckets)");
+        }
+
+        for (int i = start; i < bucketCount; i++) {
             pw.print(prefix);
             pw.print("  bucketStart="); pw.print(bucketStart[i]);
             pw.print(" rx="); pw.print(rx[i]);
@@ -293,7 +300,7 @@
     @Override
     public String toString() {
         final CharArrayWriter writer = new CharArrayWriter();
-        dump("", new PrintWriter(writer));
+        dump("", new PrintWriter(writer), false);
         return writer.toString();
     }
 
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 8a678d6..76534ef 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -38,8 +38,22 @@
     /** Bring the named network interface down. */
     public native static int disableInterface(String interfaceName);
 
-    /** Reset any sockets that are connected via the named interface. */
-    public native static int resetConnections(String interfaceName);
+    /** Setting bit 0 indicates reseting of IPv4 addresses required */
+    public static final int RESET_IPV4_ADDRESSES = 0x01;
+
+    /** Setting bit 1 indicates reseting of IPv4 addresses required */
+    public static final int RESET_IPV6_ADDRESSES = 0x02;
+
+    /** Reset all addresses */
+    public static final int RESET_ALL_ADDRESSES = RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES;
+
+    /**
+     * Reset IPv6 or IPv4 sockets that are connected via the named interface.
+     *
+     * @param interfaceName is the interface to reset
+     * @param mask {@see #RESET_IPV4_ADDRESSES} and {@see #RESET_IPV6_ADDRESSES}
+     */
+    public native static int resetConnections(String interfaceName, int mask);
 
     /**
      * Start the DHCP client daemon, in order to have it request addresses
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index cb47193..2b59dba 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -16,14 +16,18 @@
 
 package android.net;
 
+import android.app.DownloadManager;
+import android.app.backup.BackupManager;
 import android.content.Context;
+import android.media.MediaPlayer;
 import android.os.IBinder;
 import android.os.INetworkManagementService;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 
-import dalvik.system.BlockGuard;
+import com.android.server.NetworkManagementSocketTagger;
 
+import dalvik.system.SocketTagger;
 import java.net.Socket;
 import java.net.SocketException;
 
@@ -50,6 +54,27 @@
     public static final int UID_REMOVED = -4;
 
     /**
+     * Default tag value for {@link DownloadManager} traffic.
+     *
+     * @hide
+     */
+    public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFF0001;
+
+    /**
+     * Default tag value for {@link MediaPlayer} traffic.
+     *
+     * @hide
+     */
+    public static final int TAG_SYSTEM_MEDIA = 0xFFFF0002;
+
+    /**
+     * Default tag value for {@link BackupManager} traffic.
+     *
+     * @hide
+     */
+    public static final int TAG_SYSTEM_BACKUP = 0xFFFF0003;
+
+    /**
      * Snapshot of {@link NetworkStats} when the currently active profiling
      * session started, or {@code null} if no session active.
      *
@@ -67,12 +92,20 @@
      * Changes only take effect during subsequent calls to
      * {@link #tagSocket(Socket)}.
      */
+    public static void setThreadStatsTag(int tag) {
+        NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
+    }
+
+    /**
+     * @deprecated unsupported, will eventually be removed
+     */
+    @Deprecated
     public static void setThreadStatsTag(String tag) {
-        BlockGuard.setThreadSocketStatsTag(tag);
+        setThreadStatsTag(tag.hashCode());
     }
 
     public static void clearThreadStatsTag() {
-        BlockGuard.setThreadSocketStatsTag(null);
+        NetworkManagementSocketTagger.setThreadSocketStatsTag(-1);
     }
 
     /**
@@ -89,12 +122,12 @@
      * {@hide}
      */
     public static void setThreadStatsUid(int uid) {
-        BlockGuard.setThreadSocketStatsUid(uid);
+        NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
     }
 
     /** {@hide} */
     public static void clearThreadStatsUid() {
-        BlockGuard.setThreadSocketStatsUid(-1);
+        NetworkManagementSocketTagger.setThreadSocketStatsUid(-1);
     }
 
     /**
@@ -103,18 +136,18 @@
      * parameters. When finished, call {@link #untagSocket(Socket)} to remove
      * statistics parameters.
      *
-     * @see #setThreadStatsTag(String)
+     * @see #setThreadStatsTag(int)
      * @see #setThreadStatsUid(int)
      */
     public static void tagSocket(Socket socket) throws SocketException {
-        BlockGuard.tagSocketFd(socket.getFileDescriptor$());
+        SocketTagger.get().tag(socket);
     }
 
     /**
      * Remove any statistics parameters from the given {@link Socket}.
      */
     public static void untagSocket(Socket socket) throws SocketException {
-        BlockGuard.untagSocketFd(socket.getFileDescriptor$());
+        SocketTagger.get().untag(socket);
     }
 
     /**
diff --git a/core/java/android/net/http/SslCertificate.java b/core/java/android/net/http/SslCertificate.java
index 5079c23..fe6d4eb 100644
--- a/core/java/android/net/http/SslCertificate.java
+++ b/core/java/android/net/http/SslCertificate.java
@@ -16,16 +16,27 @@
 
 package android.net.http;
 
+import android.content.Context;
 import android.os.Bundle;
+import android.text.format.DateFormat;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
 
+import java.io.ByteArrayInputStream;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Vector;
 
-import java.security.cert.X509Certificate;
-
-import com.android.org.bouncycastle.asn1.DERObjectIdentifier;
 import com.android.org.bouncycastle.asn1.x509.X509Name;
 
 /**
@@ -41,30 +52,40 @@
     /**
      * Name of the entity this certificate is issued to
      */
-    private DName mIssuedTo;
+    private final DName mIssuedTo;
 
     /**
      * Name of the entity this certificate is issued by
      */
-    private DName mIssuedBy;
+    private final DName mIssuedBy;
 
     /**
      * Not-before date from the validity period
      */
-    private Date mValidNotBefore;
+    private final Date mValidNotBefore;
 
     /**
      * Not-after date from the validity period
      */
-    private Date mValidNotAfter;
+    private final Date mValidNotAfter;
 
-     /**
+    /**
+     * The original source certificate, if available.
+     *
+     * TODO If deprecated constructors are removed, this should always
+     * be available, and saveState and restoreState can be simplified
+     * to be unconditional.
+     */
+    private final X509Certificate mX509Certificate;
+
+    /**
      * Bundle key names
      */
     private static final String ISSUED_TO = "issued-to";
     private static final String ISSUED_BY = "issued-by";
     private static final String VALID_NOT_BEFORE = "valid-not-before";
     private static final String VALID_NOT_AFTER = "valid-not-after";
+    private static final String X509_CERTIFICATE = "x509-certificate";
 
     /**
      * Saves the certificate state to a bundle
@@ -72,18 +93,21 @@
      * @return A bundle with the certificate stored in it or null if fails
      */
     public static Bundle saveState(SslCertificate certificate) {
-        Bundle bundle = null;
-
-        if (certificate != null) {
-            bundle = new Bundle();
-
-            bundle.putString(ISSUED_TO, certificate.getIssuedTo().getDName());
-            bundle.putString(ISSUED_BY, certificate.getIssuedBy().getDName());
-
-            bundle.putString(VALID_NOT_BEFORE, certificate.getValidNotBefore());
-            bundle.putString(VALID_NOT_AFTER, certificate.getValidNotAfter());
+        if (certificate == null) {
+            return null;
         }
-
+        Bundle bundle = new Bundle();
+        bundle.putString(ISSUED_TO, certificate.getIssuedTo().getDName());
+        bundle.putString(ISSUED_BY, certificate.getIssuedBy().getDName());
+        bundle.putString(VALID_NOT_BEFORE, certificate.getValidNotBefore());
+        bundle.putString(VALID_NOT_AFTER, certificate.getValidNotAfter());
+        X509Certificate x509Certificate = certificate.mX509Certificate;
+        if (x509Certificate != null) {
+            try {
+                bundle.putByteArray(X509_CERTIFICATE, x509Certificate.getEncoded());
+            } catch (CertificateEncodingException ignored) {
+            }
+        }
         return bundle;
     }
 
@@ -93,29 +117,43 @@
      * @return The SSL certificate stored in the bundle or null if fails
      */
     public static SslCertificate restoreState(Bundle bundle) {
-        if (bundle != null) {
-            return new SslCertificate(
-                bundle.getString(ISSUED_TO),
-                bundle.getString(ISSUED_BY),
-                bundle.getString(VALID_NOT_BEFORE),
-                bundle.getString(VALID_NOT_AFTER));
+        if (bundle == null) {
+            return null;
         }
-
-        return null;
+        X509Certificate x509Certificate;
+        byte[] bytes = bundle.getByteArray(X509_CERTIFICATE);
+        if (bytes == null) {
+            x509Certificate = null;
+        } else {
+            try {
+                CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+                Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(bytes));
+                x509Certificate = (X509Certificate) cert;
+            } catch (CertificateException e) {
+                x509Certificate = null;
+            }
+        }
+        return new SslCertificate(bundle.getString(ISSUED_TO),
+                                  bundle.getString(ISSUED_BY),
+                                  parseDate(bundle.getString(VALID_NOT_BEFORE)),
+                                  parseDate(bundle.getString(VALID_NOT_AFTER)),
+                                  x509Certificate);
     }
 
     /**
      * Creates a new SSL certificate object
      * @param issuedTo The entity this certificate is issued to
      * @param issuedBy The entity that issued this certificate
-     * @param validNotBefore The not-before date from the certificate validity period in ISO 8601 format
-     * @param validNotAfter The not-after date from the certificate validity period in ISO 8601 format
+     * @param validNotBefore The not-before date from the certificate
+     *     validity period in ISO 8601 format
+     * @param validNotAfter The not-after date from the certificate
+     *     validity period in ISO 8601 format
      * @deprecated Use {@link #SslCertificate(X509Certificate)}
      */
     @Deprecated
     public SslCertificate(
             String issuedTo, String issuedBy, String validNotBefore, String validNotAfter) {
-        this(issuedTo, issuedBy, parseDate(validNotBefore), parseDate(validNotAfter));
+        this(issuedTo, issuedBy, parseDate(validNotBefore), parseDate(validNotAfter), null);
     }
 
     /**
@@ -129,10 +167,7 @@
     @Deprecated
     public SslCertificate(
             String issuedTo, String issuedBy, Date validNotBefore, Date validNotAfter) {
-        mIssuedTo = new DName(issuedTo);
-        mIssuedBy = new DName(issuedBy);
-        mValidNotBefore = cloneDate(validNotBefore);
-        mValidNotAfter  = cloneDate(validNotAfter);
+        this(issuedTo, issuedBy, validNotBefore, validNotAfter, null);
     }
 
     /**
@@ -143,7 +178,19 @@
         this(certificate.getSubjectDN().getName(),
              certificate.getIssuerDN().getName(),
              certificate.getNotBefore(),
-             certificate.getNotAfter());
+             certificate.getNotAfter(),
+             certificate);
+    }
+
+    private SslCertificate(
+            String issuedTo, String issuedBy,
+            Date validNotBefore, Date validNotAfter,
+            X509Certificate x509Certificate) {
+        mIssuedTo = new DName(issuedTo);
+        mIssuedBy = new DName(issuedBy);
+        mValidNotBefore = cloneDate(validNotBefore);
+        mValidNotAfter  = cloneDate(validNotAfter);
+        mX509Certificate = x509Certificate;
     }
 
     /**
@@ -199,12 +246,59 @@
     }
 
     /**
+     * Convenience for UI presentation, not intended as public API.
+     */
+    private static String getSerialNumber(X509Certificate x509Certificate) {
+        if (x509Certificate == null) {
+            return "";
+        }
+        BigInteger serialNumber = x509Certificate.getSerialNumber();
+        if (serialNumber == null) {
+            return "";
+        }
+        return fingerprint(serialNumber.toByteArray());
+    }
+
+    /**
+     * Convenience for UI presentation, not intended as public API.
+     */
+    private static String getDigest(X509Certificate x509Certificate, String algorithm) {
+        if (x509Certificate == null) {
+            return "";
+        }
+        try {
+            byte[] bytes = x509Certificate.getEncoded();
+            MessageDigest md = MessageDigest.getInstance(algorithm);
+            byte[] digest = md.digest(bytes);
+            return fingerprint(digest);
+        } catch (CertificateEncodingException ignored) {
+            return "";
+        } catch (NoSuchAlgorithmException ignored) {
+            return "";
+        }
+    }
+
+    private static final String fingerprint(byte[] bytes) {
+        if (bytes == null) {
+            return "";
+        }
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < bytes.length; i++) {
+            byte b = bytes[i];
+            IntegralToString.appendByteAsHex(sb, b, true);
+            if (i+1 != bytes.length) {
+                sb.append(':');
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
      * @return A string representation of this certificate for debugging
      */
     public String toString() {
-        return
-            "Issued to: " + mIssuedTo.getDName() + ";\n" +
-            "Issued by: " + mIssuedBy.getDName() + ";\n";
+        return ("Issued to: " + mIssuedTo.getDName() + ";\n"
+                + "Issued by: " + mIssuedBy.getDName() + ";\n");
     }
 
     /**
@@ -328,4 +422,73 @@
             return mUName != null ? mUName : "";
         }
     }
+
+    /**
+     * Inflates the SSL certificate view (helper method).
+     * @return The resultant certificate view with issued-to, issued-by,
+     * issued-on, expires-on, and possibly other fields set.
+     *
+     * @hide Used by Browser and Settings
+     */
+    public View inflateCertificateView(Context context) {
+        LayoutInflater factory = LayoutInflater.from(context);
+
+        View certificateView = factory.inflate(
+            com.android.internal.R.layout.ssl_certificate, null);
+
+        // issued to:
+        SslCertificate.DName issuedTo = getIssuedTo();
+        if (issuedTo != null) {
+            ((TextView) certificateView.findViewById(com.android.internal.R.id.to_common))
+                    .setText(issuedTo.getCName());
+            ((TextView) certificateView.findViewById(com.android.internal.R.id.to_org))
+                    .setText(issuedTo.getOName());
+            ((TextView) certificateView.findViewById(com.android.internal.R.id.to_org_unit))
+                    .setText(issuedTo.getUName());
+        }
+        // serial number:
+        ((TextView) certificateView.findViewById(com.android.internal.R.id.serial_number))
+                .setText(getSerialNumber(mX509Certificate));
+
+        // issued by:
+        SslCertificate.DName issuedBy = getIssuedBy();
+        if (issuedBy != null) {
+            ((TextView) certificateView.findViewById(com.android.internal.R.id.by_common))
+                    .setText(issuedBy.getCName());
+            ((TextView) certificateView.findViewById(com.android.internal.R.id.by_org))
+                    .setText(issuedBy.getOName());
+            ((TextView) certificateView.findViewById(com.android.internal.R.id.by_org_unit))
+                    .setText(issuedBy.getUName());
+        }
+
+        // issued on:
+        String issuedOn = formatCertificateDate(context, getValidNotBeforeDate());
+        ((TextView) certificateView.findViewById(com.android.internal.R.id.issued_on))
+                .setText(issuedOn);
+
+        // expires on:
+        String expiresOn = formatCertificateDate(context, getValidNotAfterDate());
+        ((TextView) certificateView.findViewById(com.android.internal.R.id.expires_on))
+                .setText(expiresOn);
+
+        // fingerprints:
+        ((TextView) certificateView.findViewById(com.android.internal.R.id.sha256_fingerprint))
+                .setText(getDigest(mX509Certificate, "SHA256"));
+        ((TextView) certificateView.findViewById(com.android.internal.R.id.sha1_fingerprint))
+                .setText(getDigest(mX509Certificate, "SHA1"));
+
+        return certificateView;
+    }
+
+    /**
+     * Formats the certificate date to a properly localized date string.
+     * @return Properly localized version of the certificate date string and
+     * the "" if it fails to localize.
+     */
+    private String formatCertificateDate(Context context, Date certificateDate) {
+        if (certificateDate == null) {
+            return "";
+        }
+        return DateFormat.getDateFormat(context).format(certificateDate);
+    }
 }
diff --git a/core/java/android/net/http/SslError.java b/core/java/android/net/http/SslError.java
index e1b9deb..1e1cb49 100644
--- a/core/java/android/net/http/SslError.java
+++ b/core/java/android/net/http/SslError.java
@@ -59,36 +59,97 @@
     /**
      * The SSL certificate associated with the error set
      */
-    SslCertificate mCertificate;
+    final SslCertificate mCertificate;
+
+    /**
+     * The URL associated with the error set.
+     */
+    final String mUrl;
 
     /**
      * Creates a new SSL error set object
      * @param error The SSL error
      * @param certificate The associated SSL certificate
+     * @deprecated Use {@link #SslError(int, SslCertificate, String)}
      */
+    @Deprecated
     public SslError(int error, SslCertificate certificate) {
         addError(error);
+        if (certificate == null) {
+            throw new NullPointerException("certificate is null.");
+        }
         mCertificate = certificate;
+        mUrl = "";
     }
 
     /**
      * Creates a new SSL error set object
      * @param error The SSL error
      * @param certificate The associated SSL certificate
+     * @deprecated Use {@link #SslError(int, X509Certificate, String)}
      */
+    @Deprecated
     public SslError(int error, X509Certificate certificate) {
         addError(error);
+        if (certificate == null) {
+            throw new NullPointerException("certificate is null.");
+        }
         mCertificate = new SslCertificate(certificate);
+        mUrl = "";
     }
 
     /**
-     * @return The SSL certificate associated with the error set
+     * Creates a new SSL error set object
+     * @param error The SSL error
+     * @param certificate The associated SSL certificate
+     * @param url The associated URL.
+     */
+    public SslError(int error, SslCertificate certificate, String url) {
+        addError(error);
+        if (certificate == null) {
+            throw new NullPointerException("certificate is null.");
+        }
+        mCertificate = certificate;
+        if (url == null) {
+            throw new NullPointerException("url is null.");
+        }
+        mUrl = url;
+    }
+
+    /**
+     * Creates a new SSL error set object
+     * @param error The SSL error
+     * @param certificate The associated SSL certificate
+     * @param url The associated URL.
+     */
+    public SslError(int error, X509Certificate certificate, String url) {
+        addError(error);
+        if (certificate == null) {
+            throw new NullPointerException("certificate is null.");
+        }
+        mCertificate = new SslCertificate(certificate);
+        if (url == null) {
+            throw new NullPointerException("url is null.");
+        }
+        mUrl = url;
+    }
+
+    /**
+     * @return The SSL certificate associated with the error set, non-null.
      */
     public SslCertificate getCertificate() {
         return mCertificate;
     }
 
     /**
+     * @return The URL associated with the error set, non-null.
+     * "" if one of the deprecated constructors is used.
+     */
+    public String getUrl() {
+        return mUrl;
+    }
+
+    /**
      * Adds the SSL error to the error set
      * @param error The SSL error to add
      * @return True iff the error being added is a known SSL error
@@ -137,6 +198,7 @@
      */
     public String toString() {
         return "primary error: " + getPrimaryError() +
-            " certificate: " + getCertificate();
+            " certificate: " + getCertificate() +
+            "  on URL: " + getUrl();
     }
 }
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index 5ade9eb..0eb8cd8 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -338,7 +338,15 @@
      * @hide
      */
     public static NdefRecord createUri(Uri uri) {
-        String uriString = uri.toString();
+        return createUri(uri.toString());
+    }
+
+    /**
+     * Creates an NDEF record of well known type URI.
+     * TODO: Make a public API
+     * @hide
+     */
+    public static NdefRecord createUri(String uriString) {
         byte prefix = 0x0;
         for (int i = 1; i < URI_PREFIX_MAP.length; i++) {
             if (uriString.startsWith(URI_PREFIX_MAP[i])) {
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index 54583d6..a73067a 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -313,14 +313,16 @@
      */
     @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder("TAG ")
-            .append("uid = ")
-            .append(mId)
-            .append(" Tech [");
-        for (int i : mTechList) {
-            sb.append(i)
-            .append(", ");
+        StringBuilder sb = new StringBuilder("TAG: Tech [");
+        String[] techList = getTechList();
+        int length = techList.length;
+        for (int i = 0; i < length; i++) {
+            sb.append(techList[i]);
+            if (i < length - 1) {
+                sb.append(", ");
+            }
         }
+        sb.append("]");
         return sb.toString();
     }
 
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 1b28aa2..6c7c58d 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -278,6 +278,16 @@
 
         /**
          * Current version under development.
+         *
+         * <p>Applications targeting this or a later release will get these
+         * new changes in behavior:</p>
+         * <ul>
+         * <li> 2d drawing hardware acceleration is now turned on by default.
+         * You can use
+         * {@link android.R.attr#hardwareAccelerated android:hardwareAccelerated}
+         * to turn it off if needed, although this is strongly discouraged since
+         * it will result in poor performance on larger screen devices.
+         * </ul>
          */
         public static final int ICE_CREAM_SANDWICH = CUR_DEVELOPMENT;
     }
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 1b09242..f230526 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -210,6 +210,21 @@
     NetworkStats getNetworkStatsUidDetail(int uid);
 
     /**
+     * Set quota for an interface.
+     */
+    void setInterfaceQuota(String iface, long quota);
+
+    /**
+     * Remove quota for an interface.
+     */
+    void removeInterfaceQuota(String iface);
+
+    /**
+     * Control network activity of a UID over interfaces with a quota limit.
+     */
+    void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces);
+
+    /**
      * Configures bandwidth throttling on an interface.
      */
     void setInterfaceThrottle(String iface, int rxKbps, int txKbps);
@@ -226,6 +241,23 @@
      */
     int getInterfaceTxThrottle(String iface);
 
-    void setBandwidthControlEnabled(boolean enabled);
+    /**
+     * Sets the name of the default interface in the DNS resolver.
+     */
+    void setDefaultInterfaceForDns(String iface);
 
+    /**
+     * Bind name servers to an interface in the DNS resolver.
+     */
+    void setDnsServersForInterface(String iface, in String[] servers);
+
+    /**
+     * Flush the DNS cache associated with the default interface
+     */
+    void flushDefaultDnsCache();
+
+    /**
+     * Flush the DNS cache associated with the specified interface
+     */
+    void flushInterfaceDnsCache(String iface);
 }
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 3edd692..c0be664 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -86,9 +86,7 @@
     public static final void prepareMainLooper() {
         prepare();
         setMainLooper(myLooper());
-        if (Process.supportsProcesses()) {
-            myLooper().mQueue.mQuitAllowed = false;
-        }
+        myLooper().mQueue.mQuitAllowed = false;
     }
 
     private synchronized static void setMainLooper(Looper looper) {
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index a17983a..21373ec 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -313,8 +313,8 @@
          */
         public void release(int flags) {
             synchronized (mToken) {
-                mHandler.removeCallbacks(mReleaser);
                 if (!mRefCounted || --mCount == 0) {
+                    mHandler.removeCallbacks(mReleaser);
                     try {
                         mService.releaseWakeLock(mToken, flags);
                     } catch (RemoteException e) {
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index d475f36..269e50e 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -92,12 +92,6 @@
     public static final int SDCARD_RW_GID = 1015;
 
     /**
-     * Defines the UID for the KeyChain service.
-     * @hide
-     */
-    public static final int KEYCHAIN_UID = 1020;
-
-    /**
      * Defines the UID/GID for the NFC service process.
      * @hide
      */
@@ -272,7 +266,8 @@
      * @param uid The user-id under which the process will run.
      * @param gid The group-id under which the process will run.
      * @param gids Additional group-ids associated with the process.
-     * @param enableDebugger True if debugging should be enabled for this process.
+     * @param debugFlags Additional flags.
+     * @param targetSdkVersion The target SDK version for the app.
      * @param zygoteArgs Additional arguments to supply to the zygote process.
      * 
      * @return int If > 0 the pid of the new process; if 0 the process is
@@ -284,72 +279,17 @@
     public static final int start(final String processClass,
                                   final String niceName,
                                   int uid, int gid, int[] gids,
-                                  int debugFlags,
-                                  String[] zygoteArgs)
-    {
-        if (supportsProcesses()) {
-            try {
-                return startViaZygote(processClass, niceName, uid, gid, gids,
-                        debugFlags, zygoteArgs);
-            } catch (ZygoteStartFailedEx ex) {
-                Log.e(LOG_TAG,
-                        "Starting VM process through Zygote failed");
-                throw new RuntimeException(
-                        "Starting VM process through Zygote failed", ex);
-            }
-        } else {
-            // Running in single-process mode
-            
-            Runnable runnable = new Runnable() {
-                        public void run() {
-                            Process.invokeStaticMain(processClass);
-                        }
-            };
-            
-            // Thread constructors must not be called with null names (see spec). 
-            if (niceName != null) {
-                new Thread(runnable, niceName).start();
-            } else {
-                new Thread(runnable).start();
-            }
-            
-            return 0;
-        }
-    }
-    
-    /**
-     * Start a new process.  Don't supply a custom nice name.
-     * {@hide}
-     */
-    public static final int start(String processClass, int uid, int gid,
-            int[] gids, int debugFlags, String[] zygoteArgs) {
-        return start(processClass, "", uid, gid, gids, 
-                debugFlags, zygoteArgs);
-    }
-
-    private static void invokeStaticMain(String className) {
-        Class cl;
-        Object args[] = new Object[1];
-
-        args[0] = new String[0];     //this is argv
-   
+                                  int debugFlags, int targetSdkVersion,
+                                  String[] zygoteArgs) {
         try {
-            cl = Class.forName(className);
-            cl.getMethod("main", new Class[] { String[].class })
-                    .invoke(null, args);            
-        } catch (Exception ex) {
-            // can be: ClassNotFoundException,
-            // NoSuchMethodException, SecurityException,
-            // IllegalAccessException, IllegalArgumentException
-            // InvocationTargetException
-            // or uncaught exception from main()
-
-            Log.e(LOG_TAG, "Exception invoking static main on " 
-                    + className, ex);
-
-            throw new RuntimeException(ex);
+            return startViaZygote(processClass, niceName, uid, gid, gids,
+                    debugFlags, targetSdkVersion, zygoteArgs);
+        } catch (ZygoteStartFailedEx ex) {
+            Log.e(LOG_TAG,
+                    "Starting VM process through Zygote failed");
+            throw new RuntimeException(
+                    "Starting VM process through Zygote failed", ex);
         }
-
     }
 
     /** retry interval for opening a zygote socket */
@@ -506,7 +446,8 @@
      * @param gid a POSIX gid that the new process shuold setgid() to
      * @param gids null-ok; a list of supplementary group IDs that the
      * new process should setgroup() to.
-     * @param enableDebugger True if debugging should be enabled for this process.
+     * @param debugFlags Additional flags.
+     * @param targetSdkVersion The target SDK version for the app.
      * @param extraArgs Additional arguments to supply to the zygote process.
      * @return PID
      * @throws ZygoteStartFailedEx if process start failed for any reason
@@ -515,7 +456,7 @@
                                   final String niceName,
                                   final int uid, final int gid,
                                   final int[] gids,
-                                  int debugFlags,
+                                  int debugFlags, int targetSdkVersion,
                                   String[] extraArgs)
                                   throws ZygoteStartFailedEx {
         int pid;
@@ -528,6 +469,9 @@
             argsForZygote.add("--runtime-init");
             argsForZygote.add("--setuid=" + uid);
             argsForZygote.add("--setgid=" + gid);
+            if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
+                argsForZygote.add("--enable-jni-logging");
+            }
             if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
                 argsForZygote.add("--enable-safemode");
             }
@@ -540,6 +484,7 @@
             if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
                 argsForZygote.add("--enable-assert");
             }
+            argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
 
             //TODO optionally enable debuger
             //argsForZygote.add("--enable-debugger");
@@ -739,8 +684,13 @@
      * 
      * @return Returns true if the system can run in multiple processes, else
      * false if everything is running in a single process.
+     *
+     * @deprecated This method always returns true.  Do not use.
      */
-    public static final native boolean supportsProcesses();
+    @Deprecated
+    public static final boolean supportsProcesses() {
+        return true;
+    }
 
     /**
      * Set the out-of-memory badness adjustment for a process.
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index b721665..1af24f4 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -114,7 +114,7 @@
      * @hide
      */
     public static void initServiceCache(Map<String, IBinder> cache) {
-        if (sCache.size() != 0 && Process.supportsProcesses()) {
+        if (sCache.size() != 0) {
             throw new IllegalStateException("setServiceCache may only be called once");
         }
         sCache.putAll(cache);
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index c2dc8ae..9302060 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -655,6 +655,26 @@
                 }
                 return _result;
             }
+
+            /*
+             * Returns the filesystem path of a mounted secure container.
+             */
+            public String getSecureContainerFilesystemPath(String id) throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                String _result;
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(id);
+                    mRemote.transact(Stub.TRANSACTION_getSecureContainerFilesystemPath, _data, _reply, 0);
+                    _reply.readException();
+                    _result = _reply.readString();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+                return _result;
+            }
         }
 
         private static final String DESCRIPTOR = "IMountService";
@@ -719,6 +739,8 @@
 
         static final int TRANSACTION_getVolumeList = IBinder.FIRST_CALL_TRANSACTION + 29;
 
+        static final int TRANSACTION_getSecureContainerFilesystemPath = IBinder.FIRST_CALL_TRANSACTION + 30;
+
         /**
          * Cast an IBinder object into an IMountService interface, generating a
          * proxy if needed.
@@ -1031,6 +1053,15 @@
                     reply.writeParcelableArray(result, 0);
                     return true;
                 }
+                case TRANSACTION_getSecureContainerFilesystemPath: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String id;
+                    id = data.readString();
+                    String path = getSecureContainerFilesystemPath(id);
+                    reply.writeNoException();
+                    reply.writeString(path);
+                    return true;
+                }
             }
             return super.onTransact(code, data, reply, flags);
         }
@@ -1210,4 +1241,6 @@
      * Returns list of all mountable volumes.
      */
     public Parcelable[] getVolumeList() throws RemoteException;
+
+    public String getSecureContainerFilesystemPath(String id) throws RemoteException;
 }
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index 792e4c1..60900e1 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -34,6 +34,8 @@
     private final int mMtpReserveSpace;
     private final boolean mAllowMassStorage;
     private int mStorageId;
+    // maximum file size for the storage, or zero for no limit
+    private final long mMaxFileSize;
 
     // StorageVolume extra for ACTION_MEDIA_REMOVED, ACTION_MEDIA_UNMOUNTED, ACTION_MEDIA_CHECKING,
     // ACTION_MEDIA_NOFS, ACTION_MEDIA_MOUNTED, ACTION_MEDIA_SHARED, ACTION_MEDIA_UNSHARED,
@@ -41,18 +43,20 @@
     public static final String EXTRA_STORAGE_VOLUME = "storage_volume";
 
     public StorageVolume(String path, String description, boolean removable,
-            boolean emulated, int mtpReserveSpace, boolean allowMassStorage) {
+            boolean emulated, int mtpReserveSpace, boolean allowMassStorage, long maxFileSize) {
         mPath = path;
         mDescription = description;
         mRemovable = removable;
         mEmulated = emulated;
         mMtpReserveSpace = mtpReserveSpace;
         mAllowMassStorage = allowMassStorage;
+        mMaxFileSize = maxFileSize;
     }
 
     // for parcelling only
     private StorageVolume(String path, String description, boolean removable,
-            boolean emulated, int mtpReserveSpace, int storageId, boolean allowMassStorage) {
+            boolean emulated, int mtpReserveSpace, int storageId,
+            boolean allowMassStorage, long maxFileSize) {
         mPath = path;
         mDescription = description;
         mRemovable = removable;
@@ -60,6 +64,7 @@
         mMtpReserveSpace = mtpReserveSpace;
         mAllowMassStorage = allowMassStorage;
         mStorageId = storageId;
+        mMaxFileSize = maxFileSize;
     }
 
     /**
@@ -142,6 +147,15 @@
         return mAllowMassStorage;
     }
 
+    /**
+     * Returns maximum file size for the volume, or zero if it is unbounded.
+     *
+     * @return maximum file size
+     */
+    public long getMaxFileSize() {
+        return mMaxFileSize;
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (obj instanceof StorageVolume && mPath != null) {
@@ -171,9 +185,10 @@
             int storageId = in.readInt();
             int mtpReserveSpace = in.readInt();
             int allowMassStorage = in.readInt();
+            long maxFileSize = in.readLong();
             return new StorageVolume(path, description,
-                    removable == 1, emulated == 1,
-                    mtpReserveSpace, storageId, allowMassStorage == 1);
+                    removable == 1, emulated == 1, mtpReserveSpace,
+                    storageId, allowMassStorage == 1, maxFileSize);
         }
 
         public StorageVolume[] newArray(int size) {
@@ -193,5 +208,6 @@
         parcel.writeInt(mStorageId);
         parcel.writeInt(mMtpReserveSpace);
         parcel.writeInt(mAllowMassStorage ? 1 : 0);
+        parcel.writeLong(mMaxFileSize);
     }
 }
diff --git a/core/java/android/pim/EventRecurrence.java b/core/java/android/pim/EventRecurrence.java
deleted file mode 100644
index cde7dac..0000000
--- a/core/java/android/pim/EventRecurrence.java
+++ /dev/null
@@ -1,918 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.pim;
-
-import android.text.TextUtils;
-import android.text.format.Time;
-import android.util.Log;
-import android.util.TimeFormatException;
-
-import java.util.Calendar;
-import java.util.HashMap;
-
-/**
- * Event recurrence utility functions.
- */
-public class EventRecurrence {
-    private static String TAG = "EventRecur";
-
-    public static final int SECONDLY = 1;
-    public static final int MINUTELY = 2;
-    public static final int HOURLY = 3;
-    public static final int DAILY = 4;
-    public static final int WEEKLY = 5;
-    public static final int MONTHLY = 6;
-    public static final int YEARLY = 7;
-
-    public static final int SU = 0x00010000;
-    public static final int MO = 0x00020000;
-    public static final int TU = 0x00040000;
-    public static final int WE = 0x00080000;
-    public static final int TH = 0x00100000;
-    public static final int FR = 0x00200000;
-    public static final int SA = 0x00400000;
-
-    public Time      startDate;     // set by setStartDate(), not parse()
-
-    public int       freq;          // SECONDLY, MINUTELY, etc.
-    public String    until;
-    public int       count;
-    public int       interval;
-    public int       wkst;          // SU, MO, TU, etc.
-
-    /* lists with zero entries may be null references */
-    public int[]     bysecond;
-    public int       bysecondCount;
-    public int[]     byminute;
-    public int       byminuteCount;
-    public int[]     byhour;
-    public int       byhourCount;
-    public int[]     byday;
-    public int[]     bydayNum;
-    public int       bydayCount;
-    public int[]     bymonthday;
-    public int       bymonthdayCount;
-    public int[]     byyearday;
-    public int       byyeardayCount;
-    public int[]     byweekno;
-    public int       byweeknoCount;
-    public int[]     bymonth;
-    public int       bymonthCount;
-    public int[]     bysetpos;
-    public int       bysetposCount;
-
-    /** maps a part string to a parser object */
-    private static HashMap<String,PartParser> sParsePartMap;
-    static {
-        sParsePartMap = new HashMap<String,PartParser>();
-        sParsePartMap.put("FREQ", new ParseFreq());
-        sParsePartMap.put("UNTIL", new ParseUntil());
-        sParsePartMap.put("COUNT", new ParseCount());
-        sParsePartMap.put("INTERVAL", new ParseInterval());
-        sParsePartMap.put("BYSECOND", new ParseBySecond());
-        sParsePartMap.put("BYMINUTE", new ParseByMinute());
-        sParsePartMap.put("BYHOUR", new ParseByHour());
-        sParsePartMap.put("BYDAY", new ParseByDay());
-        sParsePartMap.put("BYMONTHDAY", new ParseByMonthDay());
-        sParsePartMap.put("BYYEARDAY", new ParseByYearDay());
-        sParsePartMap.put("BYWEEKNO", new ParseByWeekNo());
-        sParsePartMap.put("BYMONTH", new ParseByMonth());
-        sParsePartMap.put("BYSETPOS", new ParseBySetPos());
-        sParsePartMap.put("WKST", new ParseWkst());
-    }
-
-    /* values for bit vector that keeps track of what we have already seen */
-    private static final int PARSED_FREQ = 1 << 0;
-    private static final int PARSED_UNTIL = 1 << 1;
-    private static final int PARSED_COUNT = 1 << 2;
-    private static final int PARSED_INTERVAL = 1 << 3;
-    private static final int PARSED_BYSECOND = 1 << 4;
-    private static final int PARSED_BYMINUTE = 1 << 5;
-    private static final int PARSED_BYHOUR = 1 << 6;
-    private static final int PARSED_BYDAY = 1 << 7;
-    private static final int PARSED_BYMONTHDAY = 1 << 8;
-    private static final int PARSED_BYYEARDAY = 1 << 9;
-    private static final int PARSED_BYWEEKNO = 1 << 10;
-    private static final int PARSED_BYMONTH = 1 << 11;
-    private static final int PARSED_BYSETPOS = 1 << 12;
-    private static final int PARSED_WKST = 1 << 13;
-
-    /** maps a FREQ value to an integer constant */
-    private static final HashMap<String,Integer> sParseFreqMap = new HashMap<String,Integer>();
-    static {
-        sParseFreqMap.put("SECONDLY", SECONDLY);
-        sParseFreqMap.put("MINUTELY", MINUTELY);
-        sParseFreqMap.put("HOURLY", HOURLY);
-        sParseFreqMap.put("DAILY", DAILY);
-        sParseFreqMap.put("WEEKLY", WEEKLY);
-        sParseFreqMap.put("MONTHLY", MONTHLY);
-        sParseFreqMap.put("YEARLY", YEARLY);
-    }
-
-    /** maps a two-character weekday string to an integer constant */
-    private static final HashMap<String,Integer> sParseWeekdayMap = new HashMap<String,Integer>();
-    static {
-        sParseWeekdayMap.put("SU", SU);
-        sParseWeekdayMap.put("MO", MO);
-        sParseWeekdayMap.put("TU", TU);
-        sParseWeekdayMap.put("WE", WE);
-        sParseWeekdayMap.put("TH", TH);
-        sParseWeekdayMap.put("FR", FR);
-        sParseWeekdayMap.put("SA", SA);
-    }
-
-    /** If set, allow lower-case recurrence rule strings.  Minor performance impact. */
-    private static final boolean ALLOW_LOWER_CASE = false;
-
-    /** If set, validate the value of UNTIL parts.  Minor performance impact. */
-    private static final boolean VALIDATE_UNTIL = false;
-
-    /** If set, require that only one of {UNTIL,COUNT} is present.  Breaks compat w/ old parser. */
-    private static final boolean ONLY_ONE_UNTIL_COUNT = false;
-
-
-    /**
-     * Thrown when a recurrence string provided can not be parsed according
-     * to RFC2445.
-     */
-    public static class InvalidFormatException extends RuntimeException {
-        InvalidFormatException(String s) {
-            super(s);
-        }
-    }
-
-    /**
-     * Parse an iCalendar/RFC2445 recur type according to Section 4.3.10.  The string is
-     * parsed twice, by the old and new parsers, and the results are compared.
-     * <p>
-     * TODO: this will go away, and what is now parse2() will simply become parse().
-     */
-    public void parse(String recur) {
-        InvalidFormatException newExcep = null;
-        try {
-            parse2(recur);
-        } catch (InvalidFormatException ife) {
-            newExcep = ife;
-        }
-
-        boolean oldThrew = false;
-        try {
-            EventRecurrence check = new EventRecurrence();
-            check.parseNative(recur);
-            if (newExcep == null) {
-                // Neither threw, check to see if results match.
-                if (!equals(check)) {
-                    throw new InvalidFormatException("Recurrence rule parse does not match [" +
-                            recur + "]");
-                }
-            }
-        } catch (InvalidFormatException ife) {
-            oldThrew = true;
-            if (newExcep == null) {
-                // Old threw, but new didn't.  Log a warning, but don't throw.
-                Log.d(TAG, "NOTE: old parser rejected [" + recur + "]: " + ife.getMessage());
-            }
-        }
-
-        if (newExcep != null) {
-            if (!oldThrew) {
-                // New threw, but old didn't.  Log a warning and throw the exception.
-                Log.d(TAG, "NOTE: new parser rejected [" + recur + "]: " + newExcep.getMessage());
-            }
-            throw newExcep;
-        }
-    }
-
-    native void parseNative(String recur);
-
-    public void setStartDate(Time date) {
-        startDate = date;
-    }
-
-    /**
-     * Converts one of the Calendar.SUNDAY constants to the SU, MO, etc.
-     * constants.  btw, I think we should switch to those here too, to
-     * get rid of this function, if possible.
-     */
-    public static int calendarDay2Day(int day)
-    {
-        switch (day)
-        {
-            case Calendar.SUNDAY:
-                return SU;
-            case Calendar.MONDAY:
-                return MO;
-            case Calendar.TUESDAY:
-                return TU;
-            case Calendar.WEDNESDAY:
-                return WE;
-            case Calendar.THURSDAY:
-                return TH;
-            case Calendar.FRIDAY:
-                return FR;
-            case Calendar.SATURDAY:
-                return SA;
-            default:
-                throw new RuntimeException("bad day of week: " + day);
-        }
-    }
-
-    public static int timeDay2Day(int day)
-    {
-        switch (day)
-        {
-            case Time.SUNDAY:
-                return SU;
-            case Time.MONDAY:
-                return MO;
-            case Time.TUESDAY:
-                return TU;
-            case Time.WEDNESDAY:
-                return WE;
-            case Time.THURSDAY:
-                return TH;
-            case Time.FRIDAY:
-                return FR;
-            case Time.SATURDAY:
-                return SA;
-            default:
-                throw new RuntimeException("bad day of week: " + day);
-        }
-    }
-    public static int day2TimeDay(int day)
-    {
-        switch (day)
-        {
-            case SU:
-                return Time.SUNDAY;
-            case MO:
-                return Time.MONDAY;
-            case TU:
-                return Time.TUESDAY;
-            case WE:
-                return Time.WEDNESDAY;
-            case TH:
-                return Time.THURSDAY;
-            case FR:
-                return Time.FRIDAY;
-            case SA:
-                return Time.SATURDAY;
-            default:
-                throw new RuntimeException("bad day of week: " + day);
-        }
-    }
-
-    /**
-     * Converts one of the SU, MO, etc. constants to the Calendar.SUNDAY
-     * constants.  btw, I think we should switch to those here too, to
-     * get rid of this function, if possible.
-     */
-    public static int day2CalendarDay(int day)
-    {
-        switch (day)
-        {
-            case SU:
-                return Calendar.SUNDAY;
-            case MO:
-                return Calendar.MONDAY;
-            case TU:
-                return Calendar.TUESDAY;
-            case WE:
-                return Calendar.WEDNESDAY;
-            case TH:
-                return Calendar.THURSDAY;
-            case FR:
-                return Calendar.FRIDAY;
-            case SA:
-                return Calendar.SATURDAY;
-            default:
-                throw new RuntimeException("bad day of week: " + day);
-        }
-    }
-
-    /**
-     * Converts one of the internal day constants (SU, MO, etc.) to the
-     * two-letter string representing that constant.
-     *
-     * @param day one the internal constants SU, MO, etc.
-     * @return the two-letter string for the day ("SU", "MO", etc.)
-     *
-     * @throws IllegalArgumentException Thrown if the day argument is not one of
-     * the defined day constants.
-     */
-    private static String day2String(int day) {
-        switch (day) {
-        case SU:
-            return "SU";
-        case MO:
-            return "MO";
-        case TU:
-            return "TU";
-        case WE:
-            return "WE";
-        case TH:
-            return "TH";
-        case FR:
-            return "FR";
-        case SA:
-            return "SA";
-        default:
-            throw new IllegalArgumentException("bad day argument: " + day);
-        }
-    }
-
-    private static void appendNumbers(StringBuilder s, String label,
-                                        int count, int[] values)
-    {
-        if (count > 0) {
-            s.append(label);
-            count--;
-            for (int i=0; i<count; i++) {
-                s.append(values[i]);
-                s.append(",");
-            }
-            s.append(values[count]);
-        }
-    }
-
-    private void appendByDay(StringBuilder s, int i)
-    {
-        int n = this.bydayNum[i];
-        if (n != 0) {
-            s.append(n);
-        }
-
-        String str = day2String(this.byday[i]);
-        s.append(str);
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder s = new StringBuilder();
-
-        s.append("FREQ=");
-        switch (this.freq)
-        {
-            case SECONDLY:
-                s.append("SECONDLY");
-                break;
-            case MINUTELY:
-                s.append("MINUTELY");
-                break;
-            case HOURLY:
-                s.append("HOURLY");
-                break;
-            case DAILY:
-                s.append("DAILY");
-                break;
-            case WEEKLY:
-                s.append("WEEKLY");
-                break;
-            case MONTHLY:
-                s.append("MONTHLY");
-                break;
-            case YEARLY:
-                s.append("YEARLY");
-                break;
-        }
-
-        if (!TextUtils.isEmpty(this.until)) {
-            s.append(";UNTIL=");
-            s.append(until);
-        }
-
-        if (this.count != 0) {
-            s.append(";COUNT=");
-            s.append(this.count);
-        }
-
-        if (this.interval != 0) {
-            s.append(";INTERVAL=");
-            s.append(this.interval);
-        }
-
-        if (this.wkst != 0) {
-            s.append(";WKST=");
-            s.append(day2String(this.wkst));
-        }
-
-        appendNumbers(s, ";BYSECOND=", this.bysecondCount, this.bysecond);
-        appendNumbers(s, ";BYMINUTE=", this.byminuteCount, this.byminute);
-        appendNumbers(s, ";BYSECOND=", this.byhourCount, this.byhour);
-
-        // day
-        int count = this.bydayCount;
-        if (count > 0) {
-            s.append(";BYDAY=");
-            count--;
-            for (int i=0; i<count; i++) {
-                appendByDay(s, i);
-                s.append(",");
-            }
-            appendByDay(s, count);
-        }
-
-        appendNumbers(s, ";BYMONTHDAY=", this.bymonthdayCount, this.bymonthday);
-        appendNumbers(s, ";BYYEARDAY=", this.byyeardayCount, this.byyearday);
-        appendNumbers(s, ";BYWEEKNO=", this.byweeknoCount, this.byweekno);
-        appendNumbers(s, ";BYMONTH=", this.bymonthCount, this.bymonth);
-        appendNumbers(s, ";BYSETPOS=", this.bysetposCount, this.bysetpos);
-
-        return s.toString();
-    }
-
-    public boolean repeatsOnEveryWeekDay() {
-        if (this.freq != WEEKLY) {
-            return false;
-        }
-
-        int count = this.bydayCount;
-        if (count != 5) {
-            return false;
-        }
-
-        for (int i = 0 ; i < count ; i++) {
-            int day = byday[i];
-            if (day == SU || day == SA) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    public boolean repeatsMonthlyOnDayCount() {
-        if (this.freq != MONTHLY) {
-            return false;
-        }
-
-        if (bydayCount != 1 || bymonthdayCount != 0) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Determines whether two integer arrays contain identical elements.
-     * <p>
-     * The native implementation over-allocated the arrays (and may have stuff left over from
-     * a previous run), so we can't just check the arrays -- the separately-maintained count
-     * field also matters.  We assume that a null array will have a count of zero, and that the
-     * array can hold as many elements as the associated count indicates.
-     * <p>
-     * TODO: replace this with Arrays.equals() when the old parser goes away.
-     */
-    private static boolean arraysEqual(int[] array1, int count1, int[] array2, int count2) {
-        if (count1 != count2) {
-            return false;
-        }
-
-        for (int i = 0; i < count1; i++) {
-            if (array1[i] != array2[i])
-                return false;
-        }
-
-        return true;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!(obj instanceof EventRecurrence)) {
-            return false;
-        }
-
-        EventRecurrence er = (EventRecurrence) obj;
-        return  (startDate == null ?
-                        er.startDate == null : Time.compare(startDate, er.startDate) == 0) &&
-                freq == er.freq &&
-                (until == null ? er.until == null : until.equals(er.until)) &&
-                count == er.count &&
-                interval == er.interval &&
-                wkst == er.wkst &&
-                arraysEqual(bysecond, bysecondCount, er.bysecond, er.bysecondCount) &&
-                arraysEqual(byminute, byminuteCount, er.byminute, er.byminuteCount) &&
-                arraysEqual(byhour, byhourCount, er.byhour, er.byhourCount) &&
-                arraysEqual(byday, bydayCount, er.byday, er.bydayCount) &&
-                arraysEqual(bydayNum, bydayCount, er.bydayNum, er.bydayCount) &&
-                arraysEqual(bymonthday, bymonthdayCount, er.bymonthday, er.bymonthdayCount) &&
-                arraysEqual(byyearday, byyeardayCount, er.byyearday, er.byyeardayCount) &&
-                arraysEqual(byweekno, byweeknoCount, er.byweekno, er.byweeknoCount) &&
-                arraysEqual(bymonth, bymonthCount, er.bymonth, er.bymonthCount) &&
-                arraysEqual(bysetpos, bysetposCount, er.bysetpos, er.bysetposCount);
-    }
-
-    @Override public int hashCode() {
-        // We overrode equals, so we must override hashCode().  Nobody seems to need this though.
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Resets parser-modified fields to their initial state.  Does not alter startDate.
-     * <p>
-     * The original parser always set all of the "count" fields, "wkst", and "until",
-     * essentially allowing the same object to be used multiple times by calling parse().
-     * It's unclear whether this behavior was intentional.  For now, be paranoid and
-     * preserve the existing behavior by resetting the fields.
-     * <p>
-     * We don't need to touch the integer arrays; they will either be ignored or
-     * overwritten.  The "startDate" field is not set by the parser, so we ignore it here.
-     */
-    private void resetFields() {
-        until = null;
-        freq = count = interval = bysecondCount = byminuteCount = byhourCount =
-            bydayCount = bymonthdayCount = byyeardayCount = byweeknoCount = bymonthCount =
-            bysetposCount = 0;
-    }
-
-    /**
-     * Parses an rfc2445 recurrence rule string into its component pieces.  Attempting to parse
-     * malformed input will result in an EventRecurrence.InvalidFormatException.
-     *
-     * @param recur The recurrence rule to parse (in un-folded form).
-     */
-    void parse2(String recur) {
-        /*
-         * From RFC 2445 section 4.3.10:
-         *
-         * recur = "FREQ"=freq *(
-         *       ; either UNTIL or COUNT may appear in a 'recur',
-         *       ; but UNTIL and COUNT MUST NOT occur in the same 'recur'
-         *
-         *       ( ";" "UNTIL" "=" enddate ) /
-         *       ( ";" "COUNT" "=" 1*DIGIT ) /
-         *
-         *       ; the rest of these keywords are optional,
-         *       ; but MUST NOT occur more than once
-         *
-         *       ( ";" "INTERVAL" "=" 1*DIGIT )          /
-         *       ( ";" "BYSECOND" "=" byseclist )        /
-         *       ( ";" "BYMINUTE" "=" byminlist )        /
-         *       ( ";" "BYHOUR" "=" byhrlist )           /
-         *       ( ";" "BYDAY" "=" bywdaylist )          /
-         *       ( ";" "BYMONTHDAY" "=" bymodaylist )    /
-         *       ( ";" "BYYEARDAY" "=" byyrdaylist )     /
-         *       ( ";" "BYWEEKNO" "=" bywknolist )       /
-         *       ( ";" "BYMONTH" "=" bymolist )          /
-         *       ( ";" "BYSETPOS" "=" bysplist )         /
-         *       ( ";" "WKST" "=" weekday )              /
-         *       ( ";" x-name "=" text )
-         *       )
-         *
-         * Examples:
-         *   FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU
-         *   FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8
-         *
-         * Strategy:
-         * (1) Split the string at ';' boundaries to get an array of rule "parts".
-         * (2) For each part, find substrings for left/right sides of '=' (name/value).
-         * (3) Call a <name>-specific parsing function to parse the <value> into an
-         *     output field.
-         *
-         * By keeping track of which names we've seen in a bit vector, we can verify the
-         * constraints indicated above (FREQ appears first, none of them appear more than once --
-         * though x-[name] would require special treatment), and we have either UNTIL or COUNT
-         * but not both.
-         *
-         * In general, RFC 2445 property names (e.g. "FREQ") and enumerations ("TU") must
-         * be handled in a case-insensitive fashion, but case may be significant for other
-         * properties.  We don't have any case-sensitive values in RRULE, except possibly
-         * for the custom "X-" properties, but we ignore those anyway.  Thus, we can trivially
-         * convert the entire string to upper case and then use simple comparisons.
-         *
-         * Differences from previous version:
-         * - allows lower-case property and enumeration values [optional]
-         * - enforces that FREQ appears first
-         * - enforces that only one of UNTIL and COUNT may be specified
-         * - allows (but ignores) X-* parts
-         * - improved validation on various values (e.g. UNTIL timestamps)
-         * - error messages are more specific
-         */
-
-        /* TODO: replace with "if (freq != 0) throw" if nothing requires this */
-        resetFields();
-
-        int parseFlags = 0;
-        String[] parts;
-        if (ALLOW_LOWER_CASE) {
-            parts = recur.toUpperCase().split(";");
-        } else {
-            parts = recur.split(";");
-        }
-        for (String part : parts) {
-            int equalIndex = part.indexOf('=');
-            if (equalIndex <= 0) {
-                /* no '=' or no LHS */
-                throw new InvalidFormatException("Missing LHS in " + part);
-            }
-
-            String lhs = part.substring(0, equalIndex);
-            String rhs = part.substring(equalIndex + 1);
-            if (rhs.length() == 0) {
-                throw new InvalidFormatException("Missing RHS in " + part);
-            }
-
-            /*
-             * In lieu of a "switch" statement that allows string arguments, we use a
-             * map from strings to parsing functions.
-             */
-            PartParser parser = sParsePartMap.get(lhs);
-            if (parser == null) {
-                if (lhs.startsWith("X-")) {
-                    //Log.d(TAG, "Ignoring custom part " + lhs);
-                    continue;
-                }
-                throw new InvalidFormatException("Couldn't find parser for " + lhs);
-            } else {
-                int flag = parser.parsePart(rhs, this);
-                if ((parseFlags & flag) != 0) {
-                    throw new InvalidFormatException("Part " + lhs + " was specified twice");
-                }
-                if (parseFlags == 0 && flag != PARSED_FREQ) {
-                    throw new InvalidFormatException("FREQ must be specified first");
-                }
-                parseFlags |= flag;
-            }
-        }
-
-        // If not specified, week starts on Monday.
-        if ((parseFlags & PARSED_WKST) == 0) {
-            wkst = MO;
-        }
-
-        // FREQ is mandatory.
-        if ((parseFlags & PARSED_FREQ) == 0) {
-            throw new InvalidFormatException("Must specify a FREQ value");
-        }
-
-        // Can't have both UNTIL and COUNT.
-        if ((parseFlags & (PARSED_UNTIL | PARSED_COUNT)) == (PARSED_UNTIL | PARSED_COUNT)) {
-            if (ONLY_ONE_UNTIL_COUNT) {
-                throw new InvalidFormatException("Must not specify both UNTIL and COUNT: " + recur);
-            } else {
-                Log.w(TAG, "Warning: rrule has both UNTIL and COUNT: " + recur);
-            }
-        }
-    }
-
-    /**
-     * Base class for the RRULE part parsers.
-     */
-    abstract static class PartParser {
-        /**
-         * Parses a single part.
-         *
-         * @param value The right-hand-side of the part.
-         * @param er The EventRecurrence into which the result is stored.
-         * @return A bit value indicating which part was parsed.
-         */
-        public abstract int parsePart(String value, EventRecurrence er);
-
-        /**
-         * Parses an integer, with range-checking.
-         *
-         * @param str The string to parse.
-         * @param minVal Minimum allowed value.
-         * @param maxVal Maximum allowed value.
-         * @param allowZero Is 0 allowed?
-         * @return The parsed value.
-         */
-        public static int parseIntRange(String str, int minVal, int maxVal, boolean allowZero) {
-            try {
-                if (str.charAt(0) == '+') {
-                    // Integer.parseInt does not allow a leading '+', so skip it manually.
-                    str = str.substring(1);
-                }
-                int val = Integer.parseInt(str);
-                if (val < minVal || val > maxVal || (val == 0 && !allowZero)) {
-                    throw new InvalidFormatException("Integer value out of range: " + str);
-                }
-                return val;
-            } catch (NumberFormatException nfe) {
-                throw new InvalidFormatException("Invalid integer value: " + str);
-            }
-        }
-
-        /**
-         * Parses a comma-separated list of integers, with range-checking.
-         *
-         * @param listStr The string to parse.
-         * @param minVal Minimum allowed value.
-         * @param maxVal Maximum allowed value.
-         * @param allowZero Is 0 allowed?
-         * @return A new array with values, sized to hold the exact number of elements.
-         */
-        public static int[] parseNumberList(String listStr, int minVal, int maxVal,
-                boolean allowZero) {
-            int[] values;
-
-            if (listStr.indexOf(",") < 0) {
-                // Common case: only one entry, skip split() overhead.
-                values = new int[1];
-                values[0] = parseIntRange(listStr, minVal, maxVal, allowZero);
-            } else {
-                String[] valueStrs = listStr.split(",");
-                int len = valueStrs.length;
-                values = new int[len];
-                for (int i = 0; i < len; i++) {
-                    values[i] = parseIntRange(valueStrs[i], minVal, maxVal, allowZero);
-                }
-            }
-            return values;
-        }
-   }
-
-    /** parses FREQ={SECONDLY,MINUTELY,...} */
-    private static class ParseFreq extends PartParser {
-        @Override public int parsePart(String value, EventRecurrence er) {
-            Integer freq = sParseFreqMap.get(value);
-            if (freq == null) {
-                throw new InvalidFormatException("Invalid FREQ value: " + value);
-            }
-            er.freq = freq;
-            return PARSED_FREQ;
-        }
-    }
-    /** parses UNTIL=enddate, e.g. "19970829T021400" */
-    private static class ParseUntil extends PartParser {
-        @Override public int parsePart(String value, EventRecurrence er) {
-            if (VALIDATE_UNTIL) {
-                try {
-                    // Parse the time to validate it.  The result isn't retained.
-                    Time until = new Time();
-                    until.parse(value);
-                } catch (TimeFormatException tfe) {
-                    throw new InvalidFormatException("Invalid UNTIL value: " + value);
-                }
-            }
-            er.until = value;
-            return PARSED_UNTIL;
-        }
-    }
-    /** parses COUNT=[non-negative-integer] */
-    private static class ParseCount extends PartParser {
-        @Override public int parsePart(String value, EventRecurrence er) {
-            er.count = parseIntRange(value, 0, Integer.MAX_VALUE, true);
-            return PARSED_COUNT;
-        }
-    }
-    /** parses INTERVAL=[non-negative-integer] */
-    private static class ParseInterval extends PartParser {
-        @Override public int parsePart(String value, EventRecurrence er) {
-            er.interval = parseIntRange(value, 1, Integer.MAX_VALUE, false);
-            return PARSED_INTERVAL;
-        }
-    }
-    /** parses BYSECOND=byseclist */
-    private static class ParseBySecond extends PartParser {
-        @Override public int parsePart(String value, EventRecurrence er) {
-            int[] bysecond = parseNumberList(value, 0, 59, true);
-            er.bysecond = bysecond;
-            er.bysecondCount = bysecond.length;
-            return PARSED_BYSECOND;
-        }
-    }
-    /** parses BYMINUTE=byminlist */
-    private static class ParseByMinute extends PartParser {
-        @Override public int parsePart(String value, EventRecurrence er) {
-            int[] byminute = parseNumberList(value, 0, 59, true);
-            er.byminute = byminute;
-            er.byminuteCount = byminute.length;
-            return PARSED_BYMINUTE;
-        }
-    }
-    /** parses BYHOUR=byhrlist */
-    private static class ParseByHour extends PartParser {
-        @Override public int parsePart(String value, EventRecurrence er) {
-            int[] byhour = parseNumberList(value, 0, 23, true);
-            er.byhour = byhour;
-            er.byhourCount = byhour.length;
-            return PARSED_BYHOUR;
-        }
-    }
-    /** parses BYDAY=bywdaylist, e.g. "1SU,-1SU" */
-    private static class ParseByDay extends PartParser {
-        @Override public int parsePart(String value, EventRecurrence er) {
-            int[] byday;
-            int[] bydayNum;
-            int bydayCount;
-
-            if (value.indexOf(",") < 0) {
-                /* only one entry, skip split() overhead */
-                bydayCount = 1;
-                byday = new int[1];
-                bydayNum = new int[1];
-                parseWday(value, byday, bydayNum, 0);
-            } else {
-                String[] wdays = value.split(",");
-                int len = wdays.length;
-                bydayCount = len;
-                byday = new int[len];
-                bydayNum = new int[len];
-                for (int i = 0; i < len; i++) {
-                    parseWday(wdays[i], byday, bydayNum, i);
-                }
-            }
-            er.byday = byday;
-            er.bydayNum = bydayNum;
-            er.bydayCount = bydayCount;
-            return PARSED_BYDAY;
-        }
-
-        /** parses [int]weekday, putting the pieces into parallel array entries */
-        private static void parseWday(String str, int[] byday, int[] bydayNum, int index) {
-            int wdayStrStart = str.length() - 2;
-            String wdayStr;
-
-            if (wdayStrStart > 0) {
-                /* number is included; parse it out and advance to weekday */
-                String numPart = str.substring(0, wdayStrStart);
-                int num = parseIntRange(numPart, -53, 53, false);
-                bydayNum[index] = num;
-                wdayStr = str.substring(wdayStrStart);
-            } else {
-                /* just the weekday string */
-                wdayStr = str;
-            }
-            Integer wday = sParseWeekdayMap.get(wdayStr);
-            if (wday == null) {
-                throw new InvalidFormatException("Invalid BYDAY value: " + str);
-            }
-            byday[index] = wday;
-        }
-    }
-    /** parses BYMONTHDAY=bymodaylist */
-    private static class ParseByMonthDay extends PartParser {
-        @Override public int parsePart(String value, EventRecurrence er) {
-            int[] bymonthday = parseNumberList(value, -31, 31, false);
-            er.bymonthday = bymonthday;
-            er.bymonthdayCount = bymonthday.length;
-            return PARSED_BYMONTHDAY;
-        }
-    }
-    /** parses BYYEARDAY=byyrdaylist */
-    private static class ParseByYearDay extends PartParser {
-        @Override public int parsePart(String value, EventRecurrence er) {
-            int[] byyearday = parseNumberList(value, -366, 366, false);
-            er.byyearday = byyearday;
-            er.byyeardayCount = byyearday.length;
-            return PARSED_BYYEARDAY;
-        }
-    }
-    /** parses BYWEEKNO=bywknolist */
-    private static class ParseByWeekNo extends PartParser {
-        @Override public int parsePart(String value, EventRecurrence er) {
-            int[] byweekno = parseNumberList(value, -53, 53, false);
-            er.byweekno = byweekno;
-            er.byweeknoCount = byweekno.length;
-            return PARSED_BYWEEKNO;
-        }
-    }
-    /** parses BYMONTH=bymolist */
-    private static class ParseByMonth extends PartParser {
-        @Override public int parsePart(String value, EventRecurrence er) {
-            int[] bymonth = parseNumberList(value, 1, 12, false);
-            er.bymonth = bymonth;
-            er.bymonthCount = bymonth.length;
-            return PARSED_BYMONTH;
-        }
-    }
-    /** parses BYSETPOS=bysplist */
-    private static class ParseBySetPos extends PartParser {
-        @Override public int parsePart(String value, EventRecurrence er) {
-            int[] bysetpos = parseNumberList(value, Integer.MIN_VALUE, Integer.MAX_VALUE, true);
-            er.bysetpos = bysetpos;
-            er.bysetposCount = bysetpos.length;
-            return PARSED_BYSETPOS;
-        }
-    }
-    /** parses WKST={SU,MO,...} */
-    private static class ParseWkst extends PartParser {
-        @Override public int parsePart(String value, EventRecurrence er) {
-            Integer wkst = sParseWeekdayMap.get(value);
-            if (wkst == null) {
-                throw new InvalidFormatException("Invalid WKST value: " + value);
-            }
-            er.wkst = wkst;
-            return PARSED_WKST;
-        }
-    }
-}
diff --git a/core/java/android/pim/ICalendar.java b/core/java/android/pim/ICalendar.java
deleted file mode 100644
index 58c5c63..0000000
--- a/core/java/android/pim/ICalendar.java
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * Copyright (C) 2007 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.pim;
-
-import android.util.Log;
-
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-import java.util.ArrayList;
-
-/**
- * Parses RFC 2445 iCalendar objects.
- */
-public class ICalendar {
-
-    private static final String TAG = "Sync";
-
-    // TODO: keep track of VEVENT, VTODO, VJOURNAL, VFREEBUSY, VTIMEZONE, VALARM
-    // components, by type field or by subclass?  subclass would allow us to
-    // enforce grammars.
-
-    /**
-     * Exception thrown when an iCalendar object has invalid syntax.
-     */
-    public static class FormatException extends Exception {
-        public FormatException() {
-            super();
-        }
-
-        public FormatException(String msg) {
-            super(msg);
-        }
-
-        public FormatException(String msg, Throwable cause) {
-            super(msg, cause);
-        }
-    }
-
-    /**
-     * A component within an iCalendar (VEVENT, VTODO, VJOURNAL, VFEEBUSY,
-     * VTIMEZONE, VALARM).
-     */
-    public static class Component {
-
-        // components
-        private static final String BEGIN = "BEGIN";
-        private static final String END = "END";
-        private static final String NEWLINE = "\n";
-        public static final String VCALENDAR = "VCALENDAR";
-        public static final String VEVENT = "VEVENT";
-        public static final String VTODO = "VTODO";
-        public static final String VJOURNAL = "VJOURNAL";
-        public static final String VFREEBUSY = "VFREEBUSY";
-        public static final String VTIMEZONE = "VTIMEZONE";
-        public static final String VALARM = "VALARM";
-
-        private final String mName;
-        private final Component mParent; // see if we can get rid of this
-        private LinkedList<Component> mChildren = null;
-        private final LinkedHashMap<String, ArrayList<Property>> mPropsMap =
-                new LinkedHashMap<String, ArrayList<Property>>();
-
-        /**
-         * Creates a new component with the provided name.
-         * @param name The name of the component.
-         */
-        public Component(String name, Component parent) {
-            mName = name;
-            mParent = parent;
-        }
-
-        /**
-         * Returns the name of the component.
-         * @return The name of the component.
-         */
-        public String getName() {
-            return mName;
-        }
-
-        /**
-         * Returns the parent of this component.
-         * @return The parent of this component.
-         */
-        public Component getParent() {
-            return mParent;
-        }
-
-        /**
-         * Helper that lazily gets/creates the list of children.
-         * @return The list of children.
-         */
-        protected LinkedList<Component> getOrCreateChildren() {
-            if (mChildren == null) {
-                mChildren = new LinkedList<Component>();
-            }
-            return mChildren;
-        }
-
-        /**
-         * Adds a child component to this component.
-         * @param child The child component.
-         */
-        public void addChild(Component child) {
-            getOrCreateChildren().add(child);
-        }
-
-        /**
-         * Returns a list of the Component children of this component.  May be
-         * null, if there are no children.
-         *
-         * @return A list of the children.
-         */
-        public List<Component> getComponents() {
-            return mChildren;
-        }
-
-        /**
-         * Adds a Property to this component.
-         * @param prop
-         */
-        public void addProperty(Property prop) {
-            String name= prop.getName();
-            ArrayList<Property> props = mPropsMap.get(name);
-            if (props == null) {
-                props = new ArrayList<Property>();
-                mPropsMap.put(name, props);
-            }
-            props.add(prop);
-        }
-
-        /**
-         * Returns a set of the property names within this component.
-         * @return A set of property names within this component.
-         */
-        public Set<String> getPropertyNames() {
-            return mPropsMap.keySet();
-        }
-
-        /**
-         * Returns a list of properties with the specified name.  Returns null
-         * if there are no such properties.
-         * @param name The name of the property that should be returned.
-         * @return A list of properties with the requested name.
-         */
-        public List<Property> getProperties(String name) {
-            return mPropsMap.get(name);
-        }
-
-        /**
-         * Returns the first property with the specified name.  Returns null
-         * if there is no such property.
-         * @param name The name of the property that should be returned.
-         * @return The first property with the specified name.
-         */
-        public Property getFirstProperty(String name) {
-            List<Property> props = mPropsMap.get(name);
-            if (props == null || props.size() == 0) {
-                return null;
-            }
-            return props.get(0);
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder sb = new StringBuilder();
-            toString(sb);
-            sb.append(NEWLINE);
-            return sb.toString();
-        }
-
-        /**
-         * Helper method that appends this component to a StringBuilder.  The
-         * caller is responsible for appending a newline at the end of the
-         * component.
-         */
-        public void toString(StringBuilder sb) {
-            sb.append(BEGIN);
-            sb.append(":");
-            sb.append(mName);
-            sb.append(NEWLINE);
-
-            // append the properties
-            for (String propertyName : getPropertyNames()) {
-                for (Property property : getProperties(propertyName)) {
-                    property.toString(sb);
-                    sb.append(NEWLINE);
-                }
-            }
-
-            // append the sub-components
-            if (mChildren != null) {
-                for (Component component : mChildren) {
-                    component.toString(sb);
-                    sb.append(NEWLINE);
-                }
-            }
-
-            sb.append(END);
-            sb.append(":");
-            sb.append(mName);
-        }
-    }
-
-    /**
-     * A property within an iCalendar component (e.g., DTSTART, DTEND, etc.,
-     * within a VEVENT).
-     */
-    public static class Property {
-        // properties
-        // TODO: do we want to list these here?  the complete list is long.
-        public static final String DTSTART = "DTSTART";
-        public static final String DTEND = "DTEND";
-        public static final String DURATION = "DURATION";
-        public static final String RRULE = "RRULE";
-        public static final String RDATE = "RDATE";
-        public static final String EXRULE = "EXRULE";
-        public static final String EXDATE = "EXDATE";
-        // ... need to add more.
-        
-        private final String mName;
-        private LinkedHashMap<String, ArrayList<Parameter>> mParamsMap =
-                new LinkedHashMap<String, ArrayList<Parameter>>();
-        private String mValue; // TODO: make this final?
-
-        /**
-         * Creates a new property with the provided name.
-         * @param name The name of the property.
-         */
-        public Property(String name) {
-            mName = name;
-        }
-
-        /**
-         * Creates a new property with the provided name and value.
-         * @param name The name of the property.
-         * @param value The value of the property.
-         */
-        public Property(String name, String value) {
-            mName = name;
-            mValue = value;
-        }
-
-        /**
-         * Returns the name of the property.
-         * @return The name of the property.
-         */
-        public String getName() {
-            return mName;
-        }
-
-        /**
-         * Returns the value of this property.
-         * @return The value of this property.
-         */
-        public String getValue() {
-            return mValue;
-        }
-
-        /**
-         * Sets the value of this property.
-         * @param value The desired value for this property.
-         */
-        public void setValue(String value) {
-            mValue = value;
-        }        
-
-        /**
-         * Adds a {@link Parameter} to this property.
-         * @param param The parameter that should be added.
-         */
-        public void addParameter(Parameter param) {
-            ArrayList<Parameter> params = mParamsMap.get(param.name);
-            if (params == null) {
-                params = new ArrayList<Parameter>();
-                mParamsMap.put(param.name, params);
-            }
-            params.add(param);
-        }
-
-        /**
-         * Returns the set of parameter names for this property.
-         * @return The set of parameter names for this property.
-         */
-        public Set<String> getParameterNames() {
-            return mParamsMap.keySet();
-        }
-
-        /**
-         * Returns the list of parameters with the specified name.  May return
-         * null if there are no such parameters.
-         * @param name The name of the parameters that should be returned.
-         * @return The list of parameters with the specified name.
-         */
-        public List<Parameter> getParameters(String name) {
-            return mParamsMap.get(name);
-        }
-
-        /**
-         * Returns the first parameter with the specified name.  May return
-         * nll if there is no such parameter.
-         * @param name The name of the parameter that should be returned.
-         * @return The first parameter with the specified name.
-         */
-        public Parameter getFirstParameter(String name) {
-            ArrayList<Parameter> params = mParamsMap.get(name);
-            if (params == null || params.size() == 0) {
-                return null;
-            }
-            return params.get(0);
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder sb = new StringBuilder();
-            toString(sb);
-            return sb.toString();
-        }
-
-        /**
-         * Helper method that appends this property to a StringBuilder.  The
-         * caller is responsible for appending a newline after this property.
-         */
-        public void toString(StringBuilder sb) {
-            sb.append(mName);
-            Set<String> parameterNames = getParameterNames();
-            for (String parameterName : parameterNames) {
-                for (Parameter param : getParameters(parameterName)) {
-                    sb.append(";");
-                    param.toString(sb);
-                }
-            }
-            sb.append(":");
-            sb.append(mValue);
-        }
-    }
-
-    /**
-     * A parameter defined for an iCalendar property.
-     */
-    // TODO: make this a proper class rather than a struct?
-    public static class Parameter {
-        public String name;
-        public String value;
-
-        /**
-         * Creates a new empty parameter.
-         */
-        public Parameter() {
-        }
-
-        /**
-         * Creates a new parameter with the specified name and value.
-         * @param name The name of the parameter.
-         * @param value The value of the parameter.
-         */
-        public Parameter(String name, String value) {
-            this.name = name;
-            this.value = value;
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder sb = new StringBuilder();
-            toString(sb);
-            return sb.toString();
-        }
-
-        /**
-         * Helper method that appends this parameter to a StringBuilder.
-         */
-        public void toString(StringBuilder sb) {
-            sb.append(name);
-            sb.append("=");
-            sb.append(value);
-        }
-    }
-
-    private static final class ParserState {
-        // public int lineNumber = 0;
-        public String line; // TODO: just point to original text
-        public int index;
-    }
-
-    // use factory method
-    private ICalendar() {
-    }
-
-    // TODO: get rid of this -- handle all of the parsing in one pass through
-    // the text.
-    private static String normalizeText(String text) {
-        // it's supposed to be \r\n, but not everyone does that
-        text = text.replaceAll("\r\n", "\n");
-        text = text.replaceAll("\r", "\n");
-
-        // we deal with line folding, by replacing all "\n " strings
-        // with nothing.  The RFC specifies "\r\n " to be folded, but
-        // we handle "\n " and "\r " too because we can get those.
-        text = text.replaceAll("\n ", "");
-
-        return text;
-    }
-
-    /**
-     * Parses text into an iCalendar component.  Parses into the provided
-     * component, if not null, or parses into a new component.  In the latter
-     * case, expects a BEGIN as the first line.  Returns the provided or newly
-     * created top-level component.
-     */
-    // TODO: use an index into the text, so we can make this a recursive
-    // function?
-    private static Component parseComponentImpl(Component component,
-                                                String text)
-            throws FormatException {
-        Component current = component;
-        ParserState state = new ParserState();
-        state.index = 0;
-
-        // split into lines
-        String[] lines = text.split("\n");
-
-        // each line is of the format:
-        // name *(";" param) ":" value
-        for (String line : lines) {
-            try {
-                current = parseLine(line, state, current);
-                // if the provided component was null, we will return the root
-                // NOTE: in this case, if the first line is not a BEGIN, a
-                // FormatException will get thrown.   
-                if (component == null) {
-                    component = current;
-                }
-            } catch (FormatException fe) {
-                if (false) {
-                    Log.v(TAG, "Cannot parse " + line, fe);
-                }
-                // for now, we ignore the parse error.  Google Calendar seems
-                // to be emitting some misformatted iCalendar objects.
-            }
-            continue;
-        }
-        return component;
-    }
-
-    /**
-     * Parses a line into the provided component.  Creates a new component if
-     * the line is a BEGIN, adding the newly created component to the provided
-     * parent.  Returns whatever component is the current one (to which new
-     * properties will be added) in the parse.
-     */
-    private static Component parseLine(String line, ParserState state,
-                                       Component component)
-            throws FormatException {
-        state.line = line;
-        int len = state.line.length();
-
-        // grab the name
-        char c = 0;
-        for (state.index = 0; state.index < len; ++state.index) {
-            c = line.charAt(state.index);
-            if (c == ';' || c == ':') {
-                break;
-            }
-        }
-        String name = line.substring(0, state.index);
-
-        if (component == null) {
-            if (!Component.BEGIN.equals(name)) {
-                throw new FormatException("Expected BEGIN");
-            }
-        }
-
-        Property property;
-        if (Component.BEGIN.equals(name)) {
-            // start a new component
-            String componentName = extractValue(state);
-            Component child = new Component(componentName, component);
-            if (component != null) {
-                component.addChild(child);
-            }
-            return child;
-        } else if (Component.END.equals(name)) {
-            // finish the current component
-            String componentName = extractValue(state);
-            if (component == null ||
-                    !componentName.equals(component.getName())) {
-                throw new FormatException("Unexpected END " + componentName);
-            }
-            return component.getParent();
-        } else {
-            property = new Property(name);
-        }
-
-        if (c == ';') {
-            Parameter parameter = null;
-            while ((parameter = extractParameter(state)) != null) {
-                property.addParameter(parameter);
-            }
-        }
-        String value = extractValue(state);
-        property.setValue(value);
-        component.addProperty(property);
-        return component;
-    }
-
-    /**
-     * Extracts the value ":..." on the current line.  The first character must
-     * be a ':'.
-     */
-    private static String extractValue(ParserState state)
-            throws FormatException {
-        String line = state.line;
-        if (state.index >= line.length() || line.charAt(state.index) != ':') {
-            throw new FormatException("Expected ':' before end of line in "
-                    + line);
-        }
-        String value = line.substring(state.index + 1);
-        state.index = line.length() - 1;
-        return value;
-    }
-
-    /**
-     * Extracts the next parameter from the line, if any.  If there are no more
-     * parameters, returns null.
-     */
-    private static Parameter extractParameter(ParserState state)
-            throws FormatException {
-        String text = state.line;
-        int len = text.length();
-        Parameter parameter = null;
-        int startIndex = -1;
-        int equalIndex = -1;
-        while (state.index < len) {
-            char c = text.charAt(state.index);
-            if (c == ':') {
-                if (parameter != null) {
-                    if (equalIndex == -1) {
-                        throw new FormatException("Expected '=' within "
-                                + "parameter in " + text);
-                    }
-                    parameter.value = text.substring(equalIndex + 1,
-                                                     state.index);
-                }
-                return parameter; // may be null
-            } else if (c == ';') {
-                if (parameter != null) {
-                    if (equalIndex == -1) {
-                        throw new FormatException("Expected '=' within "
-                                + "parameter in " + text);
-                    }
-                    parameter.value = text.substring(equalIndex + 1,
-                                                     state.index);
-                    return parameter;
-                } else {
-                    parameter = new Parameter();
-                    startIndex = state.index;
-                }
-            } else if (c == '=') {
-                equalIndex = state.index;
-                if ((parameter == null) || (startIndex == -1)) {
-                    throw new FormatException("Expected ';' before '=' in "
-                            + text);
-                }
-                parameter.name = text.substring(startIndex + 1, equalIndex);
-            } else if (c == '"') {
-                if (parameter == null) {
-                    throw new FormatException("Expected parameter before '\"' in " + text);
-                }
-                if (equalIndex == -1) {
-                    throw new FormatException("Expected '=' within parameter in " + text);
-                }
-                if (state.index > equalIndex + 1) {
-                    throw new FormatException("Parameter value cannot contain a '\"' in " + text);
-                }
-                final int endQuote = text.indexOf('"', state.index + 1);
-                if (endQuote < 0) {
-                    throw new FormatException("Expected closing '\"' in " + text);
-                }
-                parameter.value = text.substring(state.index + 1, endQuote);
-                state.index = endQuote + 1;
-                return parameter;
-            }
-            ++state.index;
-        }
-        throw new FormatException("Expected ':' before end of line in " + text);
-    }
-
-    /**
-     * Parses the provided text into an iCalendar object.  The top-level
-     * component must be of type VCALENDAR.
-     * @param text The text to be parsed.
-     * @return The top-level VCALENDAR component.
-     * @throws FormatException Thrown if the text could not be parsed into an
-     * iCalendar VCALENDAR object.
-     */
-    public static Component parseCalendar(String text) throws FormatException {
-        Component calendar = parseComponent(null, text);
-        if (calendar == null || !Component.VCALENDAR.equals(calendar.getName())) {
-            throw new FormatException("Expected " + Component.VCALENDAR);
-        }
-        return calendar;
-    }
-
-    /**
-     * Parses the provided text into an iCalendar event.  The top-level
-     * component must be of type VEVENT.
-     * @param text The text to be parsed.
-     * @return The top-level VEVENT component.
-     * @throws FormatException Thrown if the text could not be parsed into an
-     * iCalendar VEVENT.
-     */
-    public static Component parseEvent(String text) throws FormatException {
-        Component event = parseComponent(null, text);
-        if (event == null || !Component.VEVENT.equals(event.getName())) {
-            throw new FormatException("Expected " + Component.VEVENT);
-        }
-        return event;
-    }
-
-    /**
-     * Parses the provided text into an iCalendar component.
-     * @param text The text to be parsed.
-     * @return The top-level component.
-     * @throws FormatException Thrown if the text could not be parsed into an
-     * iCalendar component.
-     */
-    public static Component parseComponent(String text) throws FormatException {
-        return parseComponent(null, text);
-    }
-
-    /**
-     * Parses the provided text, adding to the provided component.
-     * @param component The component to which the parsed iCalendar data should
-     * be added.
-     * @param text The text to be parsed.
-     * @return The top-level component.
-     * @throws FormatException Thrown if the text could not be parsed as an
-     * iCalendar object.
-     */
-    public static Component parseComponent(Component component, String text)
-        throws FormatException {
-        text = normalizeText(text);
-        return parseComponentImpl(component, text);
-    }
-}
diff --git a/core/java/android/pim/RecurrenceSet.java b/core/java/android/pim/RecurrenceSet.java
deleted file mode 100644
index b7fb320..0000000
--- a/core/java/android/pim/RecurrenceSet.java
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- * Copyright (C) 2007 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.pim;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.provider.CalendarContract;
-import android.text.TextUtils;
-import android.text.format.Time;
-import android.util.Log;
-
-import java.util.List;
-import java.util.regex.Pattern;
-
-/**
- * Basic information about a recurrence, following RFC 2445 Section 4.8.5.
- * Contains the RRULEs, RDATE, EXRULEs, and EXDATE properties.
- */
-public class RecurrenceSet {
-
-    private final static String TAG = "CalendarProvider";
-
-    private final static String RULE_SEPARATOR = "\n";
-    private final static String FOLDING_SEPARATOR = "\n ";
-
-    // TODO: make these final?
-    public EventRecurrence[] rrules = null;
-    public long[] rdates = null;
-    public EventRecurrence[] exrules = null;
-    public long[] exdates = null;
-
-    /**
-     * Creates a new RecurrenceSet from information stored in the
-     * events table in the CalendarProvider.
-     * @param values The values retrieved from the Events table.
-     */
-    public RecurrenceSet(ContentValues values)
-            throws EventRecurrence.InvalidFormatException {
-        String rruleStr = values.getAsString(CalendarContract.Events.RRULE);
-        String rdateStr = values.getAsString(CalendarContract.Events.RDATE);
-        String exruleStr = values.getAsString(CalendarContract.Events.EXRULE);
-        String exdateStr = values.getAsString(CalendarContract.Events.EXDATE);
-        init(rruleStr, rdateStr, exruleStr, exdateStr);
-    }
-
-    /**
-     * Creates a new RecurrenceSet from information stored in a database
-     * {@link Cursor} pointing to the events table in the
-     * CalendarProvider.  The cursor must contain the RRULE, RDATE, EXRULE,
-     * and EXDATE columns.
-     *
-     * @param cursor The cursor containing the RRULE, RDATE, EXRULE, and EXDATE
-     * columns.
-     */
-    public RecurrenceSet(Cursor cursor)
-            throws EventRecurrence.InvalidFormatException {
-        int rruleColumn = cursor.getColumnIndex(CalendarContract.Events.RRULE);
-        int rdateColumn = cursor.getColumnIndex(CalendarContract.Events.RDATE);
-        int exruleColumn = cursor.getColumnIndex(CalendarContract.Events.EXRULE);
-        int exdateColumn = cursor.getColumnIndex(CalendarContract.Events.EXDATE);
-        String rruleStr = cursor.getString(rruleColumn);
-        String rdateStr = cursor.getString(rdateColumn);
-        String exruleStr = cursor.getString(exruleColumn);
-        String exdateStr = cursor.getString(exdateColumn);
-        init(rruleStr, rdateStr, exruleStr, exdateStr);
-    }
-
-    public RecurrenceSet(String rruleStr, String rdateStr,
-                  String exruleStr, String exdateStr)
-            throws EventRecurrence.InvalidFormatException {
-        init(rruleStr, rdateStr, exruleStr, exdateStr);
-    }
-
-    private void init(String rruleStr, String rdateStr,
-                      String exruleStr, String exdateStr)
-            throws EventRecurrence.InvalidFormatException {
-        if (!TextUtils.isEmpty(rruleStr) || !TextUtils.isEmpty(rdateStr)) {
-
-            if (!TextUtils.isEmpty(rruleStr)) {
-                String[] rruleStrs = rruleStr.split(RULE_SEPARATOR);
-                rrules = new EventRecurrence[rruleStrs.length];
-                for (int i = 0; i < rruleStrs.length; ++i) {
-                    EventRecurrence rrule = new EventRecurrence();
-                    rrule.parse(rruleStrs[i]);
-                    rrules[i] = rrule;
-                }
-            }
-
-            if (!TextUtils.isEmpty(rdateStr)) {
-                rdates = parseRecurrenceDates(rdateStr);
-            }
-
-            if (!TextUtils.isEmpty(exruleStr)) {
-                String[] exruleStrs = exruleStr.split(RULE_SEPARATOR);
-                exrules = new EventRecurrence[exruleStrs.length];
-                for (int i = 0; i < exruleStrs.length; ++i) {
-                    EventRecurrence exrule = new EventRecurrence();
-                    exrule.parse(exruleStr);
-                    exrules[i] = exrule;
-                }
-            }
-
-            if (!TextUtils.isEmpty(exdateStr)) {
-                exdates = parseRecurrenceDates(exdateStr);
-            }
-        }
-    }
-
-    /**
-     * Returns whether or not a recurrence is defined in this RecurrenceSet.
-     * @return Whether or not a recurrence is defined in this RecurrenceSet.
-     */
-    public boolean hasRecurrence() {
-        return (rrules != null || rdates != null);
-    }
-
-    /**
-     * Parses the provided RDATE or EXDATE string into an array of longs
-     * representing each date/time in the recurrence.
-     * @param recurrence The recurrence to be parsed.
-     * @return The list of date/times.
-     */
-    public static long[] parseRecurrenceDates(String recurrence) {
-        // TODO: use "local" time as the default.  will need to handle times
-        // that end in "z" (UTC time) explicitly at that point.
-        String tz = Time.TIMEZONE_UTC;
-        int tzidx = recurrence.indexOf(";");
-        if (tzidx != -1) {
-            tz = recurrence.substring(0, tzidx);
-            recurrence = recurrence.substring(tzidx + 1);
-        }
-        Time time = new Time(tz);
-        String[] rawDates = recurrence.split(",");
-        int n = rawDates.length;
-        long[] dates = new long[n];
-        for (int i = 0; i<n; ++i) {
-            // The timezone is updated to UTC if the time string specified 'Z'.
-            time.parse(rawDates[i]);
-            dates[i] = time.toMillis(false /* use isDst */);
-            time.timezone = tz;
-        }
-        return dates;
-    }
-
-    /**
-     * Populates the database map of values with the appropriate RRULE, RDATE,
-     * EXRULE, and EXDATE values extracted from the parsed iCalendar component.
-     * @param component The iCalendar component containing the desired
-     * recurrence specification.
-     * @param values The db values that should be updated.
-     * @return true if the component contained the necessary information
-     * to specify a recurrence.  The required fields are DTSTART,
-     * one of DTEND/DURATION, and one of RRULE/RDATE.  Returns false if
-     * there was an error, including if the date is out of range.
-     */
-    public static boolean populateContentValues(ICalendar.Component component,
-            ContentValues values) {
-        ICalendar.Property dtstartProperty =
-                component.getFirstProperty("DTSTART");
-        String dtstart = dtstartProperty.getValue();
-        ICalendar.Parameter tzidParam =
-                dtstartProperty.getFirstParameter("TZID");
-        // NOTE: the timezone may be null, if this is a floating time.
-        String tzid = tzidParam == null ? null : tzidParam.value;
-        Time start = new Time(tzidParam == null ? Time.TIMEZONE_UTC : tzid);
-        boolean inUtc = start.parse(dtstart);
-        boolean allDay = start.allDay;
-
-        // We force TimeZone to UTC for "all day recurring events" as the server is sending no
-        // TimeZone in DTSTART for them
-        if (inUtc || allDay) {
-            tzid = Time.TIMEZONE_UTC;
-        }
-                
-        String duration = computeDuration(start, component);
-        String rrule = flattenProperties(component, "RRULE");
-        String rdate = extractDates(component.getFirstProperty("RDATE"));
-        String exrule = flattenProperties(component, "EXRULE");
-        String exdate = extractDates(component.getFirstProperty("EXDATE"));
-
-        if ((TextUtils.isEmpty(dtstart))||
-                (TextUtils.isEmpty(duration))||
-                ((TextUtils.isEmpty(rrule))&&
-                        (TextUtils.isEmpty(rdate)))) {
-                if (false) {
-                    Log.d(TAG, "Recurrence missing DTSTART, DTEND/DURATION, "
-                                + "or RRULE/RDATE: "
-                                + component.toString());
-                }
-                return false;
-        }
-        
-        if (allDay) {
-            start.timezone = Time.TIMEZONE_UTC;
-        }
-        long millis = start.toMillis(false /* use isDst */);
-        values.put(CalendarContract.Events.DTSTART, millis);
-        if (millis == -1) {
-            if (false) {
-                Log.d(TAG, "DTSTART is out of range: " + component.toString());
-            }
-            return false;
-        }
-        
-        values.put(CalendarContract.Events.RRULE, rrule);
-        values.put(CalendarContract.Events.RDATE, rdate);
-        values.put(CalendarContract.Events.EXRULE, exrule);
-        values.put(CalendarContract.Events.EXDATE, exdate);
-        values.put(CalendarContract.Events.EVENT_TIMEZONE, tzid);
-        values.put(CalendarContract.Events.DURATION, duration);
-        values.put(CalendarContract.Events.ALL_DAY, allDay ? 1 : 0);
-        return true;
-    }
-
-    // This can be removed when the old CalendarSyncAdapter is removed.
-    public static boolean populateComponent(Cursor cursor,
-                                            ICalendar.Component component) {
-        
-        int dtstartColumn = cursor.getColumnIndex(CalendarContract.Events.DTSTART);
-        int durationColumn = cursor.getColumnIndex(CalendarContract.Events.DURATION);
-        int tzidColumn = cursor.getColumnIndex(CalendarContract.Events.EVENT_TIMEZONE);
-        int rruleColumn = cursor.getColumnIndex(CalendarContract.Events.RRULE);
-        int rdateColumn = cursor.getColumnIndex(CalendarContract.Events.RDATE);
-        int exruleColumn = cursor.getColumnIndex(CalendarContract.Events.EXRULE);
-        int exdateColumn = cursor.getColumnIndex(CalendarContract.Events.EXDATE);
-        int allDayColumn = cursor.getColumnIndex(CalendarContract.Events.ALL_DAY);
-
-
-        long dtstart = -1;
-        if (!cursor.isNull(dtstartColumn)) {
-            dtstart = cursor.getLong(dtstartColumn);
-        }
-        String duration = cursor.getString(durationColumn);
-        String tzid = cursor.getString(tzidColumn);
-        String rruleStr = cursor.getString(rruleColumn);
-        String rdateStr = cursor.getString(rdateColumn);
-        String exruleStr = cursor.getString(exruleColumn);
-        String exdateStr = cursor.getString(exdateColumn);
-        boolean allDay = cursor.getInt(allDayColumn) == 1;
-
-        if ((dtstart == -1) ||
-            (TextUtils.isEmpty(duration))||
-            ((TextUtils.isEmpty(rruleStr))&&
-                (TextUtils.isEmpty(rdateStr)))) {
-                // no recurrence.
-                return false;
-        }
-
-        ICalendar.Property dtstartProp = new ICalendar.Property("DTSTART");
-        Time dtstartTime = null;
-        if (!TextUtils.isEmpty(tzid)) {
-            if (!allDay) {
-                dtstartProp.addParameter(new ICalendar.Parameter("TZID", tzid));
-            }
-            dtstartTime = new Time(tzid);
-        } else {
-            // use the "floating" timezone
-            dtstartTime = new Time(Time.TIMEZONE_UTC);
-        }
-        
-        dtstartTime.set(dtstart);
-        // make sure the time is printed just as a date, if all day.
-        // TODO: android.pim.Time really should take care of this for us.
-        if (allDay) {
-            dtstartProp.addParameter(new ICalendar.Parameter("VALUE", "DATE"));
-            dtstartTime.allDay = true;
-            dtstartTime.hour = 0;
-            dtstartTime.minute = 0;
-            dtstartTime.second = 0;
-        }
-
-        dtstartProp.setValue(dtstartTime.format2445());
-        component.addProperty(dtstartProp);
-        ICalendar.Property durationProp = new ICalendar.Property("DURATION");
-        durationProp.setValue(duration);
-        component.addProperty(durationProp);
-
-        addPropertiesForRuleStr(component, "RRULE", rruleStr);
-        addPropertyForDateStr(component, "RDATE", rdateStr);
-        addPropertiesForRuleStr(component, "EXRULE", exruleStr);
-        addPropertyForDateStr(component, "EXDATE", exdateStr);
-        return true;
-    }
-
-public static boolean populateComponent(ContentValues values,
-                                            ICalendar.Component component) {
-        long dtstart = -1;
-        if (values.containsKey(CalendarContract.Events.DTSTART)) {
-            dtstart = values.getAsLong(CalendarContract.Events.DTSTART);
-        }
-        String duration = values.getAsString(CalendarContract.Events.DURATION);
-        String tzid = values.getAsString(CalendarContract.Events.EVENT_TIMEZONE);
-        String rruleStr = values.getAsString(CalendarContract.Events.RRULE);
-        String rdateStr = values.getAsString(CalendarContract.Events.RDATE);
-        String exruleStr = values.getAsString(CalendarContract.Events.EXRULE);
-        String exdateStr = values.getAsString(CalendarContract.Events.EXDATE);
-        Integer allDayInteger = values.getAsInteger(CalendarContract.Events.ALL_DAY);
-        boolean allDay = (null != allDayInteger) ? (allDayInteger == 1) : false;
-
-        if ((dtstart == -1) ||
-            (TextUtils.isEmpty(duration))||
-            ((TextUtils.isEmpty(rruleStr))&&
-                (TextUtils.isEmpty(rdateStr)))) {
-                // no recurrence.
-                return false;
-        }
-
-        ICalendar.Property dtstartProp = new ICalendar.Property("DTSTART");
-        Time dtstartTime = null;
-        if (!TextUtils.isEmpty(tzid)) {
-            if (!allDay) {
-                dtstartProp.addParameter(new ICalendar.Parameter("TZID", tzid));
-            }
-            dtstartTime = new Time(tzid);
-        } else {
-            // use the "floating" timezone
-            dtstartTime = new Time(Time.TIMEZONE_UTC);
-        }
-
-        dtstartTime.set(dtstart);
-        // make sure the time is printed just as a date, if all day.
-        // TODO: android.pim.Time really should take care of this for us.
-        if (allDay) {
-            dtstartProp.addParameter(new ICalendar.Parameter("VALUE", "DATE"));
-            dtstartTime.allDay = true;
-            dtstartTime.hour = 0;
-            dtstartTime.minute = 0;
-            dtstartTime.second = 0;
-        }
-
-        dtstartProp.setValue(dtstartTime.format2445());
-        component.addProperty(dtstartProp);
-        ICalendar.Property durationProp = new ICalendar.Property("DURATION");
-        durationProp.setValue(duration);
-        component.addProperty(durationProp);
-
-        addPropertiesForRuleStr(component, "RRULE", rruleStr);
-        addPropertyForDateStr(component, "RDATE", rdateStr);
-        addPropertiesForRuleStr(component, "EXRULE", exruleStr);
-        addPropertyForDateStr(component, "EXDATE", exdateStr);
-        return true;
-    }
-
-    private static void addPropertiesForRuleStr(ICalendar.Component component,
-                                                String propertyName,
-                                                String ruleStr) {
-        if (TextUtils.isEmpty(ruleStr)) {
-            return;
-        }
-        String[] rrules = getRuleStrings(ruleStr);
-        for (String rrule : rrules) {
-            ICalendar.Property prop = new ICalendar.Property(propertyName);
-            prop.setValue(rrule);
-            component.addProperty(prop);
-        }
-    }
-
-    private static String[] getRuleStrings(String ruleStr) {
-        if (null == ruleStr) {
-            return new String[0];
-        }
-        String unfoldedRuleStr = unfold(ruleStr);
-        String[] split = unfoldedRuleStr.split(RULE_SEPARATOR);
-        int count = split.length;
-        for (int n = 0; n < count; n++) {
-            split[n] = fold(split[n]);
-        }
-        return split;
-    }
-
-
-    private static final Pattern IGNORABLE_ICAL_WHITESPACE_RE =
-            Pattern.compile("(?:\\r\\n?|\\n)[ \t]");
-
-    private static final Pattern FOLD_RE = Pattern.compile(".{75}");
-
-    /**
-    * fold and unfolds ical content lines as per RFC 2445 section 4.1.
-    *
-    * <h3>4.1 Content Lines</h3>
-    *
-    * <p>The iCalendar object is organized into individual lines of text, called
-    * content lines. Content lines are delimited by a line break, which is a CRLF
-    * sequence (US-ASCII decimal 13, followed by US-ASCII decimal 10).
-    *
-    * <p>Lines of text SHOULD NOT be longer than 75 octets, excluding the line
-    * break. Long content lines SHOULD be split into a multiple line
-    * representations using a line "folding" technique. That is, a long line can
-    * be split between any two characters by inserting a CRLF immediately
-    * followed by a single linear white space character (i.e., SPACE, US-ASCII
-    * decimal 32 or HTAB, US-ASCII decimal 9). Any sequence of CRLF followed
-    * immediately by a single linear white space character is ignored (i.e.,
-    * removed) when processing the content type.
-    */
-    public static String fold(String unfoldedIcalContent) {
-        return FOLD_RE.matcher(unfoldedIcalContent).replaceAll("$0\r\n ");
-    }
-
-    public static String unfold(String foldedIcalContent) {
-        return IGNORABLE_ICAL_WHITESPACE_RE.matcher(
-            foldedIcalContent).replaceAll("");
-    }
-
-    private static void addPropertyForDateStr(ICalendar.Component component,
-                                              String propertyName,
-                                              String dateStr) {
-        if (TextUtils.isEmpty(dateStr)) {
-            return;
-        }
-
-        ICalendar.Property prop = new ICalendar.Property(propertyName);
-        String tz = null;
-        int tzidx = dateStr.indexOf(";");
-        if (tzidx != -1) {
-            tz = dateStr.substring(0, tzidx);
-            dateStr = dateStr.substring(tzidx + 1);
-        }
-        if (!TextUtils.isEmpty(tz)) {
-            prop.addParameter(new ICalendar.Parameter("TZID", tz));
-        }
-        prop.setValue(dateStr);
-        component.addProperty(prop);
-    }
-    
-    private static String computeDuration(Time start,
-                                          ICalendar.Component component) {
-        // see if a duration is defined
-        ICalendar.Property durationProperty =
-                component.getFirstProperty("DURATION");
-        if (durationProperty != null) {
-            // just return the duration
-            return durationProperty.getValue();
-        }
-
-        // must compute a duration from the DTEND
-        ICalendar.Property dtendProperty =
-                component.getFirstProperty("DTEND");
-        if (dtendProperty == null) {
-            // no DURATION, no DTEND: 0 second duration
-            return "+P0S";
-        }
-        ICalendar.Parameter endTzidParameter =
-                dtendProperty.getFirstParameter("TZID");
-        String endTzid = (endTzidParameter == null)
-                ? start.timezone : endTzidParameter.value;
-
-        Time end = new Time(endTzid);
-        end.parse(dtendProperty.getValue());
-        long durationMillis = end.toMillis(false /* use isDst */)
-                - start.toMillis(false /* use isDst */);
-        long durationSeconds = (durationMillis / 1000);
-        if (start.allDay && (durationSeconds % 86400) == 0) {
-            return "P" + (durationSeconds / 86400) + "D"; // Server wants this instead of P86400S
-        } else {
-            return "P" + durationSeconds + "S";
-        }
-    }
-
-    private static String flattenProperties(ICalendar.Component component,
-                                            String name) {
-        List<ICalendar.Property> properties = component.getProperties(name);
-        if (properties == null || properties.isEmpty()) {
-            return null;
-        }
-
-        if (properties.size() == 1) {
-            return properties.get(0).getValue();
-        }
-
-        StringBuilder sb = new StringBuilder();
-
-        boolean first = true;
-        for (ICalendar.Property property : component.getProperties(name)) {
-            if (first) {
-                first = false;
-            } else {
-                // TODO: use commas.  our RECUR parsing should handle that
-                // anyway.
-                sb.append(RULE_SEPARATOR);
-            }
-            sb.append(property.getValue());
-        }
-        return sb.toString();
-    }
-
-    private static String extractDates(ICalendar.Property recurrence) {
-        if (recurrence == null) {
-            return null;
-        }
-        ICalendar.Parameter tzidParam =
-                recurrence.getFirstParameter("TZID");
-        if (tzidParam != null) {
-            return tzidParam.value + ";" + recurrence.getValue();
-        }
-        return recurrence.getValue();
-    }
-}
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index 3971045..5b29103 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -17,9 +17,8 @@
 package android.provider;
 
 
-import com.android.internal.util.ArrayUtils;
-
-import android.accounts.Account;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.ContentProviderClient;
@@ -35,13 +34,10 @@
 import android.database.DatabaseUtils;
 import android.net.Uri;
 import android.os.RemoteException;
-import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.text.format.Time;
 import android.util.Log;
 
-import java.util.Arrays;
-
 /**
  * <p>
  * The contract between the calendar provider and applications. Contains
@@ -89,7 +85,6 @@
  * adapters</li>
  * </ul>
  *
- * @hide
  */
 public final class CalendarContract {
     private static final String TAG = "Calendar";
@@ -97,7 +92,9 @@
     /**
      * Broadcast Action: This is the intent that gets fired when an alarm
      * notification needs to be posted for a reminder.
+     *
      */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_EVENT_REMINDER = "android.intent.action.EVENT_REMINDER";
 
     /**
@@ -122,8 +119,7 @@
     /**
      * The content:// style URL for the top-level calendar authority
      */
-    public static final Uri CONTENT_URI =
-        Uri.parse("content://" + AUTHORITY);
+    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
 
     /**
      * An optional insert, update or delete URI parameter that allows the caller
@@ -151,6 +147,11 @@
     public static final String ACCOUNT_TYPE_LOCAL = "LOCAL";
 
     /**
+     * This utility class cannot be instantiated
+     */
+    private CalendarContract() {}
+
+    /**
      * Generic columns for use by sync adapters. The specific functions of these
      * columns are private to the sync adapter. Other clients of the API should
      * not attempt to either read or write this column. These columns are
@@ -389,7 +390,7 @@
      * Class that represents a Calendar Entity. There is one entry per calendar.
      * This is a helper class to make batch operations easier.
      */
-    public static class CalendarEntity implements BaseColumns, SyncColumns, CalendarColumns {
+    public static final class CalendarEntity implements BaseColumns, SyncColumns, CalendarColumns {
 
         /**
          * The default Uri used when creating a new calendar EntityIterator.
@@ -399,6 +400,11 @@
                 "/calendar_entities");
 
         /**
+         * This utility class cannot be instantiated
+         */
+        private CalendarEntity() {}
+
+        /**
          * Creates an entity iterator for the given cursor. It assumes the
          * cursor contains a calendars query.
          *
@@ -571,29 +577,12 @@
      * <li>{@link #CAL_SYNC10}</li>
      * </ul>
      */
-    public static class Calendars implements BaseColumns, SyncColumns, CalendarColumns {
-        private static final String WHERE_DELETE_FOR_ACCOUNT = Calendars.ACCOUNT_NAME + "=?"
-                + " AND "
-                + Calendars.ACCOUNT_TYPE + "=?";
+    public static final class Calendars implements BaseColumns, SyncColumns, CalendarColumns {
 
         /**
-         * Helper function for generating a calendars query. This is blocking
-         * and should not be used on the UI thread. See
-         * {@link ContentResolver#query(Uri, String[], String, String[], String)}
-         * for more details about using the parameters.
-         *
-         * @param cr The ContentResolver to query with
-         * @param projection A list of columns to return
-         * @param selection A formatted selection string
-         * @param selectionArgs arguments to the selection string
-         * @param orderBy How to order the returned rows
-         * @return
+         * This utility class cannot be instantiated
          */
-        public static final Cursor query(ContentResolver cr, String[] projection, String selection,
-                String[] selectionArgs, String orderBy) {
-            return cr.query(CONTENT_URI, projection, selection, selectionArgs,
-                    orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
-        }
+        private Calendars() {}
 
         /**
          * The content:// style URL for accessing Calendars
@@ -622,7 +611,9 @@
          * These fields are only writable by a sync adapter. To modify them the
          * caller must include {@link #CALLER_IS_SYNCADAPTER},
          * {@link #ACCOUNT_NAME}, and {@link #ACCOUNT_TYPE} in the Uri's query
-         * parameters.
+         * parameters. TODO move to provider
+         *
+         * @hide
          */
         public static final String[] SYNC_WRITABLE_COLUMNS = new String[] {
             ACCOUNT_NAME,
@@ -713,7 +704,7 @@
     /**
      * Fields and helpers for interacting with Attendees. Each row of this table
      * represents a single attendee or guest of an event. Calling
-     * {@link #query(ContentResolver, long)} will return a list of attendees for
+     * {@link #query(ContentResolver, long, String[])} will return a list of attendees for
      * the event with the given eventId. Both apps and sync adapters may write
      * to this table. There are six writable fields and all of them except
      * {@link #ATTENDEE_NAME} must be included when inserting a new attendee.
@@ -734,24 +725,25 @@
          */
         @SuppressWarnings("hiding")
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/attendees");
-        /**
-         * the projection used by the attendees query
-         */
-        private static final String[] PROJECTION = new String[] {
-                _ID, ATTENDEE_NAME, ATTENDEE_EMAIL, ATTENDEE_RELATIONSHIP, ATTENDEE_STATUS,};
         private static final String ATTENDEES_WHERE = Attendees.EVENT_ID + "=?";
 
         /**
+         * This utility class cannot be instantiated
+         */
+        private Attendees() {}
+
+        /**
          * Queries all attendees associated with the given event. This is a
          * blocking call and should not be done on the UI thread.
          *
          * @param cr The content resolver to use for the query
          * @param eventId The id of the event to retrieve attendees for
+         * @param projection the columns to return in the cursor
          * @return A Cursor containing all attendees for the event
          */
-        public static final Cursor query(ContentResolver cr, long eventId) {
+        public static final Cursor query(ContentResolver cr, long eventId, String[] projection) {
             String[] attArgs = {Long.toString(eventId)};
-            return cr.query(CONTENT_URI, PROJECTION, ATTENDEES_WHERE, attArgs /* selection args */,
+            return cr.query(CONTENT_URI, projection, ATTENDEES_WHERE, attArgs /* selection args */,
                     null /* sort order */);
         }
     }
@@ -1094,6 +1086,11 @@
                 "/event_entities");
 
         /**
+         * This utility class cannot be instantiated
+         */
+        private EventsEntity() {}
+
+        /**
          * Creates a new iterator for events
          *
          * @param cursor An event query
@@ -1420,37 +1417,6 @@
             CalendarColumns {
 
         /**
-         * Queries all events with the given projection. This is a blocking call
-         * and should not be done on the UI thread.
-         *
-         * @param cr The content resolver to use for the query
-         * @param projection The columns to return
-         * @return A Cursor containing all events in the db
-         */
-        public static final Cursor query(ContentResolver cr, String[] projection) {
-            return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
-        }
-
-        /**
-         * Queries events using the given projection, selection filter, and
-         * ordering. This is a blocking call and should not be done on the UI
-         * thread. For selection and selectionArgs usage see
-         * {@link ContentResolver#query(Uri, String[], String, String[], String)}
-         *
-         * @param cr The content resolver to use for the query
-         * @param projection The columns to return
-         * @param selection Filter on the query as an SQL WHERE statement
-         * @param selectionArgs Args to replace any '?'s in the selection
-         * @param orderBy How to order the rows as an SQL ORDER BY statement
-         * @return A Cursor containing the matching events
-         */
-        public static final Cursor query(ContentResolver cr, String[] projection, String selection,
-                String[] selectionArgs, String orderBy) {
-            return cr.query(CONTENT_URI, projection, selection, null,
-                    orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
-        }
-
-        /**
          * The content:// style URL for interacting with events. Appending an
          * event id using {@link ContentUris#withAppendedId(Uri, long)} will
          * specify a single event.
@@ -1464,10 +1430,15 @@
          * appended event ID.  Deletion of exceptions requires both the original event ID and
          * the exception event ID (see {@link Uri.Builder#appendPath}).
          */
-        public static final Uri EXCEPTION_CONTENT_URI =
+        public static final Uri CONTENT_EXCEPTION_URI =
                 Uri.parse("content://" + AUTHORITY + "/exception");
 
         /**
+         * This utility class cannot be instantiated
+         */
+        private Events() {}
+
+        /**
          * The default sort order for this table
          */
         private static final String DEFAULT_SORT_ORDER = "";
@@ -1475,7 +1446,9 @@
         /**
          * These are columns that should only ever be updated by the provider,
          * either because they are views mapped to another table or because they
-         * are used for provider only functionality.
+         * are used for provider only functionality. TODO move to provider
+         *
+         * @hide
          */
         public static String[] PROVIDER_WRITABLE_COLUMNS = new String[] {
                 ACCOUNT_NAME,
@@ -1505,7 +1478,9 @@
         /**
          * These fields are only writable by a sync adapter. To modify them the
          * caller must include CALLER_IS_SYNCADAPTER, _SYNC_ACCOUNT, and
-         * _SYNC_ACCOUNT_TYPE in the query parameters.
+         * _SYNC_ACCOUNT_TYPE in the query parameters. TODO move to provider.
+         *
+         * @hide
          */
         public static final String[] SYNC_WRITABLE_COLUMNS = new String[] {
             _SYNC_ID,
@@ -1537,6 +1512,11 @@
         };
 
         /**
+         * This utility class cannot be instantiated
+         */
+        private Instances() {}
+
+        /**
          * Performs a query to return all visible instances in the given range.
          * This is a blocking function and should not be done on the UI thread.
          * This will cause an expansion of recurring events to fill this time
@@ -1672,11 +1652,6 @@
         public static final String END_MINUTE = "endMinute";
     }
 
-    /**
-     * CalendarCache stores some settings for calendar including the current
-     * time zone for the instaces. These settings are stored using a key/value
-     * scheme.
-     */
     protected interface CalendarCacheColumns {
         /**
          * The key for the setting. Keys are defined in {@link CalendarCache}.
@@ -1689,7 +1664,12 @@
         public static final String VALUE = "value";
     }
 
-    public static class CalendarCache implements CalendarCacheColumns {
+    /**
+     * CalendarCache stores some settings for calendar including the current
+     * time zone for the instances. These settings are stored using a key/value
+     * scheme. A {@link #KEY} must be specified when updating these values.
+     */
+    public static final class CalendarCache implements CalendarCacheColumns {
         /**
          * The URI to use for retrieving the properties from the Calendar db.
          */
@@ -1697,22 +1677,16 @@
                 Uri.parse("content://" + AUTHORITY + "/properties");
 
         /**
-         * If updating a property, this must be provided as the selection. All
-         * other selections will fail. For queries this field can be omitted to
-         * retrieve all properties or used to query a single property. Valid
-         * keys include {@link #TIMEZONE_KEY_TYPE},
-         * {@link #TIMEZONE_KEY_INSTANCES}, and
-         * {@link #TIMEZONE_KEY_INSTANCES_PREVIOUS}, though the last one can
-         * only be read, not written.
+         * This utility class cannot be instantiated
          */
-        public static final String WHERE = "key=?";
+        private CalendarCache() {}
 
         /**
          * They key for updating the use of auto/home time zones in Calendar.
          * Valid values are {@link #TIMEZONE_TYPE_AUTO} or
          * {@link #TIMEZONE_TYPE_HOME}.
          */
-        public static final String TIMEZONE_KEY_TYPE = "timezoneType";
+        public static final String KEY_TIMEZONE_TYPE = "timezoneType";
 
         /**
          * The key for updating the time zone used by the provider when it
@@ -1720,24 +1694,24 @@
          * type is set to {@link #TIMEZONE_TYPE_HOME}. A valid time zone id
          * should be written to this field.
          */
-        public static final String TIMEZONE_KEY_INSTANCES = "timezoneInstances";
+        public static final String KEY_TIMEZONE_INSTANCES = "timezoneInstances";
 
         /**
          * The key for reading the last time zone set by the user. This should
          * only be read by apps and it will be automatically updated whenever
-         * {@link #TIMEZONE_KEY_INSTANCES} is updated with
+         * {@link #KEY_TIMEZONE_INSTANCES} is updated with
          * {@link #TIMEZONE_TYPE_HOME} set.
          */
-        public static final String TIMEZONE_KEY_INSTANCES_PREVIOUS = "timezoneInstancesPrevious";
+        public static final String KEY_TIMEZONE_INSTANCES_PREVIOUS = "timezoneInstancesPrevious";
 
         /**
-         * The value to write to {@link #TIMEZONE_KEY_TYPE} if the provider
+         * The value to write to {@link #KEY_TIMEZONE_TYPE} if the provider
          * should stay in sync with the device's time zone.
          */
         public static final String TIMEZONE_TYPE_AUTO = "auto";
 
         /**
-         * The value to write to {@link #TIMEZONE_KEY_TYPE} if the provider
+         * The value to write to {@link #KEY_TIMEZONE_TYPE} if the provider
          * should use a fixed time zone set by the user.
          */
         public static final String TIMEZONE_TYPE_HOME = "home";
@@ -1788,6 +1762,11 @@
      * @hide
      */
     public static final class CalendarMetaData implements CalendarMetaDataColumns, BaseColumns {
+
+        /**
+         * This utility class cannot be instantiated
+         */
+        private CalendarMetaData() {}
     }
 
     protected interface EventDaysColumns {
@@ -1810,14 +1789,12 @@
     public static final class EventDays implements EventDaysColumns {
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
                 + "/instances/groupbyday");
+        private static final String SELECTION = "selected=1";
 
         /**
-         * The projection used by the EventDays query.
+         * This utility class cannot be instantiated
          */
-        private static final String[] PROJECTION = {
-                STARTDAY, ENDDAY
-        };
-        private static final String SELECTION = "selected=1";
+        private EventDays() {}
 
         /**
          * Retrieves the days with events for the Julian days starting at
@@ -1829,10 +1806,12 @@
          * @param cr the ContentResolver
          * @param startDay the first Julian day in the range
          * @param numDays the number of days to load (must be at least 1)
+         * @param projection the columns to return in the cursor
          * @return a database cursor containing a list of start and end days for
          *         events
          */
-        public static final Cursor query(ContentResolver cr, int startDay, int numDays) {
+        public static final Cursor query(ContentResolver cr, int startDay, int numDays,
+                String[] projection) {
             if (numDays < 1) {
                 return null;
             }
@@ -1840,7 +1819,7 @@
             Uri.Builder builder = CONTENT_URI.buildUpon();
             ContentUris.appendId(builder, startDay);
             ContentUris.appendId(builder, endDay);
-            return cr.query(builder.build(), PROJECTION, SELECTION,
+            return cr.query(builder.build(), projection, SELECTION,
                     null /* selection args */, STARTDAY);
         }
     }
@@ -1885,7 +1864,7 @@
     /**
      * Fields and helpers for accessing reminders for an event. Each row of this
      * table represents a single reminder for an event. Calling
-     * {@link #query(ContentResolver, long)} will return a list of reminders for
+     * {@link #query(ContentResolver, long, String[])} will return a list of reminders for
      * the event with the given eventId. Both apps and sync adapters may write
      * to this table. There are three writable fields and all of them must be
      * included when inserting a new reminder. They are:
@@ -1897,25 +1876,26 @@
      */
     public static final class Reminders implements BaseColumns, RemindersColumns, EventsColumns {
         private static final String REMINDERS_WHERE = CalendarContract.Reminders.EVENT_ID + "=?";
-        /**
-         * The projection used by the reminders query.
-         */
-        private static final String[] PROJECTION = new String[] {
-                _ID, MINUTES, METHOD,};
         @SuppressWarnings("hiding")
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/reminders");
 
         /**
+         * This utility class cannot be instantiated
+         */
+        private Reminders() {}
+
+        /**
          * Queries all reminders associated with the given event. This is a
          * blocking call and should not be done on the UI thread.
          *
          * @param cr The content resolver to use for the query
          * @param eventId The id of the event to retrieve reminders for
+         * @param projection the columns to return in the cursor
          * @return A Cursor containing all reminders for the event
          */
-        public static final Cursor query(ContentResolver cr, long eventId) {
+        public static final Cursor query(ContentResolver cr, long eventId, String[] projection) {
             String[] remArgs = {Long.toString(eventId)};
-            return cr.query(CONTENT_URI, PROJECTION, REMINDERS_WHERE, remArgs /* selection args */,
+            return cr.query(CONTENT_URI, projection, REMINDERS_WHERE, remArgs /*selection args*/,
                     null /* sort order */);
         }
     }
@@ -1967,17 +1947,28 @@
         public static final String NOTIFY_TIME = "notifyTime";
 
         /**
-         * The state of this alert. It starts out as {@link #SCHEDULED}, then
-         * when the alarm goes off, it changes to {@link #FIRED}, and then when
-         * the user dismisses the alarm it changes to {@link #DISMISSED}. Column
+         * The state of this alert. It starts out as {@link #STATE_SCHEDULED}, then
+         * when the alarm goes off, it changes to {@link #STATE_FIRED}, and then when
+         * the user dismisses the alarm it changes to {@link #STATE_DISMISSED}. Column
          * name.
          * <P>Type: INTEGER</P>
          */
         public static final String STATE = "state";
 
-        public static final int SCHEDULED = 0;
-        public static final int FIRED = 1;
-        public static final int DISMISSED = 2;
+        /**
+         * An alert begins in this state when it is first created.
+         */
+        public static final int STATE_SCHEDULED = 0;
+        /**
+         * After a notification for an alert has been created it should be
+         * updated to fired.
+         */
+        public static final int STATE_FIRED = 1;
+        /**
+         * Once the user has dismissed the notification the alert's state should
+         * be set to dismissed so it is not fired again.
+         */
+        public static final int STATE_DISMISSED = 2;
 
         /**
          * The number of minutes that this alarm precedes the start time. Column
@@ -2017,6 +2008,11 @@
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY +
                 "/calendar_alerts");
 
+        /**
+         * This utility class cannot be instantiated
+         */
+        private CalendarAlerts() {}
+
         private static final String WHERE_ALARM_EXISTS = EVENT_ID + "=?"
                 + " AND " + BEGIN + "=?"
                 + " AND " + ALARM_TIME + "=?";
@@ -2024,7 +2020,7 @@
         private static final String WHERE_FINDNEXTALARMTIME = ALARM_TIME + ">=?";
         private static final String SORT_ORDER_ALARMTIME_ASC = ALARM_TIME + " ASC";
 
-        private static final String WHERE_RESCHEDULE_MISSED_ALARMS = STATE + "=" + SCHEDULED
+        private static final String WHERE_RESCHEDULE_MISSED_ALARMS = STATE + "=" + STATE_SCHEDULED
                 + " AND " + ALARM_TIME + "<?"
                 + " AND " + ALARM_TIME + ">?"
                 + " AND " + END + ">=?";
@@ -2038,10 +2034,11 @@
         public static final Uri CONTENT_URI_BY_INSTANCE =
             Uri.parse("content://" + AUTHORITY + "/calendar_alerts/by_instance");
 
-        private static final boolean DEBUG = true;
+        private static final boolean DEBUG = false;
 
         /**
-         * Helper for inserting an alarm time associated with an event
+         * Helper for inserting an alarm time associated with an event TODO move
+         * to Provider
          *
          * @hide
          */
@@ -2056,51 +2053,32 @@
             values.put(CalendarAlerts.CREATION_TIME, currentTime);
             values.put(CalendarAlerts.RECEIVED_TIME, 0);
             values.put(CalendarAlerts.NOTIFY_TIME, 0);
-            values.put(CalendarAlerts.STATE, SCHEDULED);
+            values.put(CalendarAlerts.STATE, STATE_SCHEDULED);
             values.put(CalendarAlerts.MINUTES, minutes);
             return cr.insert(CONTENT_URI, values);
         }
 
         /**
-         * Queries alerts info using the given projection, selection filter, and
-         * ordering. This is a blocking call and should not be done on the UI
-         * thread. For selection and selectionArgs usage see
-         * {@link ContentResolver#query(Uri, String[], String, String[], String)}
-         *
-         * @param cr The content resolver to use for the query
-         * @param projection The columns to return
-         * @param selection Filter on the query as an SQL WHERE statement
-         * @param selectionArgs Args to replace any '?'s in the selection
-         * @param sortOrder How to order the rows as an SQL ORDER BY statement
-         * @return A Cursor containing the matching alerts
-         */
-        public static final Cursor query(ContentResolver cr, String[] projection,
-                String selection, String[] selectionArgs, String sortOrder) {
-            return cr.query(CONTENT_URI, projection, selection, selectionArgs,
-                    sortOrder);
-        }
-
-        /**
          * Finds the next alarm after (or equal to) the given time and returns
          * the time of that alarm or -1 if no such alarm exists. This is a
-         * blocking call and should not be done on the UI thread.
+         * blocking call and should not be done on the UI thread. TODO move to
+         * provider
          *
          * @param cr the ContentResolver
          * @param millis the time in UTC milliseconds
          * @return the next alarm time greater than or equal to "millis", or -1
          *         if no such alarm exists.
+         * @hide
          */
         public static final long findNextAlarmTime(ContentResolver cr, long millis) {
             String selection = ALARM_TIME + ">=" + millis;
             // TODO: construct an explicit SQL query so that we can add
             // "LIMIT 1" to the end and get just one result.
             String[] projection = new String[] { ALARM_TIME };
-            Cursor cursor = query(cr, projection,
-                    WHERE_FINDNEXTALARMTIME,
-                    new String[] {
+            Cursor cursor = cr.query(CONTENT_URI, projection, WHERE_FINDNEXTALARMTIME,
+                    (new String[] {
                         Long.toString(millis)
-                    },
-                    SORT_ORDER_ALARMTIME_ASC);
+                    }), SORT_ORDER_ALARMTIME_ASC);
             long alarmTime = -1;
             try {
                 if (cursor != null && cursor.moveToFirst()) {
@@ -2116,13 +2094,14 @@
 
         /**
          * Searches the CalendarAlerts table for alarms that should have fired
-         * but have not and then reschedules them.  This method can be called
-         * at boot time to restore alarms that may have been lost due to a
-         * phone reboot.
+         * but have not and then reschedules them. This method can be called at
+         * boot time to restore alarms that may have been lost due to a phone
+         * reboot. TODO move to provider
          *
          * @param cr the ContentResolver
          * @param context the Context
          * @param manager the AlarmManager
+         * @hide
          */
         public static final void rescheduleMissedAlarms(ContentResolver cr,
                 Context context, AlarmManager manager) {
@@ -2136,15 +2115,10 @@
 
             // TODO: construct an explicit SQL query so that we can add
             // "GROUPBY" instead of doing a sort and de-dup
-            Cursor cursor = CalendarAlerts.query(cr,
-                    projection,
-                    WHERE_RESCHEDULE_MISSED_ALARMS,
-                    new String[] {
-                        Long.toString(now),
-                        Long.toString(ancient),
-                        Long.toString(now)
-                    },
-                    SORT_ORDER_ALARMTIME_ASC);
+            Cursor cursor = cr.query(CalendarAlerts.CONTENT_URI, projection,
+                    WHERE_RESCHEDULE_MISSED_ALARMS, (new String[] {
+                            Long.toString(now), Long.toString(ancient), Long.toString(now)
+                    }), SORT_ORDER_ALARMTIME_ASC);
             if (cursor == null) {
                 return;
             }
@@ -2177,12 +2151,13 @@
          * keep scheduled reminders up to date but apps may use this to
          * implement snooze functionality without modifying the reminders table.
          * Scheduled alarms will generate an intent using
-         * {@link #ACTION_EVENT_REMINDER}.
+         * {@link #ACTION_EVENT_REMINDER}. TODO Move to provider
          *
          * @param context A context for referencing system resources
          * @param manager The AlarmManager to use or null
          * @param alarmTime The time to fire the intent in UTC millis since
          *            epoch
+         * @hide
          */
         public static void scheduleAlarm(Context context, AlarmManager manager, long alarmTime) {
             if (DEBUG) {
@@ -2204,31 +2179,28 @@
         }
 
         /**
-         * Searches for an entry in the CalendarAlerts table that matches
-         * the given event id, begin time and alarm time.  If one is found
-         * then this alarm already exists and this method returns true.
+         * Searches for an entry in the CalendarAlerts table that matches the
+         * given event id, begin time and alarm time. If one is found then this
+         * alarm already exists and this method returns true. TODO Move to
+         * provider
          *
          * @param cr the ContentResolver
          * @param eventId the event id to match
          * @param begin the start time of the event in UTC millis
          * @param alarmTime the alarm time of the event in UTC millis
-         * @return true if there is already an alarm for the given event
-         *   with the same start time and alarm time.
+         * @return true if there is already an alarm for the given event with
+         *         the same start time and alarm time.
+         * @hide
          */
         public static final boolean alarmExists(ContentResolver cr, long eventId,
                 long begin, long alarmTime) {
             // TODO: construct an explicit SQL query so that we can add
             // "LIMIT 1" to the end and get just one result.
             String[] projection = new String[] { ALARM_TIME };
-            Cursor cursor = query(cr,
-                    projection,
-                    WHERE_ALARM_EXISTS,
-                    new String[] {
-                        Long.toString(eventId),
-                        Long.toString(begin),
-                        Long.toString(alarmTime)
-                    },
-                    null);
+            Cursor cursor = cr.query(CONTENT_URI, projection, WHERE_ALARM_EXISTS,
+                    (new String[] {
+                            Long.toString(eventId), Long.toString(begin), Long.toString(alarmTime)
+                    }), null);
             boolean found = false;
             try {
                 if (cursor != null && cursor.getCount() > 0) {
@@ -2280,6 +2252,11 @@
         public static final Uri CONTENT_URI =
                 Uri.parse("content://" + AUTHORITY + "/extendedproperties");
 
+        /**
+         * This utility class cannot be instantiated
+         */
+        private ExtendedProperties() {}
+
         // TODO: fill out this class when we actually start utilizing extendedproperties
         // in the calendar application.
    }
@@ -2348,5 +2325,10 @@
      * @hide
      */
     public static final class EventsRawTimes implements BaseColumns, EventsRawTimesColumns {
+
+        /**
+         * This utility class cannot be instantiated
+         */
+        private EventsRawTimes() {}
     }
 }
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 02faf49..382fcf3 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+
 package android.provider;
 
 import com.android.internal.telephony.CallerInfo;
@@ -24,6 +25,8 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.DataUsageFeedback;
 import android.text.TextUtils;
 
 /**
@@ -55,6 +58,29 @@
                 Uri.parse("content://call_log/calls/filter");
 
         /**
+         * An optional URI parameter which instructs the provider to allow the operation to be
+         * applied to voicemail records as well.
+         * <p>
+         * TYPE: Boolean
+         * <p>
+         * Using this parameter with a value of {@code true} will result in a security error if the
+         * calling package does not have appropriate permissions to access voicemails.
+         *
+         * @hide
+         */
+        public static final String ALLOW_VOICEMAILS_PARAM_KEY = "allow_voicemails";
+
+        /**
+         * Content uri with {@link #ALLOW_VOICEMAILS_PARAM_KEY} set. This can directly be used to
+         * access call log entries that includes voicemail records.
+         *
+         * @hide
+         */
+        public static final Uri CONTENT_URI_WITH_VOICEMAIL = CONTENT_URI.buildUpon()
+                .appendQueryParameter(ALLOW_VOICEMAILS_PARAM_KEY, "true")
+                .build();
+
+        /**
          * The default sort order for this table
          */
         public static final String DEFAULT_SORT_ORDER = "date DESC";
@@ -204,7 +230,44 @@
             }
 
             if ((ci != null) && (ci.person_id > 0)) {
-                ContactsContract.Contacts.markAsContacted(resolver, ci.person_id);
+                // Update usage information for the number associated with the contact ID.
+                // We need to use both the number and the ID for obtaining a data ID since other
+                // contacts may have the same number.
+
+                final Cursor cursor;
+
+                // We should prefer normalized one (probably coming from
+                // Phone.NORMALIZED_NUMBER column) first. If it isn't available try others.
+                if (ci.normalizedNumber != null) {
+                    final String normalizedPhoneNumber = ci.normalizedNumber;
+                    cursor = resolver.query(Phone.CONTENT_URI,
+                            new String[] { Phone._ID },
+                            Phone.CONTACT_ID + " =? AND " + Phone.NORMALIZED_NUMBER + " =?",
+                            new String[] { String.valueOf(ci.person_id), normalizedPhoneNumber},
+                            null);
+                } else {
+                    final String phoneNumber = ci.phoneNumber != null ? ci.phoneNumber : number;
+                    cursor = resolver.query(Phone.CONTENT_URI,
+                            new String[] { Phone._ID },
+                            Phone.CONTACT_ID + " =? AND " + Phone.NUMBER + " =?",
+                            new String[] { String.valueOf(ci.person_id), phoneNumber},
+                            null);
+                }
+
+                if (cursor != null) {
+                    try {
+                        if (cursor.getCount() > 0 && cursor.moveToFirst()) {
+                            final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
+                                    .appendPath(cursor.getString(0))
+                                    .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
+                                                DataUsageFeedback.USAGE_TYPE_CALL)
+                                    .build();
+                            resolver.update(feedbackUri, new ContentValues(), null, null);
+                        }
+                    } finally {
+                        cursor.close();
+                    }
+                }
             }
 
             Uri result = resolver.insert(CONTENT_URI, values);
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b5a11ab..61deea4 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -123,14 +123,16 @@
 
     /**
      * An optional URI parameter for selection queries that instructs the
-     * provider to include the user's personal profile contact entry (if any)
-     * in the contact results.  If present, the user's profile will always be
-     * the first entry returned.  The default value is false.
+     * provider to allow the user's personal profile contact entry (if any)
+     * to appear in a list of contact results.  It is only useful when issuing
+     * a query that may retrieve more than one contact.  If present, the user's
+     * profile will always be the first entry returned.  The default value is
+     * false.
      *
      * Specifying this parameter will result in a security error if the calling
      * application does not have android.permission.READ_PROFILE permission.
      */
-    public static final String INCLUDE_PROFILE = "include_profile";
+    public static final String ALLOW_PROFILE = "allow_profile";
 
     /**
      * A query parameter key used to specify the package that is requesting a query.
@@ -172,6 +174,15 @@
      */
     public static final String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account";
 
+    /**
+     * A boolean parameter for {@link Contacts#CONTENT_STREQUENT_URI} and
+     * {@link Contacts#CONTENT_STREQUENT_FILTER_URI}, which requires the ContactsProvider to
+     * return only phone-related results. For example, frequently contacted person list should
+     * include persons contacted via phone (not email, sms, etc.)
+     *
+     * @hide
+     */
+    public static final String STREQUENT_PHONE_ONLY = "strequent_phone_only";
 
     /**
      * @hide
@@ -1525,6 +1536,23 @@
         }
 
         /**
+         * A sub-directory of a single contact that contains all of the constituent raw contact
+         * {@link ContactsContract.StreamItems} rows.  This directory can be used either
+         * with a {@link #CONTENT_URI} or {@link #CONTENT_LOOKUP_URI}.
+         */
+        public static final class StreamItems implements StreamItemsColumns {
+            /**
+             * no public constructor since this is a utility class
+             */
+            private StreamItems() {}
+
+            /**
+             * The directory twig for this sub-table
+             */
+            public static final String CONTENT_DIRECTORY = "stream_items";
+        }
+
+        /**
          * <p>
          * A <i>read-only</i> sub-directory of a single contact aggregate that
          * contains all aggregation suggestions (other contacts). The
@@ -2432,6 +2460,28 @@
         }
 
         /**
+         * <p>
+         * A sub-directory of a single raw contact that contains all of its
+         * {@link ContactsContract.StreamItems} rows. To access this directory append
+         * {@link RawContacts.StreamItems#CONTENT_DIRECTORY} to the raw contact URI. See
+         * {@link ContactsContract.StreamItems} for a stand-alone table containing the
+         * same data.
+         * </p>
+         */
+        public static final class StreamItems implements BaseColumns, StreamItemsColumns {
+            /**
+             * No public constructor since this is a utility class
+             */
+            private StreamItems() {
+            }
+
+            /**
+             * The directory twig for this sub-table
+             */
+            public static final String CONTENT_DIRECTORY = "stream_items";
+        }
+
+        /**
          * TODO: javadoc
          * @param cursor
          * @return
@@ -2650,6 +2700,483 @@
     }
 
     /**
+     * <p>
+     * Constants for the stream_items table, which contains social stream updates from
+     * the user's contact list.
+     * </p>
+     * <p>
+     * Only a certain number of stream items will ever be stored under a given raw contact.
+     * Users of this API can query {@link ContactsContract.StreamItems#CONTENT_LIMIT_URI} to
+     * determine this limit, and should restrict the number of items inserted in any given
+     * transaction correspondingly.  Insertion of more items beyond the limit will
+     * automatically lead to deletion of the oldest items, by {@link StreamItems#TIMESTAMP}.
+     * </p>
+     * <h3>Operations</h3>
+     * <dl>
+     * <dt><b>Insert</b></dt>
+     * <dd>
+     * <p>Social stream updates are always associated with a raw contact.  There are a couple
+     * of ways to insert these entries.
+     * <dl>
+     * <dt>Via the {@link RawContacts.StreamItems#CONTENT_DIRECTORY} sub-path of a raw contact:</dt>
+     * <dd>
+     * <pre>
+     * ContentValues values = new ContentValues();
+     * values.put(StreamItems.TEXT, "Breakfasted at Tiffanys");
+     * values.put(StreamItems.TIMESTAMP, timestamp);
+     * values.put(StreamItems.COMMENT, "3 people reshared this");
+     * values.put(StreamItems.ACTION, action);
+     * values.put(StreamItems.ACTION_URI, actionUri);
+     * Uri streamItemUri = getContentResolver().insert(
+     *     Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
+     *         RawContacts.StreamItems.CONTENT_DIRECTORY), values);
+     * long streamItemId = ContentUris.parseId(streamItemUri);
+     * </pre>
+     * </dd>
+     * <dt>Via the {@link StreamItems#CONTENT_URI} URI:</dt>
+     * <dd>
+     * ContentValues values = new ContentValues();
+     * values.put(StreamItems.RAW_CONTACT_ID, rawContactId);
+     * values.put(StreamItems.TEXT, "Breakfasted at Tiffanys");
+     * values.put(StreamItems.TIMESTAMP, timestamp);
+     * values.put(StreamItems.COMMENT, "3 people reshared this");
+     * values.put(StreamItems.ACTION, action);
+     * values.put(StreamItems.ACTION_URI, actionUri);
+     * Uri streamItemUri = getContentResolver().insert(StreamItems.CONTENT_URI, values);
+     * long streamItemId = ContentUris.parseId(streamItemUri);
+     * </dd>
+     * </dl>
+     * </dd>
+     * </p>
+     * <p>
+     * Once a {@link StreamItems} entry has been inserted, photos associated with that
+     * social update can be inserted.  For example, after one of the insertions above,
+     * photos could be added to the stream item in one of the following ways:
+     * <dl>
+     * <dt>Via a URI including the stream item ID:</dt>
+     * <dd>
+     * <pre>
+     * values.clear();
+     * values.put(StreamItemPhotos.SORT_INDEX, 1);
+     * values.put(StreamItemPhotos.PICTURE, photoData);
+     * values.put(StreamItemPhotos.ACTION, action);
+     * values.put(StreamItemPhotos.ACTION_URI, actionUri);
+     * getContentResolver().insert(Uri.withAppendedPath(
+     *     ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId),
+     *     StreamItems.StreamItemPhotos.CONTENT_DIRECTORY), values);
+     * </pre>
+     * </dd>
+     * <dt>Via {@link ContactsContract.StreamItems#CONTENT_PHOTO_URI}</dt>
+     * <dd>
+     * <pre>
+     * values.clear();
+     * values.put(StreamItemPhotos.STREAM_ITEM_ID, streamItemId);
+     * values.put(StreamItemPhotos.SORT_INDEX, 1);
+     * values.put(StreamItemPhotos.PICTURE, photoData);
+     * values.put(StreamItemPhotos.ACTION, action);
+     * values.put(StreamItemPhotos.ACTION_URI, actionUri);
+     * getContentResolver().insert(StreamItems.CONTENT_PHOTO_URI, values);
+     * </pre>
+     * Note that this latter form allows the insertion of a stream item and its
+     * photos in a single transaction, by using {@link ContentProviderOperation} with
+     * back references to populate the stream item ID in the {@link ContentValues}.
+     * </dd>
+     * </dl>
+     * </p>
+     * </dd>
+     * <dt><b>Update</b></dt>
+     * <dd>Updates can be performed by appending the stream item ID to the
+     * {@link StreamItems#CONTENT_URI} URI.  Only social stream entries that were
+     * created by the calling package can be updated.</dd>
+     * <dt><b>Delete</b></dt>
+     * <dd>Deletes can be performed by appending the stream item ID to the
+     * {@link StreamItems#CONTENT_URI} URI.  Only social stream entries that were
+     * created by the calling package can be deleted.</dd>
+     * <dt><b>Query</b></dt>
+     * <dl>
+     * <dt>Finding all social stream updates for a given contact</dt>
+     * <dd>By Contact ID:
+     * <pre>
+     * Cursor c = getContentResolver().query(Uri.withAppendedPath(
+     *          ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId),
+     *          Contacts.StreamItems.CONTENT_DIRECTORY),
+     *          null, null, null, null);
+     * </pre>
+     * </dd>
+     * <dd>By lookup key:
+     * <pre>
+     * Cursor c = getContentResolver().query(Contacts.CONTENT_URI.buildUpon()
+     *          .appendPath(lookupKey)
+     *          .appendPath(Contacts.StreamItems.CONTENT_DIRECTORY).build(),
+     *          null, null, null, null);
+     * </pre>
+     * </dd>
+     * <dt>Finding all social stream updates for a given raw contact</dt>
+     * <dd>
+     * <pre>
+     * Cursor c = getContentResolver().query(Uri.withAppendedPath(
+     *          ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
+     *          RawContacts.StreamItems.CONTENT_DIRECTORY)),
+     *          null, null, null, null);
+     * </pre>
+     * </dd>
+     * <dt>Querying for a specific stream item by ID</dt>
+     * <dd>
+     * <pre>
+     * Cursor c = getContentResolver().query(ContentUris.withAppendedId(
+     *          StreamItems.CONTENT_URI, streamItemId),
+     *          null, null, null, null);
+     * </pre>
+     * </dd>
+     * </dl>
+     */
+    public static final class StreamItems implements BaseColumns, StreamItemsColumns {
+        /**
+         * This utility class cannot be instantiated
+         */
+        private StreamItems() {
+        }
+
+        /**
+         * The content:// style URI for this table, which handles social network stream
+         * updates for the user's contacts.
+         */
+        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "stream_items");
+
+        /**
+         * <p>
+         * A content:// style URI for the photos stored in a sub-table underneath
+         * stream items.  This is only used for inserts, and updates - queries and deletes
+         * for photos should be performed by appending
+         * {@link StreamItems.StreamItemPhotos#CONTENT_DIRECTORY} path to URIs for a
+         * specific stream item.
+         * </p>
+         * <p>
+         * When using this URI, the stream item ID for the photo(s) must be identified
+         * in the {@link ContentValues} passed in.
+         * </p>
+         */
+        public static final Uri CONTENT_PHOTO_URI = Uri.withAppendedPath(CONTENT_URI, "photo");
+
+        /**
+         * This URI allows the caller to query for the maximum number of stream items
+         * that will be stored under any single raw contact, as well as the maximum
+         * photo size (in bytes) accepted in stream item photos.
+         */
+        public static final Uri CONTENT_LIMIT_URI =
+                Uri.withAppendedPath(AUTHORITY_URI, "stream_items_limit");
+
+        /**
+         * Queries to {@link ContactsContract.StreamItems#CONTENT_LIMIT_URI} will
+         * contain this column, with the value indicating the maximum number of
+         * stream items that will be stored under any single raw contact.
+         */
+        public static final String MAX_ITEMS = "max_items";
+
+        /**
+         * Queries to {@link ContactsContract.StreamItems#CONTENT_LIMIT_URI} will
+         * contain this column, with the value indicating the byte limit for
+         * individual photos.
+         */
+        public static final String PHOTO_MAX_BYTES = "photo_max_bytes";
+
+        /**
+         * <p>
+         * A sub-directory of a single stream item entry that contains all of its
+         * photo rows. To access this
+         * directory append {@link StreamItems.StreamItemPhotos#CONTENT_DIRECTORY} to
+         * an individual stream item URI.
+         * </p>
+         */
+        public static final class StreamItemPhotos
+                implements BaseColumns, StreamItemPhotosColumns {
+            /**
+             * No public constructor since this is a utility class
+             */
+            private StreamItemPhotos() {
+            }
+
+            /**
+             * The directory twig for this sub-table
+             */
+            public static final String CONTENT_DIRECTORY = "photo";
+        }
+    }
+
+    /**
+     * Columns in the StreamItems table.
+     *
+     * @see ContactsContract.StreamItems
+     */
+    protected interface StreamItemsColumns {
+        /**
+         * A reference to the {@link RawContacts#_ID}
+         * that this stream item belongs to.
+         */
+        public static final String RAW_CONTACT_ID = "raw_contact_id";
+
+        /**
+         * The package name to use when creating {@link Resources} objects for
+         * this stream item. This value is only designed for use when building
+         * user interfaces, and should not be used to infer the owner.
+         * <P>Type: NUMBER</P>
+         */
+        public static final String RES_PACKAGE = "res_package";
+
+        /**
+         * The resource ID of the icon for the source of the stream item.
+         * This resource should be scoped by the {@link #RES_PACKAGE}.
+         * <P>Type: NUMBER</P>
+         */
+        public static final String RES_ICON = "icon";
+
+        /**
+         * The resource ID of the label describing the source of the status update, e.g. "Google
+         * Talk".  This resource should be scoped by the {@link #RES_PACKAGE}.
+         * <p>Type: NUMBER</p>
+         */
+        public static final String RES_LABEL = "label";
+
+        /**
+         * <P>
+         * The main textual contents of the item. Typically this is content
+         * that was posted by the source of this stream item, but it can also
+         * be a textual representation of an action (e.g. ”Checked in at Joe's”).
+         * This text is displayed to the user and allows formatting and embedded
+         * resource images via HTML (as parseable via
+         * {@link android.text.Html#fromHtml}).
+         * </P>
+         * <P>
+         * Long content may be truncated and/or ellipsized - the exact behavior
+         * is unspecified, but it should not break tags.
+         * </P>
+         * <P>Type: TEXT</P>
+         */
+        public static final String TEXT = "text";
+
+        /**
+         * The absolute time (milliseconds since epoch) when this stream item was
+         * inserted/updated.
+         * <P>Type: NUMBER</P>
+         */
+        public static final String TIMESTAMP = "timestamp";
+
+        /**
+         * <P>
+         * Summary information about the stream item, for example to indicate how
+         * many people have reshared it, how many have liked it, how many thumbs
+         * up and/or thumbs down it has, what the original source was, etc.
+         * </P>
+         * <P>
+         * This text is displayed to the user and allows simple formatting via
+         * HTML, in the same manner as {@link #TEXT} allows.
+         * </P>
+         * <P>
+         * Long content may be truncated and/or ellipsized - the exact behavior
+         * is unspecified, but it should not break tags.
+         * </P>
+         * <P>Type: TEXT</P>
+         */
+        public static final String COMMENTS = "comments";
+
+        /**
+         * The activity action to execute when the item is tapped.
+         * <P>Type: TEXT</P>
+         */
+        public static final String ACTION = "action";
+
+        /**
+         * The URI that is launched when the item is pressed. May be handled by
+         * the source app, but could also reference a website (e.g. YouTube).
+         * <P>Type: TEXT</P>
+         */
+        public static final String ACTION_URI = "action_uri";
+    }
+
+    /**
+     * <p>
+     * Constants for the stream_item_photos table, which contains photos associated with
+     * social stream updates.
+     * </p>
+     * <h3>Operations</h3>
+     * <dl>
+     * <dt><b>Insert</b></dt>
+     * <dd>
+     * <p>Social stream photo entries are associated with a social stream item.  Photos
+     * can be inserted into a social stream item in a couple of ways:
+     * <dl>
+     * <dt>
+     * Via the {@link StreamItems.StreamItemPhotos#CONTENT_DIRECTORY} sub-path of a
+     * stream item:
+     * </dt>
+     * <dd>
+     * <pre>
+     * ContentValues values = new ContentValues();
+     * values.put(StreamItemPhotos.SORT_INDEX, 1);
+     * values.put(StreamItemPhotos.PICTURE, photoData);
+     * values.put(StreamItemPhotos.ACTION, action);
+     * values.put(StreamItemPhotos.ACTION_URI, actionUri);
+     * Uri photoUri = getContentResolver().insert(Uri.withAppendedPath(
+     *     ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId)
+     *     StreamItems.StreamItemPhotos#CONTENT_DIRECTORY), values);
+     * long photoId = ContentUris.parseId(photoUri);
+     * </pre>
+     * </dd>
+     * <dt>Via the {@link ContactsContract.StreamItems#CONTENT_PHOTO_URI} URI:</dt>
+     * <dd>
+     * <pre>
+     * ContentValues values = new ContentValues();
+     * values.put(StreamItemPhotos.STREAM_ITEM_ID, streamItemId);
+     * values.put(StreamItemPhotos.SORT_INDEX, 1);
+     * values.put(StreamItemPhotos.PICTURE, photoData);
+     * values.put(StreamItemPhotos.ACTION, action);
+     * values.put(StreamItemPhotos.ACTION_URI, actionUri);
+     * Uri photoUri = getContentResolver().insert(StreamItems.CONTENT_PHOTO_URI, values);
+     * long photoId = ContentUris.parseId(photoUri);
+     * </pre>
+     * </dd>
+     * </dl>
+     * </p>
+     * </dd>
+     * <dt><b>Update</b></dt>
+     * <dd>
+     * <p>Updates can only be made against a specific {@link StreamItemPhotos} entry,
+     * identified by both the stream item ID it belongs to and the stream item photo ID.
+     * This can be specified in two ways.
+     * <dl>
+     * <dt>Via the {@link StreamItems.StreamItemPhotos#CONTENT_DIRECTORY} sub-path of a
+     * stream item:
+     * </dt>
+     * <dd>
+     * <pre>
+     * ContentValues values = new ContentValues();
+     * values.put(StreamItemPhotos.PICTURE, newPhotoData);
+     * getContentResolver().update(
+     *     ContentUris.withAppendedId(
+     *         Uri.withAppendedPath(
+     *             ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId)
+     *             StreamItems.StreamItemPhotos#CONTENT_DIRECTORY),
+     *         streamItemPhotoId), values, null, null);
+     * </pre>
+     * </dd>
+     * <dt>Via the {@link ContactsContract.StreamItems#CONTENT_PHOTO_URI} URI:</dt>
+     * <dd>
+     * <pre>
+     * ContentValues values = new ContentValues();
+     * values.put(StreamItemPhotos.STREAM_ITEM_ID, streamItemId);
+     * values.put(StreamItemPhotos.PICTURE, newPhotoData);
+     * getContentResolver().update(StreamItems.CONTENT_PHOTO_URI, values);
+     * </pre>
+     * </dd>
+     * </dl>
+     * </p>
+     * </dd>
+     * <dt><b>Delete</b></dt>
+     * <dd>Deletes can be made against either a specific photo item in a stream item, or
+     * against all or a selected subset of photo items under a stream item.
+     * For example:
+     * <dl>
+     * <dt>Deleting a single photo via the
+     * {@link StreamItems.StreamItemPhotos#CONTENT_DIRECTORY} sub-path of a stream item:
+     * </dt>
+     * <dd>
+     * <pre>
+     * getContentResolver().delete(
+     *     ContentUris.withAppendedId(
+     *         Uri.withAppendedPath(
+     *             ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId)
+     *             StreamItems.StreamItemPhotos#CONTENT_DIRECTORY),
+     *         streamItemPhotoId), null, null);
+     * </pre>
+     * </dd>
+     * <dt>Deleting all photos under a stream item</dt>
+     * <dd>
+     * <pre>
+     * getContentResolver().delete(
+     *     Uri.withAppendedPath(
+     *         ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId)
+     *         StreamItems.StreamItemPhotos#CONTENT_DIRECTORY), null, null);
+     * </pre>
+     * </dd>
+     * </dl>
+     * </dd>
+     * <dt><b>Query</b></dt>
+     * <dl>
+     * <dt>Querying for a specific photo in a stream item</dt>
+     * <dd>
+     * <pre>
+     * Cursor c = getContentResolver().query(
+     *     ContentUris.withAppendedId(
+     *         Uri.withAppendedPath(
+     *             ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId)
+     *             StreamItems.StreamItemPhotos#CONTENT_DIRECTORY),
+     *         streamItemPhotoId), null, null, null, null);
+     * </pre>
+     * </dd>
+     * <dt>Querying for all photos in a stream item</dt>
+     * <dd>
+     * <pre>
+     * Cursor c = getContentResolver().query(
+     *     Uri.withAppendedPath(
+     *         ContentUris.withAppendedId(StreamItems.CONTENT_URI, streamItemId)
+     *         StreamItems.StreamItemPhotos#CONTENT_DIRECTORY),
+     *     null, null, null, StreamItemPhotos.SORT_INDEX);
+     * </pre>
+     * </dl>
+     * </dd>
+     * </dl>
+     */
+    public static final class StreamItemPhotos implements BaseColumns, StreamItemPhotosColumns {
+        /**
+         * No public constructor since this is a utility class
+         */
+        private StreamItemPhotos() {
+        }
+    }
+
+    /**
+     * Columns in the StreamItemPhotos table.
+     *
+     * @see ContactsContract.StreamItemPhotos
+     */
+    protected interface StreamItemPhotosColumns {
+        /**
+         * A reference to the {@link StreamItems#_ID} this photo is associated with.
+         * <P>Type: NUMBER</P>
+         */
+        public static final String STREAM_ITEM_ID = "stream_item_id";
+
+        /**
+         * An integer to use for sort order for photos in the stream item.  If not
+         * specified, the {@link StreamItemPhotos#_ID} will be used for sorting.
+         * <P>Type: NUMBER</P>
+         */
+        public static final String SORT_INDEX = "sort_index";
+
+        /**
+         * The binary representation of the picture.  Pictures larger than
+         * {@link ContactsContract.StreamItems#PHOTO_MAX_BYTES} bytes in size (as
+         * queryable from {@link ContactsContract.StreamItems#CONTENT_LIMIT_URI})
+         * will be rejected.
+         * <P>Type: BLOB</P>
+         */
+        public static final String PICTURE = "picture";
+
+        /**
+         * The activity action to execute when the photo is tapped.
+         * <P>Type: TEXT</P>
+         */
+        public static final String ACTION = "action";
+
+        /**
+         * The URI that is launched when the photo is pressed. May be handled by
+         * the source app, but could also reference a website (e.g. YouTube).
+         * <P>Type: TEXT</P>
+         */
+        public static final String ACTION_URI = "action_uri";
+    }
+
+    /**
      * Columns in the Data table.
      *
      * @see ContactsContract.Data
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 3bc1348..f799af3 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -275,6 +275,14 @@
          * @hide
          */
         public static final String MEDIA_SCANNER_NEW_OBJECT_ID = "media_scanner_new_object_id";
+
+        /**
+         * Non-zero if the media file is drm-protected
+         * <P>Type: INTEGER (boolean)</P>
+         * @hide
+         */
+        public static final String IS_DRM = "is_drm";
+
      }
 
     /**
@@ -1124,19 +1132,19 @@
             public static final String IS_PODCAST = "is_podcast";
 
             /**
-             * Non-zero id the audio file may be a ringtone
+             * Non-zero if the audio file may be a ringtone
              * <P>Type: INTEGER (boolean)</P>
              */
             public static final String IS_RINGTONE = "is_ringtone";
 
             /**
-             * Non-zero id the audio file may be an alarm
+             * Non-zero if the audio file may be an alarm
              * <P>Type: INTEGER (boolean)</P>
              */
             public static final String IS_ALARM = "is_alarm";
 
             /**
-             * Non-zero id the audio file may be a notification sound
+             * Non-zero if the audio file may be a notification sound
              * <P>Type: INTEGER (boolean)</P>
              */
             public static final String IS_NOTIFICATION = "is_notification";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index afff7e2..23b53ae 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -20,6 +20,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.app.SearchManager;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -3490,6 +3491,18 @@
                 "sms_outgoing_check_max_count";
 
         /**
+         * The global search provider chosen by the user (if multiple global
+         * search providers are installed). This will be the provider returned
+         * by {@link SearchManager#getGlobalSearchActivity()} if it's still
+         * installed. This setting is stored as a flattened component name as
+         * per {@link ComponentName#flattenToString()}.
+         *
+         * @hide
+         */
+        public static final String SEARCH_GLOBAL_SEARCH_ACTIVITY =
+                "search_global_search_activity";
+
+        /**
          * The number of promoted sources in GlobalSearch.
          * @hide
          */
@@ -3820,6 +3833,11 @@
         /** {@hide} */
         public static final String NETSTATS_TAG_MAX_HISTORY = "netstats_tag_max_history";
 
+        /** Preferred NTP server. {@hide} */
+        public static final String NTP_SERVER = "ntp_server";
+        /** Timeout in milliseconds to wait for NTP server. {@hide} */
+        public static final String NTP_TIMEOUT = "ntp_timeout";
+
         /**
          * @hide
          */
diff --git a/core/java/android/provider/SyncConstValue.java b/core/java/android/provider/SyncConstValue.java
index 2fcf315..027aed1 100644
--- a/core/java/android/provider/SyncConstValue.java
+++ b/core/java/android/provider/SyncConstValue.java
@@ -18,7 +18,7 @@
 
 /**
  * Columns for tables that are synced to a server.
- * @deprecated
+ * @deprecated Do not use.
  * @hide
  */
 public interface SyncConstValue
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index ae41876..d0712d5 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License
  */
+
 package android.provider;
 
 import android.content.Intent;
@@ -52,35 +53,41 @@
 
     /** The authority used by the voicemail provider. */
     public static final String AUTHORITY = "com.android.voicemail";
-
-    /** URI to insert/retrieve all voicemails. */
-    public static final Uri CONTENT_URI =
-            Uri.parse("content://" + AUTHORITY + "/voicemail");
-    /** URI to insert/retrieve voicemails by a given voicemail source. */
-    public static final Uri CONTENT_URI_SOURCE =
-            Uri.parse("content://" + AUTHORITY + "/voicemail/source/");
+    /**
+     * Parameter key used in the URI to specify the voicemail source package name.
+     * <p> This field must be set in all requests that originate from a voicemail source.
+     */
+    public static final String PARAM_KEY_SOURCE_PACKAGE = "source_package";
 
     // TODO: Move ACTION_NEW_VOICEMAIL to the Intent class.
     /** Broadcast intent when a new voicemail record is inserted. */
     public static final String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
     /**
      * Extra included in {@value Intent#ACTION_PROVIDER_CHANGED} and
-     * {@value #ACTION_NEW_VOICEMAIL} broadcast intents to indicate the package
-     * that caused the change in content provider.
-     * <p>Receivers of the broadcast can use this field to determine if this is
-     * a self change.
+     * {@value #ACTION_NEW_VOICEMAIL} broadcast intents to indicate if the receiving
+     * package made this change.
      */
-    public static final String EXTRA_CHANGED_BY = "com.android.voicemail.extra.CHANGED_BY";
+    public static final String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
 
-    /** The mime type for a collection of voicemails. */
-    public static final String DIR_TYPE =
-            "vnd.android.cursor.dir/voicemails";
+    /**
+     * Name of the source package field, which must be same across all voicemail related tables.
+     * @hide
+     */
+    public static final String SOURCE_PACKAGE_FIELD = "source_package";
 
+    /** Defines fields exposed through the /voicemail path of this content provider. */
     public static final class Voicemails implements BaseColumns {
         /** Not instantiable. */
         private Voicemails() {
         }
 
+        /** URI to insert/retrieve voicemails. */
+        public static final Uri CONTENT_URI =
+            Uri.parse("content://" + AUTHORITY + "/voicemail");
+
+        /** The mime type for a collection of voicemails. */
+        public static final String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
+
         /**
          * Phone number of the voicemail sender.
          * <P>Type: TEXT</P>
@@ -118,7 +125,7 @@
          * Package name of the source application that inserted the voicemail.
          * <P>Type: TEXT</P>
          */
-        public static final String SOURCE_PACKAGE = "source_package";
+        public static final String SOURCE_PACKAGE = SOURCE_PACKAGE_FIELD;
         /**
          * Application-specific data available to the source application that
          * inserted the voicemail. This is typically used to store the source
@@ -144,5 +151,101 @@
          * @hide
          */
         public static final String _DATA = "_data";
+
+        /**
+         * A convenience method to build voicemail URI specific to a source package by appending
+         * {@link VoicemailContract#PARAM_KEY_SOURCE_PACKAGE} param to the base URI.
+         */
+        public static Uri buildSourceUri(String packageName) {
+            return Voicemails.CONTENT_URI.buildUpon()
+                    .appendQueryParameter(PARAM_KEY_SOURCE_PACKAGE, packageName).build();
+        }
+    }
+
+    /** Defines fields exposed through the /status path of this content provider. */
+    public static final class Status implements BaseColumns {
+        /** URI to insert/retrieve status of voicemail source. */
+        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/status");
+        /** The mime type for a collection of voicemail source statuses. */
+        public static final String DIR_TYPE = "vnd.android.cursor.dir/voicemail.source.status";
+        /** The mime type for a collection of voicemails. */
+        public static final String ITEM_TYPE = "vnd.android.cursor.item/voicemail.source.status";
+
+        /** Not instantiable. */
+        private Status() {
+        }
+        /**
+         * The package name of the voicemail source. There can only be a one entry per source.
+         * <P>Type: TEXT</P>
+         */
+        public static final String SOURCE_PACKAGE = SOURCE_PACKAGE_FIELD;
+        /**
+         * The URI to call to invoke source specific voicemail settings screen. On a user request
+         * to setup voicemail an intent with action VIEW with this URI will be fired by the system.
+         * <P>Type: TEXT</P>
+         */
+        public static final String SETTINGS_URI = "settings_uri";
+        /**
+         * The URI to call when the user requests to directly access the voicemail from the remote
+         * server. In case of an IVR voicemail system this is typically set to the the voicemail
+         * number specified using a tel:/ URI.
+         * <P>Type: TEXT</P>
+         */
+        public static final String VOICEMAIL_ACCESS_URI = "voicemail_access_uri";
+        /**
+         * The configuration state of the voicemail source.
+         * <P> Possible values:
+         * {@link #CONFIGURATION_STATE_OK},
+         * {@link #CONFIGURATION_STATE_NOT_CONFIGURED},
+         * {@link #CONFIGURATION_STATE_CAN_BE_CONFIGURED}
+         * <P>Type: INTEGER</P>
+         */
+        public static final String CONFIGURATION_STATE = "configuration_state";
+        public static final int CONFIGURATION_STATE_OK = 0;
+        public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1;
+        /**
+         * This state must be used when the source has verified that the current user can be
+         * upgraded to visual voicemail and would like to show a set up invitation message.
+         */
+        public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2;
+        /**
+         * The data channel state of the voicemail source. This the channel through which the source
+         * pulls voicemail data from a remote server.
+         * <P> Possible values:
+         * {@link #DATA_CHANNEL_STATE_OK},
+         * {@link #DATA_CHANNEL_STATE_NO_CONNECTION}
+         * </P>
+         * <P>Type: INTEGER</P>
+         */
+        public static final String DATA_CHANNEL_STATE = "data_channel_state";
+        public static final int DATA_CHANNEL_STATE_OK = 0;
+        public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1;
+        /**
+         * The notification channel state of the voicemail source. This is the channel through which
+         * the source gets notified of new voicemails on the remote server.
+         * <P> Possible values:
+         * {@link #NOTIFICATION_CHANNEL_STATE_OK},
+         * {@link #NOTIFICATION_CHANNEL_STATE_NO_CONNECTION},
+         * {@link #NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING}
+         * </P>
+         * <P>Type: INTEGER</P>
+         */
+        public static final String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
+        public static final int NOTIFICATION_CHANNEL_STATE_OK = 0;
+        public static final int NOTIFICATION_CHANNEL_STATE_NO_CONNECTION = 1;
+        /**
+         * Use this state when the notification can only tell that there are pending messages on
+         * the server but no details of the sender/time etc are known.
+         */
+        public static final int NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING = 2;
+
+        /**
+         * A convenience method to build status URI specific to a source package by appending
+         * {@link VoicemailContract#PARAM_KEY_SOURCE_PACKAGE} param to the base URI.
+         */
+        public static Uri buildSourceUri(String packageName) {
+            return Status.CONTENT_URI.buildUpon()
+                    .appendQueryParameter(PARAM_KEY_SOURCE_PACKAGE, packageName).build();
+        }
     }
 }
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index ca2212c..fd277d0 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -449,6 +449,22 @@
                 Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()), priority);
     }
 
+    public synchronized boolean allowIncomingConnect(BluetoothDevice device, boolean value) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH_ADMIN permission");
+        String address = device.getAddress();
+        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+            return false;
+        }
+        Integer data = mBluetoothService.getAuthorizationAgentRequestData(address);
+        if (data == null) {
+            Log.w(TAG, "allowIncomingConnect(" + device + ") called but no native data available");
+            return false;
+        }
+        log("allowIncomingConnect: A2DP: " + device + ":" + value);
+        return mBluetoothService.setAuthorizationNative(address, value, data.intValue());
+    }
+
     /**
      * Called by native code on a PropertyChanged signal from
      * org.bluez.AudioSink.
@@ -517,6 +533,7 @@
             intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
             intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
             intent.putExtra(BluetoothProfile.EXTRA_STATE, state);
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
             mContext.sendBroadcast(intent, BLUETOOTH_PERM);
 
             if (DBG) log("A2DP state : device: " + device + " State:" + prevState + "->" + state);
@@ -530,6 +547,7 @@
         intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
         intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
         intent.putExtra(BluetoothProfile.EXTRA_STATE, state);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         mContext.sendBroadcast(intent, BLUETOOTH_PERM);
 
         if (DBG) log("A2DP Playing state : device: " + device + " State:" + prevState + "->" + state);
diff --git a/core/java/android/server/BluetoothBondState.java b/core/java/android/server/BluetoothBondState.java
index 76e7885..75f38f9 100644
--- a/core/java/android/server/BluetoothBondState.java
+++ b/core/java/android/server/BluetoothBondState.java
@@ -121,6 +121,8 @@
 
     /** reason is ignored unless state == BOND_NOT_BONDED */
     public synchronized void setBondState(String address, int state, int reason) {
+        if (DBG) Log.d(TAG, "setBondState " + "address" + " " + state + "reason: " + reason);
+
         int oldState = getBondState(address);
         if (oldState == state) {
             return;
@@ -136,8 +138,10 @@
 
         if (state == BluetoothDevice.BOND_BONDED) {
             mService.addProfileState(address);
-        } else if (state == BluetoothDevice.BOND_NONE) {
-            mService.removeProfileState(address);
+        } else if (state == BluetoothDevice.BOND_BONDING) {
+            if (mA2dpProxy == null || mHeadsetProxy == null) {
+                getProfileProxy();
+            }
         }
 
         setProfilePriorities(address, state);
@@ -240,6 +244,8 @@
     }
 
     public synchronized void clearPinAttempts(String address) {
+        if (DBG) Log.d(TAG, "clearPinAttempts: " + address);
+
         mPinAttempt.remove(address);
     }
 
@@ -265,6 +271,8 @@
         } else {
             newAttempt = attempt.intValue() + 1;
         }
+        if (DBG) Log.d(TAG, "attemp newAttempt: " + newAttempt);
+
         mPinAttempt.put(address, new Integer(newAttempt));
     }
 
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index a220007..63c420a 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -49,6 +49,7 @@
     private boolean mInterrupted;
 
     private final HashMap<String, Integer> mPasskeyAgentRequestData;
+    private final HashMap<String, Integer> mAuthorizationAgentRequestData;
     private final BluetoothService mBluetoothService;
     private final BluetoothAdapter mAdapter;
     private BluetoothA2dp mA2dp;
@@ -110,6 +111,7 @@
         mBluetoothService = bluetoothService;
         mContext = context;
         mPasskeyAgentRequestData = new HashMap<String, Integer>();
+        mAuthorizationAgentRequestData = new HashMap<String, Integer>();
         mAdapter = adapter;
         //WakeLock instantiation in BluetoothEventLoop class
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
@@ -155,6 +157,10 @@
         return mPasskeyAgentRequestData;
     }
 
+    /* package */ HashMap<String, Integer> getAuthorizationAgentRequestData() {
+        return mAuthorizationAgentRequestData;
+    }
+
     /* package */ void start() {
 
         if (!isEventLoopRunningNative()) {
@@ -747,20 +753,22 @@
      *
      * @param objectPath the path of the device requesting to be authorized
      * @param deviceUuid the UUID of the requesting device
-     * @return true if the authorization is allowed; false if not allowed
+     * @param nativeData reference for native data
      */
-    private boolean onAgentAuthorize(String objectPath, String deviceUuid) {
-        if (!mBluetoothService.isEnabled()) return false;
+    private void  onAgentAuthorize(String objectPath, String deviceUuid, int nativeData) {
+        if (!mBluetoothService.isEnabled()) return;
 
         String address = mBluetoothService.getAddressFromObjectPath(objectPath);
         if (address == null) {
             Log.e(TAG, "Unable to get device address in onAuthAgentAuthorize");
-            return false;
+            return;
         }
 
         boolean authorized = false;
         ParcelUuid uuid = ParcelUuid.fromString(deviceUuid);
+
         BluetoothDevice device = mAdapter.getRemoteDevice(address);
+        mAuthorizationAgentRequestData.put(address, new Integer(nativeData));
 
         // Bluez sends the UUID of the local service being accessed, _not_ the
         // remote service
@@ -769,26 +777,29 @@
               || BluetoothUuid.isAdvAudioDist(uuid)) &&
               !isOtherSinkInNonDisconnectedState(address)) {
             authorized = mA2dp.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
-            if (authorized) {
-                Log.i(TAG, "Allowing incoming A2DP / AVRCP connection from " + address);
+            if (authorized && !BluetoothUuid.isAvrcpTarget(uuid)) {
+                Log.i(TAG, "First check pass for incoming A2DP / AVRCP connection from " + address);
                 // Some headsets try to connect AVCTP before AVDTP - against the recommendation
                 // If AVCTP connection fails, we get stuck in IncomingA2DP state in the state
                 // machine.  We don't handle AVCTP signals currently. We only send
                 // intents for AVDTP state changes. We need to handle both of them in
                 // some cases. For now, just don't move to incoming state in this case.
-                if (!BluetoothUuid.isAvrcpTarget(uuid)) {
-                    mBluetoothService.notifyIncomingA2dpConnection(address);
-                }
+                mBluetoothService.notifyIncomingA2dpConnection(address);
             } else {
-                Log.i(TAG, "Rejecting incoming A2DP / AVRCP connection from " + address);
+                Log.i(TAG, "" + authorized +
+                      "Incoming A2DP / AVRCP connection from " + address);
+                mA2dp.allowIncomingConnect(device, authorized);
             }
         } else if (mInputDevice != null && BluetoothUuid.isInputDevice(uuid)) {
             // We can have more than 1 input device connected.
             authorized = mInputDevice.getPriority(device) > BluetoothInputDevice.PRIORITY_OFF;
              if (authorized) {
-                 Log.i(TAG, "Allowing incoming HID connection from " + address);
+                 Log.i(TAG, "First check pass for incoming HID connection from " + address);
+                 // notify profile state change
+                 mBluetoothService.notifyIncomingHidConnection(address);
              } else {
                  Log.i(TAG, "Rejecting incoming HID connection from " + address);
+                 mBluetoothService.allowIncomingHidConnect(device, authorized);
              }
         } else if (BluetoothUuid.isBnep(uuid) && mBluetoothService.allowIncomingTethering()){
             authorized = true;
@@ -796,7 +807,6 @@
             Log.i(TAG, "Rejecting incoming " + deviceUuid + " connection from " + address);
         }
         log("onAgentAuthorize(" + objectPath + ", " + deviceUuid + ") = " + authorized);
-        return authorized;
     }
 
     private boolean onAgentOutOfBandDataAvailable(String objectPath) {
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 2689788..b23e3ce 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -60,13 +60,18 @@
 import com.android.internal.app.IBatteryStats;
 
 import java.io.BufferedInputStream;
+import java.io.BufferedReader;
 import java.io.BufferedWriter;
+import java.io.DataInputStream;
+import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileWriter;
+import java.io.InputStreamReader;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.io.RandomAccessFile;
 import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -152,6 +157,9 @@
     private BluetoothPanProfileHandler mBluetoothPanProfileHandler;
     private BluetoothInputProfileHandler mBluetoothInputProfileHandler;
     private BluetoothHealthProfileHandler mBluetoothHealthProfileHandler;
+    private static final String INCOMING_CONNECTION_FILE =
+      "/data/misc/bluetooth/incoming_connection.conf";
+    private HashMap<String, Pair<Integer, String>> mIncomingConnections;
 
     private static class RemoteService {
         public String address;
@@ -225,6 +233,7 @@
         mBluetoothInputProfileHandler = BluetoothInputProfileHandler.getInstance(mContext, this);
         mBluetoothPanProfileHandler = BluetoothPanProfileHandler.getInstance(mContext, this);
         mBluetoothHealthProfileHandler = BluetoothHealthProfileHandler.getInstance(mContext, this);
+        mIncomingConnections = new HashMap<String, Pair<Integer, String>>();
     }
 
     public static synchronized String readDockBluetoothAddress() {
@@ -2070,6 +2079,24 @@
         }
     }
 
+    public boolean allowIncomingHidConnect(BluetoothDevice device, boolean allow) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+                                                "Need BLUETOOTH_ADMIN permission");
+        String address = device.getAddress();
+        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+            return false;
+        }
+
+        Integer data = getAuthorizationAgentRequestData(address);
+        if (data == null) {
+            Log.w(TAG, "allowIncomingHidConnect(" + device +
+                  ") called but no native data available");
+            return false;
+        }
+        if (DBG) log("allowIncomingHidConnect: " + device + " : " + allow + " : " + data);
+        return setAuthorizationNative(address, allow, data.intValue());
+    }
+
     /*package*/List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
         synchronized (mBluetoothInputProfileHandler) {
             return mBluetoothInputProfileHandler.lookupInputDevicesMatchingStates(states);
@@ -2183,6 +2210,17 @@
         }
     }
 
+    /*package*/boolean notifyIncomingHidConnection(String address) {
+        BluetoothDeviceProfileState state = mDeviceProfileState.get(address);
+        if (state == null) {
+            return false;
+        }
+        Message msg = new Message();
+        msg.what = BluetoothDeviceProfileState.CONNECT_HID_INCOMING;
+        state.sendMessage(msg);
+        return true;
+    }
+
     public boolean connectHeadset(String address) {
         if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
 
@@ -2321,6 +2359,11 @@
         mA2dpService = a2dpService;
     }
 
+    /*package*/ Integer getAuthorizationAgentRequestData(String address) {
+        Integer data = mEventLoop.getAuthorizationAgentRequestData().remove(address);
+        return data;
+    }
+
     public void sendProfileStateMessage(int profile, int cmd) {
         Message msg = new Message();
         msg.what = cmd;
@@ -2424,6 +2467,120 @@
         }
     }
 
+    private void createIncomingConnectionStateFile() {
+        File f = new File(INCOMING_CONNECTION_FILE);
+        if (!f.exists()) {
+            try {
+                f.createNewFile();
+            } catch (IOException e) {
+                Log.e(TAG, "IOException: cannot create file");
+            }
+        }
+    }
+
+    /** @hide */
+    public Pair<Integer, String> getIncomingState(String address) {
+        if (mIncomingConnections.isEmpty()) {
+            createIncomingConnectionStateFile();
+            readIncomingConnectionState();
+        }
+        return mIncomingConnections.get(address);
+    }
+
+    private void readIncomingConnectionState() {
+        synchronized(mIncomingConnections) {
+            FileInputStream fstream = null;
+            try {
+              fstream = new FileInputStream(INCOMING_CONNECTION_FILE);
+              DataInputStream in = new DataInputStream(fstream);
+              BufferedReader file = new BufferedReader(new InputStreamReader(in));
+              String line;
+              while((line = file.readLine()) != null) {
+                  line = line.trim();
+                  if (line.length() == 0) continue;
+                  String[] value = line.split(",");
+                  if (value != null && value.length == 3) {
+                      Integer val1 = Integer.parseInt(value[1]);
+                      Pair<Integer, String> val = new Pair(val1, value[2]);
+                      mIncomingConnections.put(value[0], val);
+                  }
+              }
+            } catch (FileNotFoundException e) {
+                log("FileNotFoundException: readIncomingConnectionState" + e.toString());
+            } catch (IOException e) {
+                log("IOException: readIncomingConnectionState" + e.toString());
+            } finally {
+                if (fstream != null) {
+                    try {
+                        fstream.close();
+                    } catch (IOException e) {
+                        // Ignore
+                    }
+                }
+            }
+        }
+    }
+
+    private void truncateIncomingConnectionFile() {
+        RandomAccessFile r = null;
+        try {
+            r = new RandomAccessFile(INCOMING_CONNECTION_FILE, "rw");
+            r.setLength(0);
+        } catch (FileNotFoundException e) {
+            log("FileNotFoundException: truncateIncomingConnectionState" + e.toString());
+        } catch (IOException e) {
+            log("IOException: truncateIncomingConnectionState" + e.toString());
+        } finally {
+            if (r != null) {
+                try {
+                    r.close();
+                } catch (IOException e) {
+                    // ignore
+                 }
+            }
+        }
+    }
+
+    /** @hide */
+    public void writeIncomingConnectionState(String address, Pair<Integer, String> data) {
+        synchronized(mIncomingConnections) {
+            mIncomingConnections.put(address, data);
+
+            truncateIncomingConnectionFile();
+            BufferedWriter out = null;
+            StringBuilder value = new StringBuilder();
+            try {
+                out = new BufferedWriter(new FileWriter(INCOMING_CONNECTION_FILE, true));
+                for (String devAddress: mIncomingConnections.keySet()) {
+                  Pair<Integer, String> val = mIncomingConnections.get(devAddress);
+                  value.append(devAddress);
+                  value.append(",");
+                  value.append(val.first.toString());
+                  value.append(",");
+                  value.append(val.second);
+                  value.append("\n");
+                }
+                out.write(value.toString());
+            } catch (FileNotFoundException e) {
+                log("FileNotFoundException: writeIncomingConnectionState" + e.toString());
+            } catch (IOException e) {
+                log("IOException: writeIncomingConnectionState" + e.toString());
+            } finally {
+                if (out != null) {
+                    try {
+                        out.close();
+                    } catch (IOException e) {
+                        // Ignore
+                    }
+                }
+            }
+        }
+    }
+
+    private static void log(String msg) {
+        Log.d(TAG, msg);
+    }
+
     private native static void classInitNative();
     private native void initializeNativeDataNative();
     private native boolean setupNativeDataNative();
@@ -2470,6 +2627,7 @@
             short channel);
     private native boolean removeServiceRecordNative(int handle);
     private native boolean setLinkTimeoutNative(String path, int num_slots);
+
     native boolean connectInputDeviceNative(String path);
     native boolean disconnectInputDeviceNative(String path);
 
@@ -2493,4 +2651,5 @@
     native String getChannelApplicationNative(String channelPath);
     native ParcelFileDescriptor getChannelFdNative(String channelPath);
     native boolean releaseChannelFdNative(String channelPath);
+    native boolean setAuthorizationNative(String address, boolean value, int data);
 }
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index 3826a01..79ade26 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -23,10 +23,14 @@
 import android.app.SearchableInfo;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ResolveInfo;
+import android.database.ContentObserver;
 import android.os.Process;
+import android.provider.Settings;
 import android.util.Log;
 
 import java.util.List;
@@ -46,6 +50,8 @@
     // This field is initialized lazily in getSearchables(), and then never modified.
     private Searchables mSearchables;
 
+    private ContentObserver mGlobalSearchObserver;
+
     /**
      * Initializes the Search Manager service in the provided system context.
      * Only one instance of this object should be created!
@@ -56,6 +62,8 @@
         mContext = context;
         mContext.registerReceiver(new BootCompletedReceiver(),
                 new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+        mGlobalSearchObserver = new GlobalSearchProviderObserver(
+                mContext.getContentResolver());
     }
 
     private synchronized Searchables getSearchables() {
@@ -100,6 +108,28 @@
         }
     }
 
+    class GlobalSearchProviderObserver extends ContentObserver {
+        private final ContentResolver mResolver;
+
+        public GlobalSearchProviderObserver(ContentResolver resolver) {
+            super(null);
+            mResolver = resolver;
+            mResolver.registerContentObserver(
+                    Settings.Secure.getUriFor(Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY),
+                    false /* notifyDescendants */,
+                    this);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            getSearchables().buildSearchableList();
+            Intent intent = new Intent(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
+            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+            mContext.sendBroadcast(intent);
+        }
+
+    }
+
     //
     // Searchable activities API
     //
@@ -126,6 +156,10 @@
         return getSearchables().getSearchablesInGlobalSearchList();
     }
 
+    public List<ResolveInfo> getGlobalSearchActivities() {
+        return getSearchables().getGlobalSearchActivities();
+    }
+
     /**
      * Gets the name of the global search activity.
      */
diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java
index 279c17d..f24d52f 100644
--- a/core/java/android/server/search/Searchables.java
+++ b/core/java/android/server/search/Searchables.java
@@ -16,19 +16,23 @@
 
 package android.server.search;
 
-import android.Manifest;
 import android.app.SearchManager;
 import android.app.SearchableInfo;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
+import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 
@@ -50,7 +54,10 @@
     private HashMap<ComponentName, SearchableInfo> mSearchablesMap = null;
     private ArrayList<SearchableInfo> mSearchablesList = null;
     private ArrayList<SearchableInfo> mSearchablesInGlobalSearchList = null;
-    private ComponentName mGlobalSearchActivity = null;
+    // Contains all installed activities that handle the global search
+    // intent.
+    private List<ResolveInfo> mGlobalSearchActivities;
+    private ComponentName mCurrentGlobalSearchActivity = null;
     private ComponentName mWebSearchActivity = null;
 
     public static String GOOGLE_SEARCH_COMPONENT_NAME =
@@ -224,8 +231,11 @@
             }
         }
 
+        List<ResolveInfo> newGlobalSearchActivities = findGlobalSearchActivities();
+
         // Find the global search activity
-        ComponentName newGlobalSearchActivity = findGlobalSearchActivity();
+        ComponentName newGlobalSearchActivity = findGlobalSearchActivity(
+                newGlobalSearchActivities);
 
         // Find the web search activity
         ComponentName newWebSearchActivity = findWebSearchActivity(newGlobalSearchActivity);
@@ -235,38 +245,124 @@
             mSearchablesMap = newSearchablesMap;
             mSearchablesList = newSearchablesList;
             mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList;
-            mGlobalSearchActivity = newGlobalSearchActivity;
+            mGlobalSearchActivities = newGlobalSearchActivities;
+            mCurrentGlobalSearchActivity = newGlobalSearchActivity;
             mWebSearchActivity = newWebSearchActivity;
         }
     }
-
     /**
-     * Finds the global search activity.
+     * Returns a sorted list of installed search providers as per
+     * the following heuristics:
      *
-     * This is currently implemented by returning the first activity that handles
-     * the GLOBAL_SEARCH intent and has the GLOBAL_SEARCH permission. If we allow
-     * more than one global search activity to be installed, this code must be changed.
+     * (a) System apps are given priority over non system apps.
+     * (b) Among system apps and non system apps, the relative ordering
+     * is defined by their declared priority.
      */
-    private ComponentName findGlobalSearchActivity() {
+    private List<ResolveInfo> findGlobalSearchActivities() {
+        // Step 1 : Query the package manager for a list
+        // of activities that can handle the GLOBAL_SEARCH intent.
         Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
         PackageManager pm = mContext.getPackageManager();
         List<ResolveInfo> activities =
                 pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
-        int count = activities == null ? 0 : activities.size();
-        for (int i = 0; i < count; i++) {
-            ActivityInfo ai = activities.get(i).activityInfo;
-            if (pm.checkPermission(Manifest.permission.GLOBAL_SEARCH,
-                    ai.packageName) == PackageManager.PERMISSION_GRANTED) {
-                return new ComponentName(ai.packageName, ai.name);
-            } else {
-                Log.w(LOG_TAG, "Package " + ai.packageName + " wants to handle GLOBAL_SEARCH, "
-                        + "but does not have the GLOBAL_SEARCH permission.");
+
+        if (activities != null && !activities.isEmpty()) {
+            // Step 2: Rank matching activities according to our heuristics.
+            Collections.sort(activities, GLOBAL_SEARCH_RANKER);
+        }
+
+        return activities;
+    }
+
+    /**
+     * Finds the global search activity.
+     */
+    private ComponentName findGlobalSearchActivity(List<ResolveInfo> installed) {
+        // Fetch the global search provider from the system settings,
+        // and if it's still installed, return it.
+        final String searchProviderSetting = getGlobalSearchProviderSetting();
+        if (!TextUtils.isEmpty(searchProviderSetting)) {
+            final ComponentName globalSearchComponent = ComponentName.unflattenFromString(
+                    searchProviderSetting);
+            if (globalSearchComponent != null && isInstalled(globalSearchComponent)) {
+                return globalSearchComponent;
             }
         }
+
+        return getDefaultGlobalSearchProvider(installed);
+    }
+
+    /**
+     * Checks whether the global search provider with a given
+     * component name is installed on the system or not. This deals with
+     * cases such as the removal of an installed provider.
+     */
+    private boolean isInstalled(ComponentName globalSearch) {
+        Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
+        intent.setComponent(globalSearch);
+
+        PackageManager pm = mContext.getPackageManager();
+        List<ResolveInfo> activities =
+                pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+
+        if (activities != null && !activities.isEmpty()) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private static final Comparator<ResolveInfo> GLOBAL_SEARCH_RANKER =
+            new Comparator<ResolveInfo>() {
+        @Override
+        public int compare(ResolveInfo lhs, ResolveInfo rhs) {
+            if (lhs == rhs) {
+                return 0;
+            }
+            boolean lhsSystem = isSystemApp(lhs);
+            boolean rhsSystem = isSystemApp(rhs);
+
+            if (lhsSystem && !rhsSystem) {
+                return -1;
+            } else if (rhsSystem && !lhsSystem) {
+                return 1;
+            } else {
+                // Either both system engines, or both non system
+                // engines.
+                //
+                // Note, this isn't a typo. Higher priority numbers imply
+                // higher priority, but are "lower" in the sort order.
+                return rhs.priority - lhs.priority;
+            }
+        }
+    };
+
+    /**
+     * @return true iff. the resolve info corresponds to a system application.
+     */
+    private static final boolean isSystemApp(ResolveInfo res) {
+        return (res.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+    }
+
+    /**
+     * Returns the highest ranked search provider as per the
+     * ranking defined in {@link #getGlobalSearchActivities()}.
+     */
+    private ComponentName getDefaultGlobalSearchProvider(List<ResolveInfo> providerList) {
+        if (providerList != null && !providerList.isEmpty()) {
+            ActivityInfo ai = providerList.get(0).activityInfo;
+            return new ComponentName(ai.packageName, ai.name);
+        }
+
         Log.w(LOG_TAG, "No global search activity found");
         return null;
     }
 
+    private String getGlobalSearchProviderSetting() {
+        return Settings.Secure.getString(mContext.getContentResolver(),
+                Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY);
+    }
+
     /**
      * Finds the web search activity.
      *
@@ -281,9 +377,9 @@
         PackageManager pm = mContext.getPackageManager();
         List<ResolveInfo> activities =
                 pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
-        int count = activities == null ? 0 : activities.size();
-        for (int i = 0; i < count; i++) {
-            ActivityInfo ai = activities.get(i).activityInfo;
+
+        if (activities != null && !activities.isEmpty()) {
+            ActivityInfo ai = activities.get(0).activityInfo;
             // TODO: do some sanity checks here?
             return new ComponentName(ai.packageName, ai.name);
         }
@@ -307,10 +403,17 @@
     }
 
     /**
+     * Returns a list of activities that handle the global search intent.
+     */
+    public synchronized ArrayList<ResolveInfo> getGlobalSearchActivities() {
+        return new ArrayList<ResolveInfo>(mGlobalSearchActivities);
+    }
+
+    /**
      * Gets the name of the global search activity.
      */
     public synchronized ComponentName getGlobalSearchActivity() {
-        return mGlobalSearchActivity;
+        return mCurrentGlobalSearchActivity;
     }
 
     /**
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java
index a3686b7..8ef4295 100644
--- a/core/java/android/speech/tts/AudioPlaybackHandler.java
+++ b/core/java/android/speech/tts/AudioPlaybackHandler.java
@@ -74,6 +74,12 @@
         removeMessages(token);
 
         if (token.getType() == MessageParams.TYPE_SYNTHESIS) {
+            AudioTrack current = ((SynthesisMessageParams) token).getAudioTrack();
+            if (current != null) {
+                // Stop the current audio track if it's still playing.
+                // The audio track is thread safe in this regard.
+                current.stop();
+            }
             mQueue.add(new ListEntry(SYNTHESIS_DONE, token, HIGH_PRIORITY));
         } else  {
             final MessageParams current = getCurrentParams();
@@ -378,11 +384,16 @@
             }
             count += written;
         }
+
+        param.mLogger.onPlaybackStart();
     }
 
     private void handleSynthesisDone(MessageParams msg) {
         final SynthesisMessageParams params = (SynthesisMessageParams) msg;
         handleSynthesisDone(params);
+        // This call is delayed more than it should be, but we are
+        // certain at this point that we have all the data we want.
+        params.mLogger.onWriteData();
     }
 
     // Flush all remaining data to the audio track, stop it and release
@@ -393,9 +404,10 @@
 
         try {
             if (audioTrack != null) {
-                audioTrack.flush();
-                audioTrack.stop();
                 if (DBG) Log.d(TAG, "Releasing audio track [" + audioTrack.hashCode() + "]");
+                // The last call to AudioTrack.write( ) will return only after
+                // all data from the audioTrack has been sent to the mixer, so
+                // it's safe to release at this point.
                 audioTrack.release();
             }
         } finally {
@@ -409,6 +421,8 @@
         final SynthesisMessageParams params = (SynthesisMessageParams) msg;
         if (DBG) Log.d(TAG, "completeAudioAvailable(" + params + ")");
 
+        params.mLogger.onPlaybackStart();
+
         // Channel config and bytes per frame are checked before
         // this message is sent.
         int channelConfig = AudioPlaybackHandler.getChannelConfig(params.mChannelCount);
diff --git a/core/java/android/speech/tts/EventLogTags.logtags b/core/java/android/speech/tts/EventLogTags.logtags
new file mode 100644
index 0000000..1a9f5fe
--- /dev/null
+++ b/core/java/android/speech/tts/EventLogTags.logtags
@@ -0,0 +1,6 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package android.speech.tts;
+
+76001 tts_speak_success (engine|3),(caller|3),(length|1),(locale|3),(rate|1),(pitch|1),(engine_latency|2|3),(engine_total|2|3),(audio_latency|2|3)
+76002 tts_speak_failure (engine|3),(caller|3),(length|1),(locale|3),(rate|1),(pitch|1)
diff --git a/core/java/android/speech/tts/EventLogger.java b/core/java/android/speech/tts/EventLogger.java
new file mode 100644
index 0000000..63b954b
--- /dev/null
+++ b/core/java/android/speech/tts/EventLogger.java
@@ -0,0 +1,175 @@
+/*
+ * 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.speech.tts;
+
+import android.os.SystemClock;
+import android.text.TextUtils;
+
+/**
+ * Writes data about a given speech synthesis request to the event logs.
+ * The data that is logged includes the calling app, length of the utterance,
+ * speech rate / pitch and the latency and overall time taken.
+ *
+ * Note that {@link EventLogger#onStopped()} and {@link EventLogger#onError()}
+ * might be called from any thread, but on {@link EventLogger#onPlaybackStart()} and
+ * {@link EventLogger#onComplete()} must be called from a single thread
+ * (usually the audio playback thread}
+ */
+class EventLogger {
+    private final SynthesisRequest mRequest;
+    private final String mCallingApp;
+    private final String mServiceApp;
+    private final long mReceivedTime;
+    private long mPlaybackStartTime = -1;
+    private volatile long mRequestProcessingStartTime = -1;
+    private volatile long mEngineStartTime = -1;
+    private volatile long mEngineCompleteTime = -1;
+
+    private volatile boolean mError = false;
+    private volatile boolean mStopped = false;
+    private boolean mLogWritten = false;
+
+    EventLogger(SynthesisRequest request, String callingApp,
+            String serviceApp) {
+        mRequest = request;
+        mCallingApp = callingApp;
+        mServiceApp = serviceApp;
+        mReceivedTime = SystemClock.elapsedRealtime();
+    }
+
+    /**
+     * Notifies the logger that this request has been selected from
+     * the processing queue for processing. Engine latency / total time
+     * is measured from this baseline.
+     */
+    public void onRequestProcessingStart() {
+        mRequestProcessingStartTime = SystemClock.elapsedRealtime();
+    }
+
+    /**
+     * Notifies the logger that a chunk of data has been received from
+     * the engine. Might be called multiple times.
+     */
+    public void onEngineDataReceived() {
+        if (mEngineStartTime == -1) {
+            mEngineStartTime = SystemClock.elapsedRealtime();
+        }
+    }
+
+    /**
+     * Notifies the logger that the engine has finished processing data.
+     * Will be called exactly once.
+     */
+    public void onEngineComplete() {
+        mEngineCompleteTime = SystemClock.elapsedRealtime();
+    }
+
+    /**
+     * Notifies the logger that audio playback has started for some section
+     * of the synthesis. This is normally some amount of time after the engine
+     * has synthesized data and varides depending on utterances and
+     * other audio currently in the queue.
+     */
+    public void onPlaybackStart() {
+        // For now, keep track of only the first chunk of audio
+        // that was played.
+        if (mPlaybackStartTime == -1) {
+            mPlaybackStartTime = SystemClock.elapsedRealtime();
+        }
+    }
+
+    /**
+     * Notifies the logger that the current synthesis was stopped.
+     * Latency numbers are not reported for stopped syntheses.
+     */
+    public void onStopped() {
+        mStopped = false;
+    }
+
+    /**
+     * Notifies the logger that the current synthesis resulted in
+     * an error. This is logged using {@link EventLogTags#writeTtsSpeakFailure}.
+     */
+    public void onError() {
+        mError = true;
+    }
+
+    /**
+     * Notifies the logger that the current synthesis has completed.
+     * All available data is not logged.
+     */
+    public void onWriteData() {
+        if (mLogWritten) {
+            return;
+        } else {
+            mLogWritten = true;
+        }
+
+        long completionTime = SystemClock.elapsedRealtime();
+        // onPlaybackStart() should normally always be called if an
+        // error does not occur.
+        if (mError || mPlaybackStartTime == -1 || mEngineCompleteTime == -1) {
+            EventLogTags.writeTtsSpeakFailure(mServiceApp, mCallingApp,
+                    getUtteranceLength(), getLocaleString(),
+                    mRequest.getSpeechRate(), mRequest.getPitch());
+            return;
+        }
+
+        // We don't report stopped syntheses because their overall
+        // total time spent will be innacurate (will not correlate with
+        // the length of the utterance).
+        if (mStopped) {
+            return;
+        }
+
+        final long audioLatency = mPlaybackStartTime - mReceivedTime;
+        final long engineLatency = mEngineStartTime - mRequestProcessingStartTime;
+        final long engineTotal = mEngineCompleteTime - mRequestProcessingStartTime;
+        EventLogTags.writeTtsSpeakSuccess(mServiceApp, mCallingApp,
+                getUtteranceLength(), getLocaleString(),
+                mRequest.getSpeechRate(), mRequest.getPitch(),
+                engineLatency, engineTotal, audioLatency);
+    }
+
+    /**
+     * @return the length of the utterance for the given synthesis, 0
+     *          if the utterance was {@code null}.
+     */
+    private int getUtteranceLength() {
+        final String utterance = mRequest.getText();
+        return utterance == null ? 0 : utterance.length();
+    }
+
+    /**
+     * Returns a formatted locale string from the synthesis params of the
+     * form lang-country-variant.
+     */
+    private String getLocaleString() {
+        StringBuilder sb = new StringBuilder(mRequest.getLanguage());
+        if (!TextUtils.isEmpty(mRequest.getCountry())) {
+            sb.append('-');
+            sb.append(mRequest.getCountry());
+
+            if (!TextUtils.isEmpty(mRequest.getVariant())) {
+                sb.append('-');
+                sb.append(mRequest.getVariant());
+            }
+        }
+
+        return sb.toString();
+    }
+
+}
diff --git a/core/java/android/speech/tts/PlaybackSynthesisCallback.java b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
index bdaa1b8..38030a6 100644
--- a/core/java/android/speech/tts/PlaybackSynthesisCallback.java
+++ b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
@@ -65,29 +65,42 @@
 
     private final UtteranceCompletedDispatcher mDispatcher;
     private final String mCallingApp;
+    private final EventLogger mLogger;
 
     PlaybackSynthesisCallback(int streamType, float volume, float pan,
             AudioPlaybackHandler audioTrackHandler, UtteranceCompletedDispatcher dispatcher,
-            String callingApp) {
+            String callingApp, EventLogger logger) {
         mStreamType = streamType;
         mVolume = volume;
         mPan = pan;
         mAudioTrackHandler = audioTrackHandler;
         mDispatcher = dispatcher;
         mCallingApp = callingApp;
+        mLogger = logger;
     }
 
     @Override
     void stop() {
         if (DBG) Log.d(TAG, "stop()");
 
+        // Note that mLogger.mError might be true too at this point.
+        mLogger.onStopped();
+
         synchronized (mStateLock) {
-            if (mToken == null || mStopped) {
-                Log.w(TAG, "stop() called twice, before start(), or after done()");
+            if (mStopped) {
+                Log.w(TAG, "stop() called twice");
                 return;
             }
-            mAudioTrackHandler.stop(mToken);
-            mToken = null;
+            // mToken will be null if the engine encounters
+            // an error before it called start().
+            if (mToken != null) {
+                mAudioTrackHandler.stop(mToken);
+                mToken = null;
+            } else {
+                // In all other cases, mAudioTrackHandler.stop() will
+                // result in onComplete being called.
+                mLogger.onWriteData();
+            }
             mStopped = true;
         }
     }
@@ -124,7 +137,7 @@
             }
             SynthesisMessageParams params = new SynthesisMessageParams(
                     mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan,
-                    mDispatcher, mCallingApp);
+                    mDispatcher, mCallingApp, mLogger);
             mAudioTrackHandler.enqueueSynthesisStart(params);
 
             mToken = params;
@@ -157,6 +170,8 @@
             mAudioTrackHandler.enqueueSynthesisDataAvailable(mToken);
         }
 
+        mLogger.onEngineDataReceived();
+
         return TextToSpeech.SUCCESS;
     }
 
@@ -177,6 +192,7 @@
             }
 
             mAudioTrackHandler.enqueueSynthesisDone(mToken);
+            mLogger.onEngineComplete();
         }
         return TextToSpeech.SUCCESS;
     }
@@ -184,6 +200,9 @@
     @Override
     public void error() {
         if (DBG) Log.d(TAG, "error() [will call stop]");
+        // Currently, this call will not be logged if error( ) is called
+        // before start.
+        mLogger.onError();
         stop();
     }
 
@@ -208,7 +227,7 @@
             }
             SynthesisMessageParams params = new SynthesisMessageParams(
                     mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan,
-                    mDispatcher, mCallingApp);
+                    mDispatcher, mCallingApp, mLogger);
             params.addBuffer(buffer, offset, length);
 
             mAudioTrackHandler.enqueueSynthesisCompleteDataAvailable(params);
diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java
index 51f3d2e..caf02ef 100644
--- a/core/java/android/speech/tts/SynthesisMessageParams.java
+++ b/core/java/android/speech/tts/SynthesisMessageParams.java
@@ -30,6 +30,7 @@
     final int mChannelCount;
     final float mVolume;
     final float mPan;
+    final EventLogger mLogger;
 
     public volatile AudioTrack mAudioTrack;
 
@@ -38,7 +39,7 @@
     SynthesisMessageParams(int streamType, int sampleRate,
             int audioFormat, int channelCount,
             float volume, float pan, UtteranceCompletedDispatcher dispatcher,
-            String callingApp) {
+            String callingApp, EventLogger logger) {
         super(dispatcher, callingApp);
 
         mStreamType = streamType;
@@ -47,6 +48,7 @@
         mChannelCount = channelCount;
         mVolume = volume;
         mPan = pan;
+        mLogger = logger;
 
         // initially null.
         mAudioTrack = null;
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 5ee33e1..8e4725f 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -442,7 +442,7 @@
     private final Map<String, Uri> mUtterances;
     private final Bundle mParams = new Bundle();
     private final TtsEngines mEnginesHelper;
-    private String mCurrentEngine = null;
+    private volatile String mCurrentEngine = null;
 
     /**
      * The constructor for the TextToSpeech class, using the default TTS engine.
@@ -573,6 +573,7 @@
                 service.setCallback(getPackageName(), null);
                 service.stop(getPackageName());
                 mServiceConnection.disconnect();
+                mCurrentEngine = null;
                 return null;
             }
         }, null, "shutdown");
@@ -869,6 +870,14 @@
     }
 
     /**
+     * @return the engine currently in use by this TextToSpeech instance.
+     * @hide
+     */
+    public String getCurrentEngine() {
+        return mCurrentEngine;
+    }
+
+    /**
      * Sets the text-to-speech language.
      * The TTS engine will try to use the closest match to the specified
      * language as represented by the Locale, but there is no guarantee that the exact same Locale
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 7ea9373..010c155 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -82,8 +82,7 @@
     private AudioPlaybackHandler mAudioPlaybackHandler;
 
     private CallbackMap mCallbacks;
-
-    private int mDefaultAvailability = TextToSpeech.LANG_NOT_SUPPORTED;
+    private String mPackageName;
 
     @Override
     public void onCreate() {
@@ -99,9 +98,10 @@
 
         mCallbacks = new CallbackMap();
 
+        mPackageName = getApplicationInfo().packageName;
+
         // Load default language
-        mDefaultAvailability = onLoadLanguage(getDefaultLanguage(),
-                getDefaultCountry(), getDefaultVariant());
+        onLoadLanguage(getDefaultLanguage(), getDefaultCountry(), getDefaultVariant());
     }
 
     @Override
@@ -457,12 +457,14 @@
         // Non null after synthesis has started, and all accesses
         // guarded by 'this'.
         private AbstractSynthesisCallback mSynthesisCallback;
+        private final EventLogger mEventLogger;
 
         public SynthesisSpeechItem(String callingApp, Bundle params, String text) {
             super(callingApp, params);
             mText = text;
             mSynthesisRequest = new SynthesisRequest(mText, mParams);
             setRequestParams(mSynthesisRequest);
+            mEventLogger = new EventLogger(mSynthesisRequest, getCallingApp(), mPackageName);
         }
 
         public String getText() {
@@ -485,6 +487,7 @@
         @Override
         protected int playImpl() {
             AbstractSynthesisCallback synthesisCallback;
+            mEventLogger.onRequestProcessingStart();
             synchronized (this) {
                 mSynthesisCallback = createSynthesisCallback();
                 synthesisCallback = mSynthesisCallback;
@@ -495,7 +498,7 @@
 
         protected AbstractSynthesisCallback createSynthesisCallback() {
             return new PlaybackSynthesisCallback(getStreamType(), getVolume(), getPan(),
-                    mAudioPlaybackHandler, this, getCallingApp());
+                    mAudioPlaybackHandler, this, getCallingApp(), mEventLogger);
         }
 
         private void setRequestParams(SynthesisRequest request) {
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 4107c5a..aae9ccf 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1,4 +1,4 @@
-/*
+ /*
  * Copyright (C) 2006 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -266,7 +266,7 @@
             }
         }
 
-        Alignment align = mAlignment;
+        Alignment paraAlign = mAlignment;
         TabStops tabStops = null;
         boolean tabStopsIsInitialized = false;
 
@@ -310,10 +310,10 @@
                                                     ParagraphStyle.class);
                     spans = getParagraphSpans(sp, start, spanEnd, ParagraphStyle.class);
 
-                    align = mAlignment;
+                    paraAlign = mAlignment;
                     for (int n = spans.length-1; n >= 0; n--) {
                         if (spans[n] instanceof AlignmentSpan) {
-                            align = ((AlignmentSpan) spans[n]).getAlignment();
+                            paraAlign = ((AlignmentSpan) spans[n]).getAlignment();
                             break;
                         }
                     }
@@ -360,6 +360,16 @@
                 tabStopsIsInitialized = true;
             }
 
+            // Determine whether the line aligns to normal, opposite, or center.
+            Alignment align = paraAlign;
+            if (align == Alignment.ALIGN_LEFT) {
+                align = (dir == DIR_LEFT_TO_RIGHT) ?
+                    Alignment.ALIGN_NORMAL : Alignment.ALIGN_OPPOSITE;
+            } else if (align == Alignment.ALIGN_RIGHT) {
+                align = (dir == DIR_LEFT_TO_RIGHT) ?
+                    Alignment.ALIGN_OPPOSITE : Alignment.ALIGN_NORMAL;
+            }
+
             int x;
             if (align == Alignment.ALIGN_NORMAL) {
                 if (dir == DIR_LEFT_TO_RIGHT) {
@@ -411,7 +421,9 @@
         int dir = getParagraphDirection(line);
 
         int x;
-        if (align == Alignment.ALIGN_NORMAL) {
+        if (align == Alignment.ALIGN_LEFT) {
+            x = left;
+        } else if (align == Alignment.ALIGN_NORMAL) {
             if (dir == DIR_LEFT_TO_RIGHT) {
                 x = left;
             } else {
@@ -430,7 +442,9 @@
                 }
             }
             int max = (int)getLineExtent(line, tabStops, false);
-            if (align == Alignment.ALIGN_OPPOSITE) {
+            if (align == Alignment.ALIGN_RIGHT) {
+                x = right - max;
+            } else if (align == Alignment.ALIGN_OPPOSITE) {
                 if (dir == DIR_LEFT_TO_RIGHT) {
                     x = right - max;
                 } else {
@@ -738,11 +752,15 @@
         int dir = getParagraphDirection(line);
         Alignment align = getParagraphAlignment(line);
 
-        if (align == Alignment.ALIGN_NORMAL) {
+        if (align == Alignment.ALIGN_LEFT) {
+            return 0;
+        } else if (align == Alignment.ALIGN_NORMAL) {
             if (dir == DIR_RIGHT_TO_LEFT)
                 return getParagraphRight(line) - getLineMax(line);
             else
                 return 0;
+        } else if (align == Alignment.ALIGN_RIGHT) {
+            return mWidth - getLineMax(line);
         } else if (align == Alignment.ALIGN_OPPOSITE) {
             if (dir == DIR_RIGHT_TO_LEFT)
                 return 0;
@@ -765,11 +783,15 @@
         int dir = getParagraphDirection(line);
         Alignment align = getParagraphAlignment(line);
 
-        if (align == Alignment.ALIGN_NORMAL) {
+        if (align == Alignment.ALIGN_LEFT) {
+            return getParagraphLeft(line) + getLineMax(line);
+        } else if (align == Alignment.ALIGN_NORMAL) {
             if (dir == DIR_RIGHT_TO_LEFT)
                 return mWidth;
             else
                 return getParagraphLeft(line) + getLineMax(line);
+        } else if (align == Alignment.ALIGN_RIGHT) {
+            return mWidth;
         } else if (align == Alignment.ALIGN_OPPOSITE) {
             if (dir == DIR_RIGHT_TO_LEFT)
                 return getLineMax(line);
@@ -1765,8 +1787,10 @@
         ALIGN_NORMAL,
         ALIGN_OPPOSITE,
         ALIGN_CENTER,
-        // XXX ALIGN_LEFT,
-        // XXX ALIGN_RIGHT,
+        /** @hide */
+        ALIGN_LEFT,
+        /** @hide */
+        ALIGN_RIGHT,
     }
 
     private static final int TAB_INCREMENT = 20;
diff --git a/core/java/android/text/method/AllCapsTransformationMethod.java b/core/java/android/text/method/AllCapsTransformationMethod.java
new file mode 100644
index 0000000..f9920dd
--- /dev/null
+++ b/core/java/android/text/method/AllCapsTransformationMethod.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.text.method;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.Log;
+import android.view.View;
+
+import java.util.Locale;
+
+/**
+ * Transforms source text into an ALL CAPS string, locale-aware.
+ *
+ * @hide
+ */
+public class AllCapsTransformationMethod implements TransformationMethod2 {
+    private static final String TAG = "AllCapsTransformationMethod";
+
+    private boolean mEnabled;
+    private Locale mLocale;
+
+    public AllCapsTransformationMethod(Context context) {
+        mLocale = context.getResources().getConfiguration().locale;
+    }
+
+    @Override
+    public CharSequence getTransformation(CharSequence source, View view) {
+        if (mEnabled) {
+            return source != null ? source.toString().toUpperCase(mLocale) : null;
+        }
+        Log.w(TAG, "Caller did not enable length changes; not transforming text");
+        return source;
+    }
+
+    @Override
+    public void onFocusChanged(View view, CharSequence sourceText, boolean focused, int direction,
+            Rect previouslyFocusedRect) {
+    }
+
+    @Override
+    public void setLengthChangesAllowed(boolean allowLengthChanges) {
+        mEnabled = allowLengthChanges;
+    }
+
+}
diff --git a/core/java/android/text/method/TransformationMethod2.java b/core/java/android/text/method/TransformationMethod2.java
new file mode 100644
index 0000000..ef00ecd
--- /dev/null
+++ b/core/java/android/text/method/TransformationMethod2.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.text.method;
+
+/**
+ * TransformationMethod2 extends the TransformationMethod interface
+ * and adds the ability to relax restrictions of TransformationMethod.
+ *
+ * @hide
+ */
+public interface TransformationMethod2 extends TransformationMethod {
+    /**
+     * Relax the contract of TransformationMethod to allow length changes,
+     * or revert to the length-restricted behavior.
+     *
+     * @param allowLengthChanges true to allow the transformation to change the length
+     *                           of the input string.
+     */
+    public void setLengthChangesAllowed(boolean allowLengthChanges);
+}
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index 240ad9b..555aac5 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -22,12 +22,22 @@
 import android.os.SystemClock;
 import android.text.ParcelableSpan;
 import android.text.TextUtils;
+import android.widget.TextView;
 
 import java.util.Arrays;
 import java.util.Locale;
 
 /**
- * Holds suggestion candidates of words under this span.
+ * Holds suggestion candidates for the text enclosed in this span.
+ *
+ * When such a span is edited in an EditText, double tapping on the text enclosed in this span will
+ * display a popup dialog listing suggestion replacement for that text. The user can then replace
+ * the original text by one of the suggestions.
+ *
+ * These spans should typically be created by the input method to privide correction and alternates
+ * for the text.
+ *
+ * @see TextView#setSuggestionsEnabled(boolean)
  */
 public class SuggestionSpan implements ParcelableSpan {
     /**
@@ -115,14 +125,14 @@
     }
 
     /**
-     * @return suggestions
+     * @return an array of suggestion texts for this span
      */
     public String[] getSuggestions() {
         return mSuggestions;
     }
 
     /**
-     * @return locale of suggestions
+     * @return the locale of the suggestions
      */
     public String getLocale() {
         return mLocaleString;
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index 5b19ecd..2179ff3 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -16,41 +16,71 @@
 
 package android.util;
 
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
 import android.net.SntpClient;
 import android.os.SystemClock;
+import android.provider.Settings;
 
 /**
- * {@link TrustedTime} that connects with a remote NTP server as its remote
- * trusted time source.
+ * {@link TrustedTime} that connects with a remote NTP server as its trusted
+ * time source.
  *
  * @hide
  */
 public class NtpTrustedTime implements TrustedTime {
-    private String mNtpServer;
-    private long mNtpTimeout;
+    private static final String TAG = "NtpTrustedTime";
+    private static final boolean LOGD = false;
+
+    private static NtpTrustedTime sSingleton;
+
+    private final String mServer;
+    private final long mTimeout;
 
     private boolean mHasCache;
     private long mCachedNtpTime;
     private long mCachedNtpElapsedRealtime;
     private long mCachedNtpCertainty;
 
-    public NtpTrustedTime() {
+    private NtpTrustedTime(String server, long timeout) {
+        if (LOGD) Log.d(TAG, "creating NtpTrustedTime using " + server);
+        mServer = server;
+        mTimeout = timeout;
     }
 
-    public void setNtpServer(String server, long timeout) {
-        mNtpServer = server;
-        mNtpTimeout = timeout;
+    public static synchronized NtpTrustedTime getInstance(Context context) {
+        if (sSingleton == null) {
+            final Resources res = context.getResources();
+            final ContentResolver resolver = context.getContentResolver();
+
+            final String defaultServer = res.getString(
+                    com.android.internal.R.string.config_ntpServer);
+            final long defaultTimeout = res.getInteger(
+                    com.android.internal.R.integer.config_ntpTimeout);
+
+            final String secureServer = Settings.Secure.getString(
+                    resolver, Settings.Secure.NTP_SERVER);
+            final long timeout = Settings.Secure.getLong(
+                    resolver, Settings.Secure.NTP_TIMEOUT, defaultTimeout);
+
+            final String server = secureServer != null ? secureServer : defaultServer;
+            sSingleton = new NtpTrustedTime(server, timeout);
+        }
+
+        return sSingleton;
     }
 
     /** {@inheritDoc} */
     public boolean forceRefresh() {
-        if (mNtpServer == null) {
+        if (mServer == null) {
             // missing server, so no trusted time available
             return false;
         }
 
+        if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
         final SntpClient client = new SntpClient();
-        if (client.requestTime(mNtpServer, (int) mNtpTimeout)) {
+        if (client.requestTime(mServer, (int) mTimeout)) {
             mHasCache = true;
             mCachedNtpTime = client.getNtpTime();
             mCachedNtpElapsedRealtime = client.getNtpTimeReference();
@@ -89,9 +119,19 @@
         if (!mHasCache) {
             throw new IllegalStateException("Missing authoritative time source");
         }
+        if (LOGD) Log.d(TAG, "currentTimeMillis() cache hit");
 
         // current time is age after the last ntp cache; callers who
         // want fresh values will hit makeAuthoritative() first.
         return mCachedNtpTime + getCacheAge();
     }
+
+    public long getCachedNtpTime() {
+        if (LOGD) Log.d(TAG, "getCachedNtpTime() cache hit");
+        return mCachedNtpTime;
+    }
+
+    public long getCachedNtpTimeReference() {
+        return mCachedNtpElapsedRealtime;
+    }
 }
diff --git a/core/java/android/view/ActionProvider.java b/core/java/android/view/ActionProvider.java
new file mode 100644
index 0000000..6491da0
--- /dev/null
+++ b/core/java/android/view/ActionProvider.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.content.Context;
+
+/**
+ * This class is a mediator for accomplishing a given task, for example sharing a file.
+ * It is responsible for creating a view that performs an action that accomplishes the task.
+ * This class also implements other functions such a performing a default action.
+ * <p>
+ * An ActionProvider can be optionally specified for a {@link MenuItem} and in such a
+ * case it will be responsible for creating the action view that appears in the
+ * {@link android.app.ActionBar} as a substitute for the menu item when the item is
+ * displayed as an action item. Also the provider is responsible for performing a
+ * default action if a menu item placed on the overflow menu of the ActionBar is
+ * selected and none of the menu item callbacks has handled the selection.
+ * </p>
+ * <p>
+ * There are two ways for using an action provider for creating and handling of action views:
+ * <ul>
+ * <li>
+ * Setting the action provider on a {@link MenuItem} directly by calling
+ * {@link MenuItem#setActionProvider(ActionProvider)}.
+ * </li>
+ * <li>
+ * Declaring the action provider in the menu XML resource. For example:
+ * <pre>
+ * <code>
+ *   &lt;item android:id="@+id/my_menu_item"
+ *     android:title="Title"
+ *     android:icon="@drawable/my_menu_item_icon"
+ *     android:showAsAction="ifRoom"
+ *     android:actionProviderClass="foo.bar.SomeActionProvider" /&gt;
+ * </code>
+ * </pre>
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * @see MenuItem#setActionProvider(ActionProvider)
+ * @see MenuItem#getActionProvider()
+ */
+public abstract class ActionProvider {
+
+    /**
+     * Creates a new instance.
+     *
+     * @param context Context for accessing resources.
+     */
+    public ActionProvider(Context context) {
+    }
+
+    /**
+     * Factory method for creating new action views.
+     *
+     * @return A new action view.
+     */
+    public abstract View onCreateActionView();
+
+    /**
+     * Performs an optional default action.
+     * <p>
+     * For the case of an action provider placed in a menu item not shown as an action this
+     * method is invoked if none of the callbacks for processing menu selection has handled
+     * the event.
+     * </p>
+     * <p>
+     * A menu item selection is processed in the following order:
+     * <ul>
+     * <li>
+     * Receiving a call to {@link MenuItem.OnMenuItemClickListener#onMenuItemClick
+     *  MenuItem.OnMenuItemClickListener.onMenuItemClick}.
+     * </li>
+     * <li>
+     * Receiving a call to {@link android.app.Activity#onOptionsItemSelected(MenuItem)
+     *  Activity.onOptionsItemSelected(MenuItem)}
+     * </li>
+     * <li>
+     * Receiving a call to {@link android.app.Fragment#onOptionsItemSelected(MenuItem)
+     *  Fragment.onOptionsItemSelected(MenuItem)}
+     * </li>
+     * <li>
+     * Launching the {@link android.content.Intent} set via
+     * {@link MenuItem#setIntent(android.content.Intent) MenuItem.setIntent(android.content.Intent)}
+     * </li>
+     * <li>
+     * Invoking this method.
+     * </li>
+     * </ul>
+     * </p>
+     * <p>
+     * The default implementation does not perform any action.
+     * </p>
+     *
+     * @param actionView A view created by {@link #onCreateActionView()}.
+     */
+    public void onPerformDefaultAction(View actionView) {
+    }
+}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 04f35dc..4987e2f 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -189,6 +189,19 @@
         return mHeight;
     }
 
+    @Override
+    public int getMaximumBitmapWidth() {
+        return nGetMaximumTextureWidth();
+    }
+
+    @Override
+    public int getMaximumBitmapHeight() {
+        return nGetMaximumTextureHeight();
+    }
+
+    private static native int nGetMaximumTextureWidth();
+    private static native int nGetMaximumTextureHeight();    
+
     ///////////////////////////////////////////////////////////////////////////
     // Setup
     ///////////////////////////////////////////////////////////////////////////
@@ -233,8 +246,19 @@
         return nIsBackBufferPreserved();
     }
 
-    private static native boolean nIsBackBufferPreserved();    
-    
+    private static native boolean nIsBackBufferPreserved();
+
+    /**
+     * Disables v-sync. For performance testing only.
+     * 
+     * @hide
+     */
+    public static void disableVsync() {
+        nDisableVsync();
+    }
+
+    private static native void nDisableVsync();
+
     @Override
     void onPreDraw(Rect dirty) {
         if (dirty != null) {
@@ -252,7 +276,7 @@
     void onPostDraw() {
         nFinish(mRenderer);
     }
-    
+
     private static native void nFinish(int renderer);
 
     @Override
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index bbfb4c1..1638c74 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -57,6 +57,16 @@
      * "false", to disable partial invalidates
      */
     static final String RENDER_DIRTY_REGIONS_PROPERTY = "hwui.render_dirty_regions";
+    
+    /**
+     * System property used to enable or disable vsync.
+     * The default value of this property is assumed to be false.
+     * 
+     * Possible values:
+     * "true", to disable vsync
+     * "false", to enable vsync
+     */
+    static final String DISABLE_VSYNC_PROPERTY = "hwui.disable_vsync";
 
     /**
      * Turn on to draw dirty regions every other frame.
@@ -118,8 +128,14 @@
     abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
 
     /**
-     * Setup the hardware renderer for drawing. This is called for every
-     * frame to draw.
+     * Invoked whenever the size of the target surface changes. This will
+     * not be invoked when the surface is first created.
+     */
+    abstract void preapareSurfaceForResize();
+
+    /**
+     * Setup the hardware renderer for drawing. This is called whenever the
+     * size of the target surface changes or when the surface is first created.
      * 
      * @param width Width of the drawing surface.
      * @param height Height of the drawing surface.
@@ -279,9 +295,9 @@
     static abstract class GlRenderer extends HardwareRenderer {
         // These values are not exposed in our EGL APIs
         static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
-        static final int EGL_SURFACE_TYPE = 0x3033;
-        static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
         static final int EGL_OPENGL_ES2_BIT = 4;
+        static final int EGL_SURFACE_TYPE = 0x3033;
+        static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;        
 
         private static final int SURFACE_STATE_ERROR = 0;
         private static final int SURFACE_STATE_SUCCESS = 1;
@@ -301,8 +317,17 @@
         int mFrameCount;
         Paint mDebugPaint;
 
-        boolean mDirtyRegions;
-        final boolean mDirtyRegionsRequested;
+        static boolean sDirtyRegions;
+        static final boolean sDirtyRegionsRequested;
+        static {
+            String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true");
+            //noinspection PointlessBooleanExpression,ConstantConditions
+            sDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty);
+            sDirtyRegionsRequested = sDirtyRegions;
+        }
+
+        boolean mDirtyRegionsEnabled;
+        final boolean mVsyncDisabled;
 
         final int mGlVersion;
         final boolean mTranslucent;
@@ -314,17 +339,19 @@
         GlRenderer(int glVersion, boolean translucent) {
             mGlVersion = glVersion;
             mTranslucent = translucent;
-            final String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true");
-            //noinspection PointlessBooleanExpression,ConstantConditions
-            mDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty);
-            mDirtyRegionsRequested = mDirtyRegions;
+
+            final String vsyncProperty = SystemProperties.get(DISABLE_VSYNC_PROPERTY, "false");
+            mVsyncDisabled = "true".equalsIgnoreCase(vsyncProperty);
+            if (mVsyncDisabled) {
+                Log.d(LOG_TAG, "Disabling v-sync");
+            }
         }
 
         /**
          * Indicates whether this renderer instance can track and update dirty regions.
          */
         boolean hasDirtyRegions() {
-            return mDirtyRegions;
+            return mDirtyRegionsEnabled;
         }
 
         /**
@@ -461,8 +488,8 @@
             sEglConfig = chooseEglConfig();
             if (sEglConfig == null) {
                 // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
-                if (mDirtyRegions) {
-                    mDirtyRegions = false;
+                if (sDirtyRegions) {
+                    sDirtyRegions = false;
                     sEglConfig = chooseEglConfig();
                     if (sEglConfig == null) {
                         throw new RuntimeException("eglConfig not initialized");
@@ -482,7 +509,7 @@
         private EGLConfig chooseEglConfig() {
             int[] configsCount = new int[1];
             EGLConfig[] configs = new EGLConfig[1];
-            int[] configSpec = getConfig(mDirtyRegions);
+            int[] configSpec = getConfig(sDirtyRegions);
             if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) {
                 throw new IllegalArgumentException("eglChooseConfig failed " +
                         getEGLErrorString(sEgl.eglGetError()));
@@ -548,18 +575,18 @@
 
             // If mDirtyRegions is set, this means we have an EGL configuration
             // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set
-            if (mDirtyRegions) {
-                if (!GLES20Canvas.preserveBackBuffer()) {
+            if (sDirtyRegions) {
+                if (!(mDirtyRegionsEnabled = GLES20Canvas.preserveBackBuffer())) {
                     Log.w(LOG_TAG, "Backbuffer cannot be preserved");
                 }
-            } else if (mDirtyRegionsRequested) {
+            } else if (sDirtyRegionsRequested) {
                 // If mDirtyRegions is not set, our EGL configuration does not
                 // have EGL_SWAP_BEHAVIOR_PRESERVED_BIT; however, the default
                 // swap behavior might be EGL_BUFFER_PRESERVED, which means we
                 // want to set mDirtyRegions. We try to do this only if dirty
                 // regions were initially requested as part of the device
                 // configuration (see RENDER_DIRTY_REGIONS)
-                mDirtyRegions = GLES20Canvas.isBackBufferPreserved();
+                mDirtyRegionsEnabled = GLES20Canvas.isBackBufferPreserved();
             }
 
             return sEglContext.getGL();
@@ -602,6 +629,14 @@
         }
 
         @Override
+        void preapareSurfaceForResize() {
+            // Cancels any existing buffer to ensure we'll get a buffer
+            // of the right size before we call eglSwapBuffers
+            sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE,
+                    EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);              
+        }
+
+        @Override
         void setup(int width, int height) {
             mCanvas.setViewport(width, height);
         }
@@ -765,6 +800,14 @@
         }
 
         @Override
+        void setup(int width, int height) {
+            super.setup(width, height);
+            if (mVsyncDisabled) {
+                GLES20Canvas.disableVsync();
+            }
+        }
+
+        @Override
         DisplayList createDisplayList(View v) {
             return new GLES20DisplayList(v);
         }
diff --git a/core/java/android/view/InputEventConsistencyVerifier.java b/core/java/android/view/InputEventConsistencyVerifier.java
index 49f3bbe..9b081b2 100644
--- a/core/java/android/view/InputEventConsistencyVerifier.java
+++ b/core/java/android/view/InputEventConsistencyVerifier.java
@@ -239,7 +239,7 @@
                     break;
             }
         } finally {
-            finishEvent(false);
+            finishEvent();
         }
     }
 
@@ -302,7 +302,7 @@
                 problem("Source was not SOURCE_CLASS_TRACKBALL.");
             }
         } finally {
-            finishEvent(false);
+            finishEvent();
         }
     }
 
@@ -328,7 +328,9 @@
             mTouchEventStreamUnhandled = false;
             mTouchEventStreamPointers = 0;
         }
-        final boolean wasTainted = mTouchEventStreamIsTainted;
+        if (mTouchEventStreamIsTainted) {
+            event.setTainted(true);
+        }
 
         try {
             ensureMetaStateIsNormalized(event.getMetaState());
@@ -441,7 +443,7 @@
                 problem("Source was not SOURCE_CLASS_POINTER.");
             }
         } finally {
-            finishEvent(wasTainted);
+            finishEvent();
         }
     }
 
@@ -499,7 +501,7 @@
                 }
             }
         } finally {
-            finishEvent(false);
+            finishEvent();
         }
     }
 
@@ -591,9 +593,9 @@
         return true;
     }
 
-    private void finishEvent(boolean tainted) {
+    private void finishEvent() {
         if (mViolationMessage != null && mViolationMessage.length() != 0) {
-            if (!tainted) {
+            if (!mCurrentEvent.isTainted()) {
                 // Write a log message only if the event was not already tainted.
                 mViolationMessage.append("\n  in ").append(mCaller);
                 mViolationMessage.append("\n  ");
@@ -614,17 +616,14 @@
                 }
 
                 Log.d(mLogTag, mViolationMessage.toString());
-                tainted = true;
+
+                // Taint the event so that we do not generate additional violations from it
+                // further downstream.
+                mCurrentEvent.setTainted(true);
             }
             mViolationMessage.setLength(0);
         }
 
-        if (tainted) {
-            // Taint the event so that we do not generate additional violations from it
-            // further downstream.
-            mCurrentEvent.setTainted(true);
-        }
-
         if (RECENT_EVENTS_TO_LOG != 0) {
             if (mRecentEvents == null) {
                 mRecentEvents = new InputEvent[RECENT_EVENTS_TO_LOG];
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 5dbda90..6c3d387 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -2361,11 +2361,11 @@
      * Gets the {@link KeyCharacterMap} associated with the keyboard device.
      *
      * @return The associated key character map.
-     * @throws {@link UnavailableException} if the key character map
+     * @throws {@link KeyCharacterMap.UnavailableException} if the key character map
      * could not be loaded because it was malformed or the default key character map
      * is missing from the system.
      *
-     * @see {@link KeyCharacterMap#load}
+     * @see KeyCharacterMap#load
      */
     public final KeyCharacterMap getKeyCharacterMap() {
         return KeyCharacterMap.load(mDeviceId);
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index 372ac15..a7f0cba 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -26,6 +26,7 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.Xml;
 
 import java.io.IOException;
@@ -42,6 +43,8 @@
  * <em>something</em> file.)
  */
 public class MenuInflater {
+    private static final String LOG_TAG = "MenuInflater";
+
     /** Menu tag name in XML. */
     private static final String XML_MENU = "menu";
     
@@ -53,10 +56,16 @@
 
     private static final int NO_ID = 0;
     
-    private static final Class<?>[] ACTION_VIEW_CONSTRUCTOR_SIGNATURE = new Class[]{Context.class};
+    private static final Class<?>[] ACTION_VIEW_CONSTRUCTOR_SIGNATURE = new Class[] {Context.class};
+
+    private static final Class<?>[] ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE = ACTION_VIEW_CONSTRUCTOR_SIGNATURE;
+
+    private final Object[] mActionViewConstructorArguments;
+
+    private final Object[] mActionProviderConstructorArguments;
 
     private Context mContext;
-    
+
     /**
      * Constructs a menu inflater.
      * 
@@ -64,6 +73,8 @@
      */
     public MenuInflater(Context context) {
         mContext = context;
+        mActionViewConstructorArguments = new Object[] {context};
+        mActionProviderConstructorArguments = mActionViewConstructorArguments;
     }
 
     /**
@@ -172,14 +183,14 @@
     
     private static class InflatedOnMenuItemClickListener
             implements MenuItem.OnMenuItemClickListener {
-        private static final Class[] PARAM_TYPES = new Class[] { MenuItem.class };
+        private static final Class<?>[] PARAM_TYPES = new Class[] { MenuItem.class };
         
         private Context mContext;
         private Method mMethod;
         
         public InflatedOnMenuItemClickListener(Context context, String methodName) {
             mContext = context;
-            Class c = context.getClass();
+            Class<?> c = context.getClass();
             try {
                 mMethod = c.getMethod(methodName, PARAM_TYPES);
             } catch (Exception e) {
@@ -255,7 +266,8 @@
 
         private int itemActionViewLayout;
         private String itemActionViewClassName;
-        
+        private String itemActionProviderClassName;
+
         private String itemListenerMethodName;
         
         private static final int defaultGroupId = NO_ID;
@@ -333,9 +345,10 @@
             itemListenerMethodName = a.getString(com.android.internal.R.styleable.MenuItem_onClick);
             itemActionViewLayout = a.getResourceId(com.android.internal.R.styleable.MenuItem_actionLayout, 0);
             itemActionViewClassName = a.getString(com.android.internal.R.styleable.MenuItem_actionViewClass);
-            
+            itemActionProviderClassName = a.getString(com.android.internal.R.styleable.MenuItem_actionProviderClass);
+
             a.recycle();
-            
+
             itemAdded = false;
         }
 
@@ -377,20 +390,35 @@
                 }
             }
 
+            boolean actionViewSpecified = false;
             if (itemActionViewClassName != null) {
-                try {
-                    final Class<?> clazz = Class.forName(itemActionViewClassName, true,
-                            mContext.getClassLoader());
-                    Constructor<?> c = clazz.getConstructor(ACTION_VIEW_CONSTRUCTOR_SIGNATURE);
-                    item.setActionView((View) c.newInstance(mContext));
-                } catch (Exception e) {
-                    throw new InflateException(e);
+                View actionView = (View) newInstance(itemActionViewClassName,
+                        ACTION_VIEW_CONSTRUCTOR_SIGNATURE, mActionViewConstructorArguments);
+                item.setActionView(actionView);
+                actionViewSpecified = true;
+            }
+            if (itemActionViewLayout > 0) {
+                if (!actionViewSpecified) {
+                    item.setActionView(itemActionViewLayout);
+                    actionViewSpecified = true;
+                } else {
+                    Log.w(LOG_TAG, "Ignoring attribute 'itemActionViewLayout'."
+                            + " Action view already specified.");
                 }
-            } else if (itemActionViewLayout > 0) {
-                item.setActionView(itemActionViewLayout);
+            }
+            if (itemActionProviderClassName != null) {
+                if (!actionViewSpecified) {
+                    ActionProvider actionProvider = newInstance(itemActionProviderClassName,
+                            ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE,
+                            mActionProviderConstructorArguments);
+                    item.setActionProvider(actionProvider);
+                } else {
+                    Log.w(LOG_TAG, "Ignoring attribute 'itemActionProviderClass'."
+                            + " Action view already specified.");
+                }
             }
         }
-        
+
         public void addItem() {
             itemAdded = true;
             setItem(menu.add(groupId, itemId, itemCategoryOrder, itemTitle));
@@ -406,6 +434,18 @@
         public boolean hasAddedItem() {
             return itemAdded;
         }
+
+        @SuppressWarnings("unchecked")
+        private <T> T newInstance(String className, Class<?>[] constructorSignature,
+                Object[] arguments) {
+            try {
+                Class<?> clazz = mContext.getClassLoader().loadClass(className);
+                Constructor<?> constructor = clazz.getConstructor(constructorSignature);
+                return (T) constructor.newInstance(arguments);
+            } catch (Exception e) {
+                Log.w(LOG_TAG, "Cannot instantiate class: " + className, e);
+            }
+            return null;
+        }
     }
-    
 }
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index dc68264..ccd8353 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -88,7 +88,6 @@
      * @see MenuItem#expandActionView()
      * @see MenuItem#collapseActionView()
      * @see MenuItem#setShowAsActionFlags(int)
-     * @see MenuItem#
      */
     public interface OnActionExpandListener {
         /**
@@ -480,6 +479,10 @@
      * Set an action view for this menu item. An action view will be displayed in place
      * of an automatically generated menu item element in the UI when this item is shown
      * as an action within a parent.
+     * <p>
+     *   <strong>Note:</strong> Setting an action view overrides the action provider
+     *           set via {@link #setActionProvider(ActionProvider)}.
+     * </p>
      *
      * @param view View to use for presenting this item to the user.
      * @return This Item so additional setters can be called.
@@ -492,6 +495,10 @@
      * Set an action view for this menu item. An action view will be displayed in place
      * of an automatically generated menu item element in the UI when this item is shown
      * as an action within a parent.
+     * <p>
+     *   <strong>Note:</strong> Setting an action view overrides the action provider
+     *           set via {@link #setActionProvider(ActionProvider)}.
+     * </p>
      *
      * @param resId Layout resource to use for presenting this item to the user.
      * @return This Item so additional setters can be called.
@@ -511,6 +518,32 @@
     public View getActionView();
 
     /**
+     * Sets the {@link ActionProvider} responsible for creating an action view if
+     * the item is placed on the action bar. The provider also provides a default
+     * action invoked if the item is placed in the overflow menu.
+     * <p>
+     *   <strong>Note:</strong> Setting an action provider overrides the action view
+     *           set via {@link #setActionView(int)} or {@link #setActionView(View)}.
+     * </p>
+     *
+     * @param actionProvider The action provider.
+     * @return This Item so additional setters can be called.
+     *
+     * @see ActionProvider
+     */
+    public MenuItem setActionProvider(ActionProvider actionProvider);
+
+    /**
+     * Gets the {@link ActionProvider}.
+     *
+     * @return The action provider.
+     *
+     * @see ActionProvider
+     * @see #setActionProvider(ActionProvider)
+     */
+    public ActionProvider getActionProvider();
+
+    /**
      * Expand the action view associated with this menu item.
      * The menu item must have an action view set, as well as
      * the showAsAction flag {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}.
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 3436cd1..88f59d4 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1130,14 +1130,14 @@
     public static final int BUTTON_PRIMARY = 1 << 0;
 
     /**
-     * Button constant: Secondary button (right mouse button, stylus barrel).
+     * Button constant: Secondary button (right mouse button, stylus first button).
      *
      * @see #getButtonState
      */
     public static final int BUTTON_SECONDARY = 1 << 1;
 
     /**
-     * Button constant: Tertiary button (middle mouse button).
+     * Button constant: Tertiary button (middle mouse button, stylus second button).
      *
      * @see #getButtonState
      */
@@ -1165,13 +1165,6 @@
      */
     public static final int BUTTON_FORWARD = 1 << 4;
 
-    /**
-     * Button constant: Eraser button pressed (stylus end).
-     *
-     * @see #getButtonState
-     */
-    public static final int BUTTON_ERASER = 1 << 5;
-
     // NOTE: If you add a new axis here you must also add it to:
     //  native/include/android/input.h
 
@@ -1183,7 +1176,7 @@
         "BUTTON_TERTIARY",
         "BUTTON_BACK",
         "BUTTON_FORWARD",
-        "BUTTON_ERASER",
+        "0x00000020",
         "0x00000040",
         "0x00000080",
         "0x00000100",
@@ -2176,7 +2169,6 @@
      * @see #BUTTON_TERTIARY
      * @see #BUTTON_FORWARD
      * @see #BUTTON_BACK
-     * @see #BUTTON_ERASER
      */
     public final int getButtonState() {
         return nativeGetButtonState(mNativePtr);
@@ -2893,7 +2885,7 @@
                     toolTypeToString(getToolType(i)));
         }
 
-        msg.append(", buttonState=").append(KeyEvent.metaStateToString(getButtonState()));
+        msg.append(", buttonState=").append(MotionEvent.buttonStateToString(getButtonState()));
         msg.append(", metaState=").append(KeyEvent.metaStateToString(getMetaState()));
         msg.append(", flags=0x").append(Integer.toHexString(getFlags()));
         msg.append(", edgeFlags=0x").append(Integer.toHexString(getEdgeFlags()));
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 0c0cd76..d656f31 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -185,7 +185,7 @@
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
 
-        if (isHardwareAccelerated() && mLayer != null) {
+        if (mLayer != null) {
             if (mListener != null) {
                 mListener.onSurfaceTextureDestroyed(mSurface);
             }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0413b05..74dc100 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2326,6 +2326,7 @@
     private CheckForLongPress mPendingCheckForLongPress;
     private CheckForTap mPendingCheckForTap = null;
     private PerformClick mPerformClick;
+    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
 
     private UnsetPressedState mUnsetPressedState;
 
@@ -2492,6 +2493,98 @@
     private boolean mSendingHoverAccessibilityEvents;
 
     /**
+     * Undefined text direction (used by resolution algorithm).
+     * @hide
+     */
+    public static final int TEXT_DIRECTION_UNDEFINED = -1;
+
+    /**
+     * Text direction is inherited thru {@link ViewGroup}
+     * @hide
+     */
+    public static final int TEXT_DIRECTION_INHERIT = 0;
+
+    /**
+     * Text direction is using "first strong algorithm". The first strong directional character
+     * determines the paragraph direction. If there is no strong directional character, the
+     * paragraph direction is the view’s resolved ayout direction.
+     *
+     * @hide
+     */
+    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
+
+    /**
+     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
+     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
+     * If there are neither, the paragraph direction is the view’s resolved layout direction.
+     *
+     * @hide
+     */
+    public static final int TEXT_DIRECTION_ANY_RTL = 2;
+
+    /**
+     * Text direction is the same as the one held by a 60% majority of the characters. If there is
+     * no majority then the paragraph direction is the resolved layout direction of the View.
+     *
+     * @hide
+     */
+    public static final int TEXT_DIRECTION_CHAR_COUNT = 3;
+
+    /**
+     * Text direction is forced to LTR.
+     *
+     * @hide
+     */
+    public static final int TEXT_DIRECTION_LTR = 4;
+
+    /**
+     * Text direction is forced to RTL.
+     *
+     * @hide
+     */
+    public static final int TEXT_DIRECTION_RTL = 5;
+
+    /**
+     * Default text direction is inherited
+     */
+    protected static int DEFAULT_TEXT_DIRECTION = TEXT_DIRECTION_INHERIT;
+
+    /**
+     * Default threshold for "char count" heuristic.
+     */
+    protected static float DEFAULT_TEXT_DIRECTION_CHAR_COUNT_THRESHOLD = 0.6f;
+
+    /**
+     * The text direction that has been defined by {@link #setTextDirection(int)}.
+     *
+     * {@hide}
+     */
+    @ViewDebug.ExportedProperty(category = "text", mapping = {
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_UNDEFINED, to = "UNDEFINED"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_CHAR_COUNT, to = "CHAR_COUNT"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL")
+    })
+    protected int mTextDirection = DEFAULT_TEXT_DIRECTION;
+
+    /**
+     * The resolved text direction. If resolution has not yet been done or has been reset, it will
+     * be equal to {@link #TEXT_DIRECTION_UNDEFINED}. Otherwise it will be either {@link #TEXT_DIRECTION_LTR}
+     * or {@link #TEXT_DIRECTION_RTL}.
+     *
+     * {@hide}
+     */
+    @ViewDebug.ExportedProperty(category = "text", mapping = {
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_UNDEFINED, to = "UNDEFINED"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
+            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL")
+    })
+    protected int mResolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+
+    /**
      * Consistency verifier for debugging purposes.
      * @hide
      */
@@ -2864,6 +2957,9 @@
                 case R.styleable.View_layerType:
                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
                     break;
+                case R.styleable.View_textDirection:
+                    mTextDirection = a.getInt(attr, DEFAULT_TEXT_DIRECTION);
+                    break;
             }
         }
 
@@ -3389,6 +3485,14 @@
     }
 
     /**
+     * Register a callback to be invoked when a hover event is sent to this view.
+     * @param l the hover listener to attach to this view
+     */
+    public void setOnHoverListener(OnHoverListener l) {
+        mOnHoverListener = l;
+    }
+
+    /**
      * Register a drag event listener callback object for this View. The parameter is
      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
      * View, the system calls the
@@ -3699,7 +3803,6 @@
      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
      */
     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
-
     }
 
     /**
@@ -3728,12 +3831,23 @@
         event.setEnabled(isEnabled());
         event.setContentDescription(mContentDescription);
 
-        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
-            ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
-            getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
-            event.setItemCount(focusablesTempList.size());
-            event.setCurrentItemIndex(focusablesTempList.indexOf(this));
-            focusablesTempList.clear();
+        final int eventType = event.getEventType();
+        switch (eventType) {
+            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
+                if (mAttachInfo != null) {
+                    ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
+                    getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
+                            FOCUSABLES_ALL);
+                    event.setItemCount(focusablesTempList.size());
+                    event.setCurrentItemIndex(focusablesTempList.indexOf(this));
+                    focusablesTempList.clear();
+                }
+            } break;
+            case AccessibilityEvent.TYPE_VIEW_SCROLLED: {
+                event.setScrollX(mScrollX);
+                event.setScrollY(mScrollY);
+                event.setItemCount(getHeight());
+            } break;
         }
     }
 
@@ -4360,7 +4474,7 @@
     @RemotableViewMethod
     public void setLayoutDirection(int layoutDirection) {
         if (getLayoutDirection() != layoutDirection) {
-            resetLayoutDirectionResolution();
+            resetResolvedLayoutDirection();
             // Setting the flag will also request a layout.
             setFlags(layoutDirection, LAYOUT_DIRECTION_MASK);
         }
@@ -6165,6 +6279,16 @@
     }
 
     /**
+     * Remove the pending callback for sending a
+     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
+     */
+    private void removeSendViewScrolledAccessibilityEventCallback() {
+        if (mSendViewScrolledAccessibilityEvent != null) {
+            removeCallbacks(mSendViewScrolledAccessibilityEvent);
+        }
+    }
+
+    /**
      * Sets the TouchDelegate for this View.
      */
     public void setTouchDelegate(TouchDelegate delegate) {
@@ -6337,6 +6461,10 @@
      * @param oldt Previous vertical scroll origin.
      */
     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+            postSendViewScrolledAccessibilityEventCallback();
+        }
+
         mBackgroundSizeChanged = true;
 
         final AttachInfo ai = mAttachInfo;
@@ -8263,6 +8391,22 @@
     }
 
     /**
+     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
+     * This event is sent at most once every
+     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
+     */
+    private void postSendViewScrolledAccessibilityEventCallback() {
+        if (mSendViewScrolledAccessibilityEvent == null) {
+            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
+        }
+        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
+            mSendViewScrolledAccessibilityEvent.mIsPending = true;
+            postDelayed(mSendViewScrolledAccessibilityEvent,
+                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
+        }
+    }
+
+    /**
      * Called by a parent to request that a child update its values for mScrollX
      * and mScrollY if necessary. This will typically be done if the child is
      * animating a scroll using a {@link android.widget.Scroller Scroller}
@@ -8899,9 +9043,9 @@
             mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
         }
         jumpDrawablesToCurrentState();
-        resetLayoutDirectionResolution();
         resolveLayoutDirectionIfNeeded();
         resolvePadding();
+        resolveTextDirection();
         if (isFocused()) {
             InputMethodManager imm = InputMethodManager.peekInstance();
             imm.focusIn(this);
@@ -8989,9 +9133,15 @@
     }
 
     /**
-     * Reset the resolved layout direction by clearing the corresponding flag
+     * Reset the resolved layout direction.
+     *
+     * Subclasses need to override this method to clear cached information that depends on the
+     * resolved layout direction, or to inform child views that inherit their layout direction.
+     * Overrides must also call the superclass implementation at the start of their implementation.
+     *
+     * @hide
      */
-    void resetLayoutDirectionResolution() {
+    protected void resetResolvedLayoutDirection() {
         // Reset the current View resolution
         mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED;
     }
@@ -9002,7 +9152,7 @@
      * @param locale Locale to check
      * @return true if a Locale is corresponding to a RTL script.
      */
-    private static boolean isLayoutDirectionRtl(Locale locale) {
+    protected static boolean isLayoutDirectionRtl(Locale locale) {
         return (LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE ==
                 LocaleUtil.getLayoutDirectionFromLocale(locale));
     }
@@ -9019,6 +9169,7 @@
         removeUnsetPressCallback();
         removeLongPressCallback();
         removePerformClickCallback();
+        removeSendViewScrolledAccessibilityEventCallback();
 
         destroyDrawingCache();
 
@@ -9037,6 +9188,9 @@
         }
 
         mCurrentAnimation = null;
+
+        resetResolvedLayoutDirection();
+        resetResolvedTextDirection();
     }
 
     /**
@@ -11830,6 +11984,10 @@
         mPrivateFlags |= FORCE_LAYOUT;
         mPrivateFlags |= INVALIDATED;
 
+        if (mLayoutParams != null && mParent != null) {
+            mLayoutParams.resolveWithDirection(getResolvedLayoutDirection());
+        }
+
         if (mParent != null && !mParent.isLayoutRequested()) {
             mParent.requestLayout();
         }
@@ -12844,6 +13002,91 @@
         return getVerticalScrollFactor();
     }
 
+    /**
+     * Return the value specifying the text direction or policy that was set with
+     * {@link #setTextDirection(int)}.
+     *
+     * @return the defined text direction. It can be one of:
+     *
+     * {@link #TEXT_DIRECTION_INHERIT},
+     * {@link #TEXT_DIRECTION_FIRST_STRONG}
+     * {@link #TEXT_DIRECTION_ANY_RTL},
+     * {@link #TEXT_DIRECTION_CHAR_COUNT},
+     * {@link #TEXT_DIRECTION_LTR},
+     * {@link #TEXT_DIRECTION_RTL},
+     *
+     * @hide
+     */
+    public int getTextDirection() {
+        return mTextDirection;
+    }
+
+    /**
+     * Set the text direction.
+     *
+     * @param textDirection the direction to set. Should be one of:
+     *
+     * {@link #TEXT_DIRECTION_INHERIT},
+     * {@link #TEXT_DIRECTION_FIRST_STRONG}
+     * {@link #TEXT_DIRECTION_ANY_RTL},
+     * {@link #TEXT_DIRECTION_CHAR_COUNT},
+     * {@link #TEXT_DIRECTION_LTR},
+     * {@link #TEXT_DIRECTION_RTL},
+     *
+     * @hide
+     */
+    public void setTextDirection(int textDirection) {
+        if (textDirection != mTextDirection) {
+            mTextDirection = textDirection;
+            resetResolvedTextDirection();
+            requestLayout();
+        }
+    }
+
+    /**
+     * Return the resolved text direction.
+     *
+     * @return the resolved text direction. Return one of:
+     *
+     * {@link #TEXT_DIRECTION_LTR},
+     * {@link #TEXT_DIRECTION_RTL},
+     *
+     * @hide
+     */
+    public int getResolvedTextDirection() {
+        if (!isResolvedTextDirection()) {
+            resolveTextDirection();
+        }
+        return mResolvedTextDirection;
+    }
+
+    /**
+     * Resolve the text direction. Classes that extend View and want to do a specific text direction
+     * resolution will need to implement this method and set the mResolvedTextDirection to
+     * either TEXT_DIRECTION_LTR if direction is LTR or TEXT_DIRECTION_RTL if
+     * direction is RTL.
+     */
+    protected void resolveTextDirection() {
+    }
+
+    /**
+     * Return if the text direction has been resolved or not.
+     *
+     * @return true, if resolved and false if not resolved
+     *
+     * @hide
+     */
+    public boolean isResolvedTextDirection() {
+        return (mResolvedTextDirection != TEXT_DIRECTION_UNDEFINED);
+    }
+
+    /**
+     * Reset resolved text direction. Will be resolved during a call to getResolvedLayoutDirection().
+     */
+    protected void resetResolvedTextDirection() {
+        mResolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+    }
+
     //
     // Properties
     //
@@ -13816,6 +14059,18 @@
                 host.invalidate(true);
             }
         }
+    }
 
+    /**
+     * Resuable callback for sending
+     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
+     */
+    private class SendViewScrolledAccessibilityEvent implements Runnable {
+        public volatile boolean mIsPending;
+
+        public void run() {
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
+            mIsPending = false;
+        }
     }
 }
diff --git a/core/java/android/view/ViewAncestor.java b/core/java/android/view/ViewAncestor.java
index e5d6d9f..b4f323c 100644
--- a/core/java/android/view/ViewAncestor.java
+++ b/core/java/android/view/ViewAncestor.java
@@ -136,13 +136,6 @@
     static final ArrayList<ComponentCallbacks> sConfigCallbacks
             = new ArrayList<ComponentCallbacks>();
 
-    /**
-     * Delay before dispatching an accessibility event that the window
-     * content has changed. The window content is considered changed
-     * after a layout pass.
-     */
-    private static final long SEND_WINDOW_CONTENT_CHANGED_DELAY_MILLIS = 500;
-
     long mLastTrackballTime = 0;
     final TrackballAxis mTrackballAxisX = new TrackballAxis();
     final TrackballAxis mTrackballAxisY = new TrackballAxis();
@@ -284,7 +277,7 @@
 
     AccessibilityInteractionConnectionManager mAccessibilityInteractionConnectionManager;
 
-    SendWindowContentChanged mSendWindowContentChanged;
+    SendWindowContentChangedAccessibilityEvent mSendWindowContentChangedAccessibilityEvent;
 
     private final int mDensity;
 
@@ -1321,6 +1314,9 @@
             if (hwInitialized || ((windowShouldResize || params != null) &&
                     mAttachInfo.mHardwareRenderer != null &&
                     mAttachInfo.mHardwareRenderer.isEnabled())) {
+                if (!hwInitialized) {
+                    mAttachInfo.mHardwareRenderer.preapareSurfaceForResize();
+                }
                 mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
             }
 
@@ -3692,14 +3688,19 @@
     /**
      * Post a callback to send a
      * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
+     * This event is send at most once every
+     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
      */
     private void postSendWindowContentChangedCallback() {
-        if (mSendWindowContentChanged == null) {
-            mSendWindowContentChanged = new SendWindowContentChanged();
-        } else {
-            removeCallbacks(mSendWindowContentChanged);
+        if (mSendWindowContentChangedAccessibilityEvent == null) {
+            mSendWindowContentChangedAccessibilityEvent =
+                new SendWindowContentChangedAccessibilityEvent();
         }
-        postDelayed(mSendWindowContentChanged, SEND_WINDOW_CONTENT_CHANGED_DELAY_MILLIS);
+        if (!mSendWindowContentChangedAccessibilityEvent.mIsPending) {
+            mSendWindowContentChangedAccessibilityEvent.mIsPending = true;
+            postDelayed(mSendWindowContentChangedAccessibilityEvent,
+                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
+        }
     }
 
     /**
@@ -3707,8 +3708,8 @@
      * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
      */
     private void removeSendWindowContentChangedCallback() {
-        if (mSendWindowContentChanged != null) {
-            removeCallbacks(mSendWindowContentChanged);
+        if (mSendWindowContentChangedAccessibilityEvent != null) {
+            removeCallbacks(mSendWindowContentChangedAccessibilityEvent);
         }
     }
 
@@ -3847,10 +3848,6 @@
         }
 
         private static int checkCallingPermission(String permission) {
-            if (!Process.supportsProcesses()) {
-                return PackageManager.PERMISSION_GRANTED;
-            }
-
             try {
                 return ActivityManagerNative.getDefault().checkPermission(
                         permission, Binder.getCallingPid(), Binder.getCallingUid());
@@ -4634,10 +4631,24 @@
         }
     }
 
-    private class SendWindowContentChanged implements Runnable {
+    private class SendWindowContentChangedAccessibilityEvent implements Runnable {
+        public volatile boolean mIsPending;
+
         public void run() {
             if (mView != null) {
-                mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+                // Check again for accessibility state since this is executed delayed.
+                AccessibilityManager accessibilityManager =
+                    AccessibilityManager.getInstance(mView.mContext);
+                if (accessibilityManager.isEnabled()) {
+                    // Send the event directly since we do not want to append the
+                    // source text because this is the text for the entire window
+                    // and we just want to notify that the content has changed.
+                    AccessibilityEvent event = AccessibilityEvent.obtain(
+                            AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+                    mView.onInitializeAccessibilityEvent(event);
+                    accessibilityManager.sendAccessibilityEvent(event);
+                }
+                mIsPending = false;
             }
         }
     }
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 5919150..dbcbd6e 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -19,6 +19,8 @@
 import android.app.AppGlobals;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.RemoteException;
 import android.provider.Settings;
 import android.util.DisplayMetrics;
 import android.util.SparseArray;
@@ -176,6 +178,14 @@
     private static final int TOUCH_EXPLORATION_TAP_SLOP = 80;
 
     /**
+     * Delay before dispatching a recurring accessibility event in milliseconds.
+     * This delay guarantees that a recurring event will be send at most once
+     * during the {@link #SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS} time
+     * frame.
+     */
+    private static final long SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS = 400;
+
+    /**
      * The maximum size of View's drawing cache, expressed in bytes. This size
      * should be at least equal to the size of the screen in ARGB888 format.
      */
@@ -211,6 +221,9 @@
     private final int mOverscrollDistance;
     private final int mOverflingDistance;
 
+    private boolean sHasPermanentMenuKey;
+    private boolean sHasPermanentMenuKeySet;
+
     private static final SparseArray<ViewConfiguration> sConfigurations =
             new SparseArray<ViewConfiguration>(2);
 
@@ -246,11 +259,12 @@
      * @see android.util.DisplayMetrics
      */
     private ViewConfiguration(Context context) {
-        final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+        final Resources res = context.getResources();
+        final DisplayMetrics metrics = res.getDisplayMetrics();
+        final Configuration config = res.getConfiguration();
         final float density = metrics.density;
         final float sizeAndDensity;
-        if (context.getResources().getConfiguration().isLayoutSizeAtLeast(
-                Configuration.SCREENLAYOUT_SIZE_XLARGE)) {
+        if (config.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_XLARGE)) {
             sizeAndDensity = density * 1.5f;
         } else {
             sizeAndDensity = density;
@@ -272,6 +286,17 @@
 
         mOverscrollDistance = (int) (sizeAndDensity * OVERSCROLL_DISTANCE + 0.5f);
         mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f);
+
+        if (!sHasPermanentMenuKeySet) {
+            IWindowManager wm = Display.getWindowManager();
+            try {
+                sHasPermanentMenuKey = wm.canStatusBarHide() && !res.getBoolean(
+                        com.android.internal.R.bool.config_showNavigationBar);
+                sHasPermanentMenuKeySet = true;
+            } catch (RemoteException ex) {
+                sHasPermanentMenuKey = false;
+            }
+        }
     }
 
     /**
@@ -498,6 +523,19 @@
     }
 
     /**
+     * Interval for dispatching a recurring accessibility event in milliseconds.
+     * This interval guarantees that a recurring event will be send at most once
+     * during the {@link #getSendRecurringAccessibilityEventsInterval()} time frame.
+     *
+     * @return The delay in milliseconds.
+     *
+     * @hide
+     */
+    public static long getSendRecurringAccessibilityEventsInterval() {
+        return SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS;
+    }
+
+    /**
      * @return Distance a touch must be outside the bounds of a window for it
      * to be counted as outside the window for purposes of dismissing that
      * window.
@@ -619,4 +657,20 @@
     public static float getScrollFriction() {
         return SCROLL_FRICTION;
     }
+
+    /**
+     * Report if the device has a permanent menu key available to the user.
+     *
+     * <p>As of Android 3.0, devices may not have a permanent menu key available.
+     * Apps should use the action bar to present menu options to users.
+     * However, there are some apps where the action bar is inappropriate
+     * or undesirable. This method may be used to detect if a menu key is present.
+     * If not, applications should provide another on-screen affordance to access
+     * functionality.
+     *
+     * @return true if a permanent menu key is present, false otherwise.
+     */
+    public boolean hasPermanentMenuKey() {
+        return sHasPermanentMenuKey;
+    }
 }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index a21f8bb..752fd5a 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1745,6 +1745,7 @@
                 final long now = SystemClock.uptimeMillis();
                 event = MotionEvent.obtain(now, now,
                         MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
+                event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
                 syntheticEvent = true;
             }
 
@@ -4997,20 +4998,61 @@
         viewAncestor.requestTransitionStart(transition);
     }
 
-    /**
-     * This method will be called when we need to reset the layout direction resolution flag
-     *
-     */
     @Override
-    void resetLayoutDirectionResolution() {
-        super.resetLayoutDirectionResolution();
+    protected void resetResolvedLayoutDirection() {
+        super.resetResolvedLayoutDirection();
 
         // Take care of resetting the children resolution too
         final int count = getChildCount();
         for (int i = 0; i < count; i++) {
             final View child = getChildAt(i);
             if (child.getLayoutDirection() == LAYOUT_DIRECTION_INHERIT) {
-                child.resetLayoutDirectionResolution();
+                child.resetResolvedLayoutDirection();
+            }
+        }
+    }
+
+    /**
+     * This method will be called during text direction resolution (text direction resolution
+     * inheritance)
+     */
+    @Override
+    protected void resolveTextDirection() {
+        int resolvedTextDirection;
+        switch(mTextDirection) {
+            default:
+            case TEXT_DIRECTION_INHERIT:
+                // Try to the text direction from the parent layout
+                if (mParent != null && mParent instanceof ViewGroup) {
+                    resolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection();
+                } else {
+                    // We reached the top of the View hierarchy, so set the text direction
+                    // heuristic to "first strong"
+                    resolvedTextDirection = TEXT_DIRECTION_FIRST_STRONG;
+                }
+                break;
+            // Pass down the hierarchy the following text direction values
+            case TEXT_DIRECTION_FIRST_STRONG:
+            case TEXT_DIRECTION_ANY_RTL:
+            case TEXT_DIRECTION_CHAR_COUNT:
+            case TEXT_DIRECTION_LTR:
+            case TEXT_DIRECTION_RTL:
+                resolvedTextDirection = mTextDirection;
+                break;
+        }
+        mResolvedTextDirection = resolvedTextDirection;
+    }
+
+    @Override
+    protected void resetResolvedTextDirection() {
+        super.resetResolvedTextDirection();
+
+        // Take care of resetting the children resolution too
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.getTextDirection() == TEXT_DIRECTION_INHERIT) {
+                child.resetResolvedTextDirection();
             }
         }
     }
@@ -5175,6 +5217,21 @@
         }
 
         /**
+         * Resolve layout parameters depending on the layout direction. Subclasses that care about
+         * layoutDirection changes should override this method. The default implementation does
+         * nothing.
+         *
+         * @param layoutDirection the direction of the layout
+         *
+         * {@link View#LAYOUT_DIRECTION_LTR}
+         * {@link View#LAYOUT_DIRECTION_RTL}
+         *
+         * @hide
+         */
+        protected void resolveWithDirection(int layoutDirection) {
+        }
+
+        /**
          * Returns a String representation of this set of layout parameters.
          *
          * @param output the String to prepend to the internal representation
@@ -5215,30 +5272,56 @@
      */
     public static class MarginLayoutParams extends ViewGroup.LayoutParams {
         /**
-         * The left margin in pixels of the child.
+         * The left margin in pixels of the child. Whenever this value is changed, a call to
+         * {@link android.view.View#requestLayout()} needs to be done.
          */
         @ViewDebug.ExportedProperty(category = "layout")
         public int leftMargin;
 
         /**
-         * The top margin in pixels of the child.
+         * The top margin in pixels of the child. Whenever this value is changed, a call to
+         * {@link android.view.View#requestLayout()} needs to be done.
          */
         @ViewDebug.ExportedProperty(category = "layout")
         public int topMargin;
 
         /**
-         * The right margin in pixels of the child.
+         * The right margin in pixels of the child. Whenever this value is changed, a call to
+         * {@link android.view.View#requestLayout()} needs to be done.
          */
         @ViewDebug.ExportedProperty(category = "layout")
         public int rightMargin;
 
         /**
-         * The bottom margin in pixels of the child.
+         * The bottom margin in pixels of the child. Whenever this value is changed, a call to
+         * {@link android.view.View#requestLayout()} needs to be done.
          */
         @ViewDebug.ExportedProperty(category = "layout")
         public int bottomMargin;
 
         /**
+         * The start margin in pixels of the child.
+         *
+         * @hide
+         *
+         */
+        @ViewDebug.ExportedProperty(category = "layout")
+        protected int startMargin = DEFAULT_RELATIVE;
+
+        /**
+         * The end margin in pixels of the child.
+         *
+         * @hide
+         */
+        @ViewDebug.ExportedProperty(category = "layout")
+        protected int endMargin = DEFAULT_RELATIVE;
+
+        /**
+         * The default start and end margin.
+         */
+        static private final int DEFAULT_RELATIVE = Integer.MIN_VALUE;
+
+        /**
          * Creates a new set of layout parameters. The values are extracted from
          * the supplied attributes set and context.
          *
@@ -5270,6 +5353,10 @@
                         R.styleable.ViewGroup_MarginLayout_layout_marginRight, 0);
                 bottomMargin = a.getDimensionPixelSize(
                         R.styleable.ViewGroup_MarginLayout_layout_marginBottom, 0);
+                startMargin = a.getDimensionPixelSize(
+                        R.styleable.ViewGroup_MarginLayout_layout_marginStart, DEFAULT_RELATIVE);
+                endMargin = a.getDimensionPixelSize(
+                        R.styleable.ViewGroup_MarginLayout_layout_marginEnd, DEFAULT_RELATIVE);
             }
 
             a.recycle();
@@ -5295,6 +5382,8 @@
             this.topMargin = source.topMargin;
             this.rightMargin = source.rightMargin;
             this.bottomMargin = source.bottomMargin;
+            this.startMargin = source.startMargin;
+            this.endMargin = source.endMargin;
         }
 
         /**
@@ -5305,7 +5394,9 @@
         }
 
         /**
-         * Sets the margins, in pixels.
+         * Sets the margins, in pixels. A call to {@link android.view.View#requestLayout()} needs
+         * to be done so that the new margins are taken into account. Left and right margins may be
+         * overriden by {@link android.view.View#requestLayout()} depending on layout direction.
          *
          * @param left the left margin size
          * @param top the top margin size
@@ -5323,6 +5414,92 @@
             rightMargin = right;
             bottomMargin = bottom;
         }
+
+        /**
+         * Sets the relative margins, in pixels. A call to {@link android.view.View#requestLayout()}
+         * needs to be done so that the new relative margins are taken into account. Left and right
+         * margins may be overriden by {@link android.view.View#requestLayout()} depending on layout
+         * direction.
+         *
+         * @param start the start margin size
+         * @param top the top margin size
+         * @param end the right margin size
+         * @param bottom the bottom margin size
+         *
+         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
+         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginTop
+         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
+         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginBottom
+         *
+         * @hide
+         */
+        public void setMarginsRelative(int start, int top, int end, int bottom) {
+            startMargin = start;
+            topMargin = top;
+            endMargin = end;
+            bottomMargin = bottom;
+        }
+
+        /**
+         * Returns the start margin in pixels.
+         *
+         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
+         *
+         * @return the start margin in pixels.
+         *
+         * @hide
+         */
+        public int getMarginStart() {
+            return startMargin;
+        }
+
+        /**
+         * Returns the end margin in pixels.
+         *
+         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
+         *
+         * @return the end margin in pixels.
+         *
+         * @hide
+         */
+        public int getMarginEnd() {
+            return endMargin;
+        }
+
+        /**
+         * Check if margins are relative.
+         *
+         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
+         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
+         *
+         * @return true if either marginStart or marginEnd has been set
+         *
+         * @hide
+         */
+        public boolean isMarginRelative() {
+            return (startMargin != DEFAULT_RELATIVE) || (endMargin != DEFAULT_RELATIVE);
+        }
+
+        /**
+         * This will be called by {@link android.view.View#requestLayout()}. Left and Right margins
+         * maybe overriden depending on layout direction.
+         *
+         * @hide
+         */
+        @Override
+        protected void resolveWithDirection(int layoutDirection) {
+            switch(layoutDirection) {
+                case View.LAYOUT_DIRECTION_RTL:
+                    leftMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : leftMargin;
+                    rightMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : rightMargin;
+                    break;
+                case View.LAYOUT_DIRECTION_LTR:
+                default:
+                    leftMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : leftMargin;
+                    rightMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : rightMargin;
+                    break;
+            }
+        }
     }
 
     /* Describes a touched view and the ids of the pointers that it has captured.
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 30d6489..ac86769 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -25,150 +25,239 @@
 import java.util.List;
 
 /**
+ * <p>
  * This class represents accessibility events that are sent by the system when
  * something notable happens in the user interface. For example, when a
  * {@link android.widget.Button} is clicked, a {@link android.view.View} is focused, etc.
+ * </p>
  * <p>
  * An accessibility event is fired by an individual view which populates the event with
- * a record for its state and requests from its parent to send the event to interested
- * parties. The parent can optionally add a record for itself before dispatching a similar
- * request to its parent. A parent can also choose not to respect the request for sending
- * an event. The accessibility event is sent by the topmost view in the view tree.
- * Therefore, an {@link android.accessibilityservice.AccessibilityService} can explore
- * all records in an accessibility event to obtain more information about the context
- * in which the event was fired.
+ * data for its state and requests from its parent to send the event to interested
+ * parties. The parent can optionally add an {@link AccessibilityRecord} for itself before
+ * dispatching a similar request to its parent. A parent can also choose not to respect the
+ * request for sending an event. The accessibility event is sent by the topmost view in the
+ * view tree. Therefore, an {@link android.accessibilityservice.AccessibilityService} can
+ * explore all records in an accessibility event to obtain more information about the
+ * context in which the event was fired.
+ * </p>
  * <p>
- * A client can add, remove, and modify records. The getters and setters for individual
- * properties operate on the current record which can be explicitly set by the client. By
- * default current is the first record. Thus, querying a record would require setting
- * it as the current one and interacting with the property getters and setters.
+ * The main purpose of an accessibility event is to expose enough information for an
+ * {@link android.accessibilityservice.AccessibilityService} to provide meaningful feedback
+ * to the user. Sometimes however, an accessibility service may need more contextual
+ * information then the one in the event pay-load. In such cases the service can obtain
+ * the event source which is an {@link AccessibilityNodeInfo} (snapshot of a View state)
+ * which can be used for exploring the window content. Note that the privilege for accessing
+ * an event's source, thus the window content, has to be explicitly requested. For more
+ * details refer to {@link android.accessibilityservice.AccessibilityService}. If an
+ * accessibility service has not requested to retrieve the window content the event will
+ * not contain reference to its source. Also for events of type
+ * {@link #TYPE_NOTIFICATION_STATE_CHANGED} the source is never available.
+ * </p>
  * <p>
  * This class represents various semantically different accessibility event
- * types. Each event type has associated a set of related properties. In other
+ * types. Each event type has an associated set of related properties. In other
  * words, each event type is characterized via a subset of the properties exposed
  * by this class. For each event type there is a corresponding constant defined
- * in this class. Since some event types are semantically close there are mask
- * constants that group them together. Follows a specification of the event
- * types and their associated properties:
+ * in this class. Follows a specification of the event types and their associated properties:
+ * </p>
  * <p>
- * <b>VIEW TYPES</b> <br>
+ * <b>VIEW TYPES</b></br>
+ * </p>
  * <p>
  * <b>View clicked</b> - represents the event of clicking on a {@link android.view.View}
- * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br>
- * Type:{@link #TYPE_VIEW_CLICKED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.</br>
+ * <em>Type:</em>{@link #TYPE_VIEW_CLICKED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ *   <li>{@link #isPassword()} - Whether the source is password.</li>
+ *   <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * </ul>
+ * </p>
  * <p>
  * <b>View long clicked</b> - represents the event of long clicking on a {@link android.view.View}
- * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br>
- * Type:{@link #TYPE_VIEW_LONG_CLICKED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc </br>
+ * <em>Type:</em>{@link #TYPE_VIEW_LONG_CLICKED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ *   <li>{@link #isPassword()} - Whether the source is password.</li>
+ *   <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * </ul>
+ * </p>
  * <p>
  * <b>View selected</b> - represents the event of selecting an item usually in
- * the context of an {@link android.widget.AdapterView}. <br>
- * Type: {@link #TYPE_VIEW_SELECTED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * the context of an {@link android.widget.AdapterView}.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_SELECTED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ *   <li>{@link #isPassword()} - Whether the source is password.</li>
+ *   <li>{@link #isChecked()} - Whether the source is checked.</li>
+ *   <li>{@link #getItemCount()} - The number of selectable items of the source.</li>
+ *   <li>{@link #getCurrentItemIndex()} - The currently selected item index.</li>
+ * </ul>
+ * </p>
  * <p>
  * <b>View focused</b> - represents the event of focusing a
- * {@link android.view.View}. <br>
- * Type: {@link #TYPE_VIEW_FOCUSED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * {@link android.view.View}.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_FOCUSED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ *   <li>{@link #isPassword()} - Whether the source is password.</li>
+ *   <li>{@link #isChecked()} - Whether the source is checked.</li>
+ *   <li>{@link #getItemCount()} - The number of focusable items on the screen.</li>
+ *   <li>{@link #getCurrentItemIndex()} - The currently focused item index.</li>
+ * </ul>
+ * </p>
  * <p>
  * <b>View text changed</b> - represents the event of changing the text of an
- * {@link android.widget.EditText}. <br>
- * Type: {@link #TYPE_VIEW_TEXT_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()},
- * {@link #getFromIndex()},
- * {@link #getAddedCount()},
- * {@link #getRemovedCount()},
- * {@link #getBeforeText()}
+ * {@link android.widget.EditText}.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_TEXT_CHANGED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ *   <li>{@link #isPassword()} - Whether the source is password.</li>
+ *   <li>{@link #isChecked()} - Whether the source is checked.</li>
+ *   <li>{@link #getFromIndex()} - The text change start index.</li>
+ *   <li>{@link #getAddedCount()} - The number of added characters.</li>
+ *   <li>{@link #getRemovedCount()} - The number of removed characters.</li>
+ *   <li>{@link #getBeforeText()} - The text of the source before the change.</li>
+ * </ul>
+ * </p>
  * <p>
- * <b>TRANSITION TYPES</b> <br>
+ * <b>View text selection changed</b> - represents the event of changing the text
+ * selection of an {@link android.widget.EditText}.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} </br>
+ * <em>Properties:</em></br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ *   <li>{@link #isPassword()} - Whether the source is password.</li>
+ *   <li>{@link #getFromIndex()} - The selection start index.</li>
+ *   <li>{@link #getToIndex()} - The selection end index.</li>
+ *   <li>{@link #getItemCount()} - The length of the source text.</li>
+ * </ul>
+ * </p>
  * <p>
+ * <b>View scrolled</b> - represents the event of scrolling a view. If
+ * the source is a descendant of {@link android.widget.AdapterView} the
+ * scroll is reported in terms of visible items - the first visible item,
+ * the last visible item, and the total items - because the the source
+ * is unaware if its pixel size since its adapter is responsible for
+ * creating views. In all other cases the scroll is reported as the current
+ * scroll on the X and Y axis respectively plus the height of the source in
+ * pixels.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_SCROLLED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ *   <li>{@link #getScrollX()} - The horizontal offset of the source
+ *                                (without descendants of AdapterView)).</li>
+ *   <li>{@link #getScrollY()} - The vertical offset of the source
+ *                                (without descendants of AdapterView)).</li>
+ *   <li>{@link #getFromIndex()} - The index of the first visible item of the source
+ *                                 (for descendants of AdapterView).</li>
+ *   <li>{@link #getToIndex()} - The index of the last visible item of the source
+ *                               (for descendants of AdapterView).</li>
+ *   <li>{@link #getItemCount()} - The total items of the source (for descendants of AdapterView)
+ *                                 or the height of the source in pixels (all other cases).</li>
+ * </ul>
+ * </p>
+ * <p>
+ * <b>TRANSITION TYPES</b></br>
+ * </p>
  * <b>Window state changed</b> - represents the event of opening a
  * {@link android.widget.PopupWindow}, {@link android.view.Menu},
- * {@link android.app.Dialog}, etc. <br>
- * Type: {@link #TYPE_WINDOW_STATE_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()}
+ * {@link android.app.Dialog}, etc.</br>
+ * <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ * </ul>
+ * </p>
  * <p>
  * <b>Window content changed</b> - represents the event of change in the
  * content of a window. This change can be adding/removing view, changing
- * a view size, etc.<br>
- * Type: {@link #TYPE_WINDOW_CONTENT_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()}
+ * a view size, etc.</br>
  * <p>
- * <b>NOTIFICATION TYPES</b> <br>
+ * <strong>Note:</strong> This event is fired only for the window source of the
+ * last accessibility event different from {@link #TYPE_NOTIFICATION_STATE_CHANGED})
+ * and its purpose is to notify clients that the content of the user interaction
+ * window has changed.
+ * </p>
+ * <em>Type:</em> {@link #TYPE_WINDOW_CONTENT_CHANGED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ *   <li>{@link #getSource()} - The source info (for registered clients).</li>
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ * </ul>
  * <p>
- * <b>Notification state changed</b> - represents the event showing/hiding
+ * <b>NOTIFICATION TYPES</b></br>
+ * <p>
+ * <b>Notification state changed</b> - represents the event showing
  * {@link android.app.Notification}.
- * Type: {@link #TYPE_NOTIFICATION_STATE_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()}
- * {@link #getParcelableData()}
+ * <em>Type:</em> {@link #TYPE_NOTIFICATION_STATE_CHANGED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ *   <li>{@link #getClassName()} - The class name of the source.</li>
+ *   <li>{@link #getPackageName()} - The package name of the source.</li>
+ *   <li>{@link #getEventTime()}  - The event time.</li>
+ *   <li>{@link #getText()} - The text of the source.</li>
+ *   <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}.</li>
+ * </ul>
+ * </p>
  * <p>
  * <b>Security note</b>
  * <p>
- * Since an event contains the text of its source privacy can be compromised by leaking of
+ * Since an event contains the text of its source privacy can be compromised by leaking
  * sensitive information such as passwords. To address this issue any event fired in response
  * to manipulation of a PASSWORD field does NOT CONTAIN the text of the password.
  *
  * @see android.view.accessibility.AccessibilityManager
  * @see android.accessibilityservice.AccessibilityService
+ * @see AccessibilityNodeInfo
  */
 public final class AccessibilityEvent extends AccessibilityRecord implements Parcelable {
     private static final boolean DEBUG = false;
@@ -222,13 +311,13 @@
     public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010;
 
     /**
-     * Represents the event of opening/closing a {@link android.widget.PopupWindow},
+     * Represents the event of opening a {@link android.widget.PopupWindow},
      * {@link android.view.Menu}, {@link android.app.Dialog}, etc.
      */
     public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020;
 
     /**
-     * Represents the event showing/hiding a {@link android.app.Notification}.
+     * Represents the event showing a {@link android.app.Notification}.
      */
     public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040;
 
@@ -258,6 +347,16 @@
     public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;
 
     /**
+     * Represents the event of scrolling a view.
+     */
+    public static final int TYPE_VIEW_SCROLLED = 0x00001000;
+
+    /**
+     * Represents the event of changing the selection in an {@link android.widget.EditText}.
+     */
+    public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000;
+
+    /**
      * Mask for {@link AccessibilityEvent} all types.
      *
      * @see #TYPE_VIEW_CLICKED
@@ -267,6 +366,13 @@
      * @see #TYPE_VIEW_TEXT_CHANGED
      * @see #TYPE_WINDOW_STATE_CHANGED
      * @see #TYPE_NOTIFICATION_STATE_CHANGED
+     * @see #TYPE_VIEW_HOVER_ENTER
+     * @see #TYPE_VIEW_HOVER_EXIT
+     * @see #TYPE_TOUCH_EXPLORATION_GESTURE_START
+     * @see #TYPE_TOUCH_EXPLORATION_GESTURE_END
+     * @see #TYPE_WINDOW_CONTENT_CHANGED
+     * @see #TYPE_VIEW_SCROLLED
+     * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED
      */
     public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
 
@@ -359,10 +465,10 @@
     }
 
     /**
-     * Gets the records at a given index.
+     * Gets the record at a given index.
      *
      * @param index The index.
-     * @return The records at the specified index.
+     * @return The record at the specified index.
      */
     public AccessibilityRecord getRecord(int index) {
         return mRecords.get(index);
@@ -433,7 +539,7 @@
 
     /**
      * Returns a cached instance if such is available or a new one is
-     * instantiated with type property set.
+     * instantiated with its type property set.
      *
      * @param eventType The event type.
      * @return An instance.
@@ -446,7 +552,7 @@
 
     /**
      * Returns a cached instance if such is available or a new one is
-     * instantiated with type property set.
+     * initialized with from the given <code>event</code>.
      *
      * @param event The other event.
      * @return An instance.
@@ -486,9 +592,10 @@
     }
 
     /**
-     * Return an instance back to be reused.
+     * Recycles an instance back to be reused.
      * <p>
-     * <b>Note: You must not touch the object after calling this function.</b>
+     *   <b>Note: You must not touch the object after calling this function.</b>
+     * </p>
      *
      * @throws IllegalStateException If the event is already recycled.
      */
@@ -564,6 +671,9 @@
         record.mCurrentItemIndex = parcel.readInt();
         record.mItemCount = parcel.readInt();
         record.mFromIndex = parcel.readInt();
+        record.mToIndex = parcel.readInt();
+        record.mScrollX = parcel.readInt();
+        record.mScrollY =  parcel.readInt();
         record.mAddedCount = parcel.readInt();
         record.mRemovedCount = parcel.readInt();
         record.mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
@@ -613,6 +723,9 @@
         parcel.writeInt(record.mCurrentItemIndex);
         parcel.writeInt(record.mItemCount);
         parcel.writeInt(record.mFromIndex);
+        parcel.writeInt(record.mToIndex);
+        parcel.writeInt(record.mScrollX);
+        parcel.writeInt(record.mScrollY);
         parcel.writeInt(record.mAddedCount);
         parcel.writeInt(record.mRemovedCount);
         TextUtils.writeToParcel(record.mClassName, parcel, flags);
@@ -635,7 +748,7 @@
     @Override
     public String toString() {
         StringBuilder builder = new StringBuilder();
-        builder.append("; EventType: ").append(eventTypeToString(mEventType));
+        builder.append("EventType: ").append(eventTypeToString(mEventType));
         builder.append("; EventTime: ").append(mEventTime);
         builder.append("; PackageName: ").append(mPackageName);
         builder.append(super.toString());
@@ -657,8 +770,12 @@
                 builder.append("; IsPassword: " + record.isPassword());
                 builder.append("; IsChecked: " + record.isChecked());
                 builder.append("; IsFullScreen: " + record.isFullScreen());
+                builder.append("; Scrollable: " + record.isScrollable());
                 builder.append("; BeforeText: " + record.mBeforeText);
                 builder.append("; FromIndex: " + record.mFromIndex);
+                builder.append("; ToIndex: " + record.mToIndex);
+                builder.append("; ScrollX: " + record.mScrollX);
+                builder.append("; ScrollY: " + record.mScrollY);
                 builder.append("; AddedCount: " + record.mAddedCount);
                 builder.append("; RemovedCount: " + record.mRemovedCount);
                 builder.append("; ParcelableData: " + record.mParcelableData);
@@ -675,11 +792,11 @@
      * Returns the string representation of an event type. For example,
      * {@link #TYPE_VIEW_CLICKED} is represented by the string TYPE_VIEW_CLICKED.
      *
-     * @param feedbackType The event type
+     * @param eventType The event type
      * @return The string representation.
      */
-    public static String eventTypeToString(int feedbackType) {
-        switch (feedbackType) {
+    public static String eventTypeToString(int eventType) {
+        switch (eventType) {
             case TYPE_VIEW_CLICKED:
                 return "TYPE_VIEW_CLICKED";
             case TYPE_VIEW_LONG_CLICKED:
@@ -704,6 +821,10 @@
                 return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
             case TYPE_WINDOW_CONTENT_CHANGED:
                 return "TYPE_WINDOW_CONTENT_CHANGED";
+            case TYPE_VIEW_TEXT_SELECTION_CHANGED:
+                return "TYPE_VIEW_TEXT_SELECTION_CHANGED";
+            case TYPE_VIEW_SCROLLED:
+                return "TYPE_VIEW_SCROLLED";
             default:
                 return null;
         }
diff --git a/core/java/android/view/accessibility/AccessibilityEventSource.java b/core/java/android/view/accessibility/AccessibilityEventSource.java
index 3d70959..f11880b 100644
--- a/core/java/android/view/accessibility/AccessibilityEventSource.java
+++ b/core/java/android/view/accessibility/AccessibilityEventSource.java
@@ -24,11 +24,12 @@
     /**
      * Handles the request for sending an {@link AccessibilityEvent} given
      * the event type. The method must first check if accessibility is on
-     * via calling {@link AccessibilityManager#isEnabled()}, obtain
-     * an {@link AccessibilityEvent} from the event pool through calling
-     * {@link AccessibilityEvent#obtain(int)}, populate the event, and
-     * send it for dispatch via calling
-     * {@link AccessibilityManager#sendAccessibilityEvent(AccessibilityEvent)}.
+     * via calling {@link AccessibilityManager#isEnabled() AccessibilityManager.isEnabled()},
+     * obtain an {@link AccessibilityEvent} from the event pool through calling
+     * {@link AccessibilityEvent#obtain(int) AccessibilityEvent.obtain(int)}, populate the
+     * event, and send it for dispatch via calling
+     * {@link AccessibilityManager#sendAccessibilityEvent(AccessibilityEvent)
+     * AccessibilityManager.sendAccessibilityEvent(AccessibilityEvent)}.
      *
      * @see AccessibilityEvent
      * @see AccessibilityManager
@@ -41,7 +42,8 @@
      * Handles the request for sending an {@link AccessibilityEvent}. The
      * method does not guarantee to check if accessibility is on before
      * sending the event for dispatch. It is responsibility of the caller
-     * to do the check via calling {@link AccessibilityManager#isEnabled()}.
+     * to do the check via calling {@link AccessibilityManager#isEnabled()
+     * AccessibilityManager.isEnabled()}.
      *
      * @see AccessibilityEvent
      * @see AccessibilityManager
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index eece64a..314b7ca 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -37,16 +37,30 @@
 import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
- * System level service that serves as an event dispatch for {@link AccessibilityEvent}s.
- * Such events are generated when something notable happens in the user interface,
+ * System level service that serves as an event dispatch for {@link AccessibilityEvent}s,
+ * and provides facilities for querying the accessibility state of the system.
+ * Accessibility events are generated when something notable happens in the user interface,
  * for example an {@link android.app.Activity} starts, the focus or selection of a
  * {@link android.view.View} changes etc. Parties interested in handling accessibility
  * events implement and register an accessibility service which extends
  * {@link android.accessibilityservice.AccessibilityService}.
+ * <p>
+ * To obtain a handle to the accessibility manager do the following:
+ * </p>
+ * <p>
+ * <code>
+ * <pre>
+ *   AccessibilityManager accessibilityManager =
+ *           (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ * </pre>
+ * </code>
+ * </p>
  *
  * @see AccessibilityEvent
+ * @see AccessibilityNodeInfo
  * @see android.accessibilityservice.AccessibilityService
- * @see android.content.Context#getSystemService
+ * @see Context#getSystemService
+ * @see Context#ACCESSIBILITY_SERVICE
  */
 public final class AccessibilityManager {
     private static final boolean DEBUG = false;
@@ -72,10 +86,11 @@
      * Listener for the accessibility state.
      */
     public interface AccessibilityStateChangeListener {
+
         /**
          * Called back on change in the accessibility state.
          *
-         * @param enabled
+         * @param enabled Whether accessibility is enabled.
          */
         public void onAccessibilityStateChanged(boolean enabled);
     }
@@ -142,9 +157,9 @@
     }
 
     /**
-     * Returns if the {@link AccessibilityManager} is enabled.
+     * Returns if the accessibility in the system is enabled.
      *
-     * @return True if this {@link AccessibilityManager} is enabled, false otherwise.
+     * @return True if accessibility is enabled, false otherwise.
      */
     public boolean isEnabled() {
         synchronized (mHandler) {
@@ -161,17 +176,15 @@
      * @hide
      */
     public IAccessibilityManagerClient getClient() {
-       return (IAccessibilityManagerClient) mClient.asBinder(); 
+       return (IAccessibilityManagerClient) mClient.asBinder();
     }
 
     /**
-     * Sends an {@link AccessibilityEvent}. If this {@link AccessibilityManager} is not
-     * enabled the call is a NOOP.
+     * Sends an {@link AccessibilityEvent}.
      *
-     * @param event The {@link AccessibilityEvent}.
+     * @param event The event to send.
      *
-     * @throws IllegalStateException if a client tries to send an {@link AccessibilityEvent}
-     *         while accessibility is not enabled.
+     * @throws IllegalStateException if accessibility is not enabled.
      */
     public void sendAccessibilityEvent(AccessibilityEvent event) {
         if (!mIsEnabled) {
@@ -199,7 +212,7 @@
     }
 
     /**
-     * Requests interruption of the accessibility feedback from all accessibility services.
+     * Requests feedback interruption from all accessibility services.
      */
     public void interrupt() {
         if (!mIsEnabled) {
@@ -256,13 +269,20 @@
      * Returns the {@link AccessibilityServiceInfo}s of the enabled accessibility services
      * for a given feedback type.
      *
-     * @param feedbackType The feedback type (can be bitwise or of multiple types).
+     * @param feedbackTypeFlags The feedback type flags.
      * @return An unmodifiable list with {@link AccessibilityServiceInfo}s.
+     *
+     * @see AccessibilityServiceInfo#FEEDBACK_AUDIBLE
+     * @see AccessibilityServiceInfo#FEEDBACK_GENERIC
+     * @see AccessibilityServiceInfo#FEEDBACK_HAPTIC
+     * @see AccessibilityServiceInfo#FEEDBACK_SPOKEN
+     * @see AccessibilityServiceInfo#FEEDBACK_VISUAL
      */
-    public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType) {
+    public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(
+            int feedbackTypeFlags) {
         List<AccessibilityServiceInfo> services = null;
         try {
-            services = mService.getEnabledAccessibilityServiceList(feedbackType);
+            services = mService.getEnabledAccessibilityServiceList(feedbackTypeFlags);
             if (DEBUG) {
                 Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
             }
@@ -273,7 +293,8 @@
     }
 
     /**
-     * Registers an {@link AccessibilityStateChangeListener}.
+     * Registers an {@link AccessibilityStateChangeListener} for changes in
+     * the global accessibility state of the system.
      *
      * @param listener The listener.
      * @return True if successfully registered.
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 555667b..031c6ae 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -22,7 +22,6 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.text.TextUtils;
-import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.view.View;
 
@@ -30,12 +29,26 @@
 import java.util.List;
 
 /**
- * This class represents a node of the screen content. From the point of
- * view of an accessibility service the screen content is presented as tree
- * of accessibility nodes.
+ * This class represents a node of the window content as well as actions that
+ * can be requested from its source. From the point of view of an
+ * {@link android.accessibilityservice.AccessibilityService} a window content is
+ * presented as tree of accessibility node info which may or may not map one-to-one
+ * to the view hierarchy. In other words, a custom view is free to report itself as
+ * a tree of accessibility node info.
+ * </p>
+ * <p>
+ * Once an accessibility node info is delivered to an accessibility service it is
+ * made immutable and calling a state mutation method generates an error.
+ * </p>
+ * <p>
+ * Please refer to {@link android.accessibilityservice.AccessibilityService} for
+ * details about how to obtain a handle to window content as a tree of accessibility
+ * node info as well as familiarizing with the security model.
+ * </p>
  *
- * TODO(svertoslavganov): Update the documentation, add sample, and describe
- *                        the security policy.
+ * @see android.accessibilityservice.AccessibilityService
+ * @see AccessibilityEvent
+ * @see AccessibilityManager
  */
 public class AccessibilityNodeInfo implements Parcelable {
 
@@ -83,8 +96,7 @@
 
     private static final int PROPERTY_PASSWORD = 0x00000100;
 
-    // Readable representations - lazily initialized.
-    private static SparseArray<String> sActionSymbolicNames;
+    private static final int PROPERTY_SCROLLABLE = 0x00000200;
 
     // Housekeeping.
     private static final int MAX_POOL_SIZE = 50;
@@ -152,12 +164,11 @@
     /**
      * Get the child at given index.
      * <p>
-     *   <strong>
-     *     It is a client responsibility to recycle the received info by
-     *     calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
-     *     of multiple instances.
-     *   </strong>
+     *   <strong>Note:</strong> It is a client responsibility to recycle the
+     *     received info by calling {@link AccessibilityNodeInfo#recycle()}
+     *     to avoid creating of multiple instances.
      * </p>
+     *
      * @param index The child index.
      * @return The child node.
      *
@@ -182,9 +193,11 @@
     /**
      * Adds a child.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param child The child.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -213,9 +226,11 @@
     /**
      * Adds an action that can be performed on the node.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param action The action.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -228,9 +243,10 @@
     /**
      * Performs an action on the node.
      * <p>
-     *   Note: An action can be performed only if the request is made
+     *   <strong>Note:</strong> An action can be performed only if the request is made
      *   from an {@link android.accessibilityservice.AccessibilityService}.
      * </p>
+     *
      * @param action The action to perform.
      * @return True if the action was performed.
      *
@@ -254,6 +270,11 @@
      * Finds {@link AccessibilityNodeInfo}s by text. The match is case
      * insensitive containment. The search is relative to this info i.e.
      * this info is the root of the traversed tree.
+     * <p>
+     *   <strong>Note:</strong> It is a client responsibility to recycle the
+     *     received info by calling {@link AccessibilityNodeInfo#recycle()}
+     *     to avoid creating of multiple instances.
+     * </p>
      *
      * @param text The searched text.
      * @return A list of node info.
@@ -275,12 +296,11 @@
     /**
      * Gets the unique id identifying this node's parent.
      * <p>
-     *   <strong>
-     *     It is a client responsibility to recycle the received info by
-     *     calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
-     *     of multiple instances.
-     *   </strong>
+     *   <strong>Note:</strong> It is a client responsibility to recycle the
+     *     received info by calling {@link AccessibilityNodeInfo#recycle()}
+     *     to avoid creating of multiple instances.
      * </p>
+     *
      * @return The node's patent id.
      */
     public AccessibilityNodeInfo getParent() {
@@ -300,9 +320,11 @@
     /**
      * Sets the parent.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param parent The parent.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -325,9 +347,11 @@
     /**
      * Sets the node bounds in parent coordinates.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param bounds The node bounds.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -350,9 +374,11 @@
     /**
      * Sets the node bounds in screen coordinates.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param bounds The node bounds.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -374,9 +400,11 @@
     /**
      * Sets whether this node is checkable.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param checkable True if the node is checkable.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -397,9 +425,11 @@
     /**
      * Sets whether this node is checked.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param checked True if the node is checked.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -420,9 +450,11 @@
     /**
      * Sets whether this node is focusable.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param focusable True if the node is focusable.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -443,9 +475,11 @@
     /**
      * Sets whether this node is focused.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param focused True if the node is focused.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -466,9 +500,11 @@
     /**
      * Sets whether this node is selected.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param selected True if the node is selected.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -489,9 +525,11 @@
     /**
      * Sets whether this node is clickable.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param clickable True if the node is clickable.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -512,9 +550,11 @@
     /**
      * Sets whether this node is long clickable.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param longClickable True if the node is long clickable.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -535,9 +575,11 @@
     /**
      * Sets whether this node is enabled.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param enabled True if the node is enabled.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -558,9 +600,11 @@
     /**
      * Sets whether this node is a password.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param password True if the node is a password.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -570,6 +614,32 @@
     }
 
     /**
+     * Gets if the node is scrollable.
+     *
+     * @return True if the node is scrollable, false otherwise.
+     */
+    public boolean isScrollable() {
+        return getBooleanProperty(PROPERTY_SCROLLABLE);
+    }
+
+    /**
+     * Sets if the node is scrollable.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param scrollable True if the node is scrollable, false otherwise.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setScrollable(boolean scrollable) {
+        enforceNotSealed();
+        setBooleanProperty(PROPERTY_SCROLLABLE, scrollable);
+    }
+
+    /**
      * Gets the package this node comes from.
      *
      * @return The package name.
@@ -581,9 +651,11 @@
     /**
      * Sets the package this node comes from.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param packageName The package name.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -605,9 +677,11 @@
     /**
      * Sets the class this node comes from.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param className The class name.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -629,9 +703,11 @@
     /**
      * Sets the text of this node.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param text The text.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -653,9 +729,11 @@
     /**
      * Sets the content description of this node.
      * <p>
-     *   Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
      *   This class is made immutable before being delivered to an AccessibilityService.
      * </p>
+     *
      * @param contentDescription The content description.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -797,7 +875,7 @@
     /**
      * Return an instance back to be reused.
      * <p>
-     * <b>Note: You must not touch the object after calling this function.</b>
+     * <strong>Note:</strong> You must not touch the object after calling this function.
      *
      * @throws IllegalStateException If the info is already recycled.
      */
@@ -819,8 +897,8 @@
     /**
      * {@inheritDoc}
      * <p>
-     *   <b>Note: After the instance is written to a parcel it is recycled.
-     *      You must not touch the object after calling this function.</b>
+     *   <strong>Note:</strong> After the instance is written to a parcel it
+     *      is recycled. You must not touch the object after calling this function.
      * </p>
      */
     public void writeToParcel(Parcel parcel, int flags) {
@@ -862,7 +940,7 @@
         TextUtils.writeToParcel(mContentDescription, parcel, flags);
 
         // Since instances of this class are fetched via synchronous i.e. blocking
-        // calls in IPCs and we always recycle as soon as the instance is marshaled.
+        // calls in IPCs we always recycle as soon as the instance is marshaled.
         recycle();
     }
 
@@ -934,15 +1012,18 @@
      * @return The symbolic name.
      */
     private static String getActionSymbolicName(int action) {
-        SparseArray<String> actionSymbolicNames = sActionSymbolicNames;
-        if (actionSymbolicNames == null) {
-            actionSymbolicNames = sActionSymbolicNames = new SparseArray<String>();
-            actionSymbolicNames.put(ACTION_FOCUS, "ACTION_FOCUS");
-            actionSymbolicNames.put(ACTION_CLEAR_FOCUS, "ACTION_UNFOCUS");
-            actionSymbolicNames.put(ACTION_SELECT, "ACTION_SELECT");
-            actionSymbolicNames.put(ACTION_CLEAR_SELECTION, "ACTION_UNSELECT");
+        switch (action) {
+            case ACTION_FOCUS:
+                return "ACTION_FOCUS";
+            case ACTION_CLEAR_FOCUS:
+                return "ACTION_CLEAR_FOCUS";
+            case ACTION_SELECT:
+                return "ACTION_SELECT";
+            case ACTION_CLEAR_SELECTION:
+                return "ACTION_CLEAR_SELECTION";
+            default:
+                throw new IllegalArgumentException("Unknown action: " + action);
         }
-        return actionSymbolicNames.get(action);
     }
 
     private boolean canPerformRequestOverConnection(int accessibilityViewId) {
@@ -1017,6 +1098,7 @@
         builder.append("; longClickable: ").append(isLongClickable());
         builder.append("; enabled: ").append(isEnabled());
         builder.append("; password: ").append(isPassword());
+        builder.append("; scrollable: " + isScrollable());
 
         builder.append("; [");
 
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 9c495e2..f4d5e89 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -25,12 +25,28 @@
 import java.util.List;
 
 /**
- * Represents a record in an accessibility event. This class encapsulates
- * the information for a {@link android.view.View}. Note that not all properties
- * are applicable to all view types. For detailed information please refer to
- * {@link AccessibilityEvent}.
+ * Represents a record in an {@link AccessibilityEvent} and contains information
+ * about state change of its source {@link android.view.View}. When a view fires
+ * an accessibility event it requests from its parent to dispatch the
+ * constructed event. The parent may optionally append a record for itself
+ * for providing more context to
+ * {@link android.accessibilityservice.AccessibilityService}s. Hence,
+ * accessibility services can facilitate additional accessibility records
+ * to enhance feedback.
+ * </p>
+ * <p>
+ * Once the accessibility event containing a record is dispatched the record is
+ * made immutable and calling a state mutation method generates an error.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> Not all properties are applicable to all accessibility
+ * event types. For detailed information please refer to {@link AccessibilityEvent}.
+ * </p>
  *
  * @see AccessibilityEvent
+ * @see AccessibilityManager
+ * @see android.accessibilityservice.AccessibilityService
+ * @see AccessibilityNodeInfo
  */
 public class AccessibilityRecord {
 
@@ -40,6 +56,7 @@
     private static final int PROPERTY_ENABLED = 0x00000002;
     private static final int PROPERTY_PASSWORD = 0x00000004;
     private static final int PROPERTY_FULL_SCREEN = 0x00000080;
+    private static final int PROPERTY_SCROLLABLE = 0x00000100;
 
     // Housekeeping
     private static final int MAX_POOL_SIZE = 10;
@@ -54,6 +71,10 @@
     int mCurrentItemIndex;
     int mItemCount;
     int mFromIndex;
+    int mToIndex;
+    int mScrollX;
+    int mScrollY;
+
     int mAddedCount;
     int mRemovedCount;
     int mSourceViewId = View.NO_ID;
@@ -71,30 +92,6 @@
      * Hide constructor.
      */
     AccessibilityRecord() {
-
-    }
-
-    /**
-     * Initialize this record from another one.
-     *
-     * @param record The to initialize from.
-     */
-    void init(AccessibilityRecord record) {
-        mSealed = record.mSealed;
-        mBooleanProperties = record.mBooleanProperties;
-        mCurrentItemIndex = record.mCurrentItemIndex;
-        mItemCount = record.mItemCount;
-        mFromIndex = record.mFromIndex;
-        mAddedCount = record.mAddedCount;
-        mRemovedCount = record.mRemovedCount;
-        mClassName = record.mClassName;
-        mContentDescription = record.mContentDescription;
-        mBeforeText = record.mBeforeText;
-        mParcelableData = record.mParcelableData;
-        mText.addAll(record.mText);
-        mSourceWindowId = record.mSourceWindowId;
-        mSourceViewId = record.mSourceViewId;
-        mConnection = record.mConnection;
     }
 
     /**
@@ -118,13 +115,12 @@
     /**
      * Gets the {@link AccessibilityNodeInfo} of the event source.
      * <p>
-     *   <strong>
-     *     It is a client responsibility to recycle the received info by
-     *     calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
-     *     of multiple instances.
-     *   </strong>
+     *   <strong>Note:</strong> It is a client responsibility to recycle the received info
+     *   by calling {@link AccessibilityNodeInfo#recycle() AccessibilityNodeInfo#recycle()}
+     *   to avoid creating of multiple instances.
+     *
      * </p>
-     * @return The info.
+     * @return The info of the source.
      */
     public AccessibilityNodeInfo getSource() {
         enforceSealed();
@@ -246,6 +242,27 @@
     }
 
     /**
+     * Gets if the source is scrollable.
+     *
+     * @return True if the source is scrollable, false otherwise.
+     */
+    public boolean isScrollable() {
+        return getBooleanProperty(PROPERTY_SCROLLABLE);
+    }
+
+    /**
+     * Sets if the source is scrollable.
+     *
+     * @param scrollable True if the source is scrollable, false otherwise.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setScrollable(boolean scrollable) {
+        enforceNotSealed();
+        setBooleanProperty(PROPERTY_SCROLLABLE, scrollable);
+    }
+
+    /**
      * Gets the number of items that can be visited.
      *
      * @return The number of items.
@@ -288,18 +305,24 @@
     }
 
     /**
-     * Gets the index of the first character of the changed sequence.
+     * Gets the index of the first character of the changed sequence,
+     * or the beginning of a text selection or the index of the first
+     * visible item when scrolling.
      *
-     * @return The index of the first character.
+     * @return The index of the first character or selection
+     *        start or the first visible item.
      */
     public int getFromIndex() {
         return mFromIndex;
     }
 
     /**
-     * Sets the index of the first character of the changed sequence.
+     * Sets the index of the first character of the changed sequence
+     * or the beginning of a text selection or the index of the first
+     * visible item when scrolling.
      *
-     * @param fromIndex The index of the first character.
+     * @param fromIndex The index of the first character or selection
+     *        start or the first visible item.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
      */
@@ -309,6 +332,65 @@
     }
 
     /**
+     * Gets the index of text selection end or the index of the last
+     * visible item when scrolling.
+     *
+     * @return The index of selection end or last item index.
+     */
+    public int getToIndex() {
+        return mToIndex;
+    }
+
+    /**
+     * Sets the index of text selection end or the index of the last
+     * visible item when scrolling.
+     *
+     * @param toIndex The index of selection end or last item index.
+     */
+    public void setToIndex(int toIndex) {
+        enforceNotSealed();
+        mToIndex = toIndex;
+    }
+
+    /**
+     * Gets the scroll position of the source along the X axis.
+     *
+     * @return The scroll along the X axis.
+     */
+    public int getScrollX() {
+        return mScrollX;
+    }
+
+    /**
+     * Sets the scroll position of the source along the X axis.
+     *
+     * @param scrollX The scroll along the X axis.
+     */
+    public void setScrollX(int scrollX) {
+        enforceNotSealed();
+        mScrollX = scrollX;
+    }
+
+    /**
+     * Gets the scroll position of the source along the Y axis.
+     *
+     * @return The scroll along the Y axis.
+     */
+    public int getScrollY() {
+        return mScrollY;
+    }
+
+    /**
+     * Sets the scroll position of the source along the Y axis.
+     *
+     * @param scrollY The scroll along the Y axis.
+     */
+    public void setScrollY(int scrollY) {
+        enforceNotSealed();
+        mScrollY = scrollY;
+    }
+
+    /**
      * Gets the number of added characters.
      *
      * @return The number of added characters.
@@ -548,7 +630,7 @@
     /**
      * Return an instance back to be reused.
      * <p>
-     * <b>Note: You must not touch the object after calling this function.</b>
+     * <strong>Note:</strong> You must not touch the object after calling this function.
      *
      * @throws IllegalStateException If the record is already recycled.
      */
@@ -568,6 +650,32 @@
     }
 
     /**
+     * Initialize this record from another one.
+     *
+     * @param record The to initialize from.
+     */
+    void init(AccessibilityRecord record) {
+        mSealed = record.mSealed;
+        mBooleanProperties = record.mBooleanProperties;
+        mCurrentItemIndex = record.mCurrentItemIndex;
+        mItemCount = record.mItemCount;
+        mFromIndex = record.mFromIndex;
+        mToIndex = record.mToIndex;
+        mScrollX = record.mScrollX;
+        mScrollY = record.mScrollY;
+        mAddedCount = record.mAddedCount;
+        mRemovedCount = record.mRemovedCount;
+        mClassName = record.mClassName;
+        mContentDescription = record.mContentDescription;
+        mBeforeText = record.mBeforeText;
+        mParcelableData = record.mParcelableData;
+        mText.addAll(record.mText);
+        mSourceWindowId = record.mSourceWindowId;
+        mSourceViewId = record.mSourceViewId;
+        mConnection = record.mConnection;
+    }
+
+    /**
      * Clears the state of this instance.
      */
     void clear() {
@@ -576,6 +684,9 @@
         mCurrentItemIndex = INVALID_POSITION;
         mItemCount = 0;
         mFromIndex = 0;
+        mToIndex = 0;
+        mScrollX = 0;
+        mScrollY = 0;
         mAddedCount = 0;
         mRemovedCount = 0;
         mClassName = null;
@@ -599,8 +710,12 @@
         builder.append("; IsPassword: " + getBooleanProperty(PROPERTY_PASSWORD));
         builder.append("; IsChecked: " + getBooleanProperty(PROPERTY_CHECKED));
         builder.append("; IsFullScreen: " + getBooleanProperty(PROPERTY_FULL_SCREEN));
+        builder.append("; Scrollable: " + getBooleanProperty(PROPERTY_SCROLLABLE));
         builder.append("; BeforeText: " + mBeforeText);
         builder.append("; FromIndex: " + mFromIndex);
+        builder.append("; ToIndex: " + mToIndex);
+        builder.append("; ScrollX: " + mScrollX);
+        builder.append("; ScrollY: " + mScrollY);
         builder.append("; AddedCount: " + mAddedCount);
         builder.append("; RemovedCount: " + mRemovedCount);
         builder.append("; ParcelableData: " + mParcelableData);
diff --git a/core/java/android/view/accessibility/package.html b/core/java/android/view/accessibility/package.html
new file mode 100644
index 0000000..4afafd3
--- /dev/null
+++ b/core/java/android/view/accessibility/package.html
@@ -0,0 +1,39 @@
+<html>
+<body>
+<p>
+  The classes in this package are used to represent screen content and changes to it
+  as well as APIs for querying the global accessibility state of the system.
+</p>
+<p>
+  {@link android.view.accessibility.AccessibilityEvent}s are sent by the system when
+  something notable happens in the user interface. For example, when a
+  {@link android.widget.Button} is clicked, a {@link android.view.View} is focused, etc.
+</p>
+<p>
+  {@link android.view.accessibility.AccessibilityRecord} contains information
+  about state change of its source {@link android.view.View}. When a view fires
+  an accessibility event it requests from its parent to dispatch the
+  constructed event. The parent may optionally append a record for itself for
+  providing more context to {@link android.accessibilityservice.AccessibilityService}s.
+  Hence, accessibility services can facilitate additional accessibility records
+  to enhance feedback.
+</p>
+<p>
+  {@link android.view.accessibility.AccessibilityNodeInfo} represents a node of the
+  window content as well as actions that can be requested from its source. From the point
+  of view of an {@link android.accessibilityservice.AccessibilityService} a window content is
+  presented as tree of accessibility node info which may or may not map one-to-one
+  to the view hierarchy. In other words, a custom view is free to report itself as
+  a tree of accessibility node info.
+</p>
+<p>
+  {@link android.view.accessibility.AccessibilityManager} is a system level service that
+  serves as an event dispatch for  {@link android.view.accessibility.AccessibilityEvent}s,
+  and provides facilities for querying the accessibility state of the system. Accessibility
+  events are generated when something notable happens in the user interface, for example an
+  {@link android.app.Activity} starts, the focus or selection of a {@link android.view.View}
+  changes etc. Parties interested in handling accessibility events implement and register an
+  accessibility service which extends {@link android.accessibilityservice.AccessibilityService}.
+</p>
+</body>
+</html>
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 47f5e4c..a1a7281 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1126,7 +1126,7 @@
         if (mServedView == mNextServedView && !mNextServedNeedsStart) {
             return;
         }
-        
+
         InputConnection ic = null;
         synchronized (mH) {
             if (mServedView == mNextServedView && !mNextServedNeedsStart) {
@@ -1242,6 +1242,27 @@
     }
 
     /**
+     * Notify the event when the user tapped or clicked the text view.
+     */
+    public void viewClicked(View view) {
+        final boolean focusChanged = mServedView != mNextServedView;
+        checkFocus();
+        synchronized (mH) {
+            if ((mServedView != view && (mServedView == null
+                    || !mServedView.checkInputConnectionProxy(view)))
+                    || mCurrentTextBoxAttribute == null || mCurMethod == null) {
+                return;
+            }
+            try {
+                if (DEBUG) Log.v(TAG, "onViewClicked: " + focusChanged);
+                mCurMethod.viewClicked(focusChanged);
+            } catch (RemoteException e) {
+                Log.w(TAG, "IME died: " + mCurId, e);
+            }
+        }
+    }
+
+    /**
      * Returns true if the current input method wants to watch the location
      * of the input editor's cursor in its window.
      */
diff --git a/core/java/android/view/inputmethod/InputMethodSession.java b/core/java/android/view/inputmethod/InputMethodSession.java
index bb03afa..ea6f5ee 100644
--- a/core/java/android/view/inputmethod/InputMethodSession.java
+++ b/core/java/android/view/inputmethod/InputMethodSession.java
@@ -63,6 +63,15 @@
             int candidatesStart, int candidatesEnd);
 
     /**
+     * This method is called when the user tapped a text view.
+     * IMEs can't rely on this method being called because this was not part of the original IME
+     * protocol, so applications with custom text editing written before this method appeared will
+     * not call to inform the IME of this interaction.
+     * @param focusChanged true if the user changed the focused view by this click.
+     */
+    public void viewClicked(boolean focusChanged);
+
+    /**
      * This method is called when cursor location of the target input field
      * has changed within its window.  This is not normally called, but will
      * only be reported if requested by the input method.
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index 9d84c3e..4a98336 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -160,10 +160,10 @@
         if (mSubtypeNameResId == 0) {
             return localeStr;
         }
-        final String subtypeName = context.getPackageManager().getText(
-                packageName, mSubtypeNameResId, appInfo).toString();
+        final CharSequence subtypeName = context.getPackageManager().getText(
+                packageName, mSubtypeNameResId, appInfo);
         if (!TextUtils.isEmpty(subtypeName)) {
-            return String.format(subtypeName, localeStr);
+            return String.format(subtypeName.toString(), localeStr);
         } else {
             return localeStr;
         }
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 2f4774f..5aa60f4 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -50,8 +50,10 @@
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Map;
+import java.util.HashSet;
 import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
 
 import org.apache.harmony.security.provider.cert.X509CertImpl;
 
@@ -86,7 +88,8 @@
     private boolean mIsMainFrame;
 
     // Attached Javascript interfaces
-    private Map<String, Object> mJSInterfaceMap;
+    private Map<String, Object> mJavaScriptObjects;
+    private Set<Object> mRemovedJavaScriptObjects;
 
     // Key store handler when Chromium HTTP stack is used.
     private KeyStoreHandler mKeyStoreHandler = null;
@@ -229,10 +232,11 @@
         }
         sConfigCallback.addHandler(this);
 
-        mJSInterfaceMap = javascriptInterfaces;
-        if (mJSInterfaceMap == null) {
-            mJSInterfaceMap = new HashMap<String, Object>();
+        mJavaScriptObjects = javascriptInterfaces;
+        if (mJavaScriptObjects == null) {
+            mJavaScriptObjects = new HashMap<String, Object>();
         }
+        mRemovedJavaScriptObjects = new HashSet<Object>();
 
         mSettings = settings;
         mContext = context;
@@ -241,7 +245,7 @@
         mWebViewCore = w;
 
         mSearchBox = new SearchBoxImpl(mWebViewCore, mCallbackProxy);
-        mJSInterfaceMap.put(SearchBoxImpl.JS_INTERFACE_NAME, mSearchBox);
+        mJavaScriptObjects.put(SearchBoxImpl.JS_INTERFACE_NAME, mSearchBox);
 
         AssetManager am = context.getAssets();
         nativeCreateFrame(w, am, proxy.getBackForwardList());
@@ -598,15 +602,16 @@
      * We should re-attach any attached js interfaces.
      */
     private void windowObjectCleared(int nativeFramePointer) {
-        Iterator<String> iter = mJSInterfaceMap.keySet().iterator();
+        Iterator<String> iter = mJavaScriptObjects.keySet().iterator();
         while (iter.hasNext())  {
             String interfaceName = iter.next();
-            Object object = mJSInterfaceMap.get(interfaceName);
+            Object object = mJavaScriptObjects.get(interfaceName);
             if (object != null) {
                 nativeAddJavascriptInterface(nativeFramePointer,
-                        mJSInterfaceMap.get(interfaceName), interfaceName);
+                        mJavaScriptObjects.get(interfaceName), interfaceName);
             }
         }
+        mRemovedJavaScriptObjects.clear();
 
         stringByEvaluatingJavaScriptFromString(SearchBoxImpl.JS_BRIDGE);
     }
@@ -632,12 +637,15 @@
         assert obj != null;
         removeJavascriptInterface(interfaceName);
 
-        mJSInterfaceMap.put(interfaceName, obj);
+        mJavaScriptObjects.put(interfaceName, obj);
     }
 
     public void removeJavascriptInterface(String interfaceName) {
-        if (mJSInterfaceMap.containsKey(interfaceName)) {
-            mJSInterfaceMap.remove(interfaceName);
+        // We keep a reference to the removed object because the native side holds only a weak
+        // reference and we need to allow the object to continue to be used until the page has been
+        // navigated.
+        if (mJavaScriptObjects.containsKey(interfaceName)) {
+            mRemovedJavaScriptObjects.add(mJavaScriptObjects.remove(interfaceName));
         }
     }
 
@@ -1150,11 +1158,12 @@
      * {@link #nativeSslCertErrorProceed(int)} or
      * {@link #nativeSslCertErrorCancel(int, int)}.
      */
-    private void reportSslCertError(final int handle, final int cert_error, byte cert_der[]) {
+    private void reportSslCertError(
+            final int handle, final int cert_error, byte cert_der[], String url) {
         final SslError ssl_error;
         try {
             X509Certificate cert = new X509CertImpl(cert_der);
-            ssl_error = new SslError(cert_error, cert);
+            ssl_error = new SslError(cert_error, cert, url);
         } catch (IOException e) {
             // Can't get the certificate, not much to do.
             Log.e(LOGTAG, "Can't get the certificate from WebKit, canceling");
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index f7d55f6..0294e3f 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -119,6 +119,7 @@
     private static final int NOTIFY_SEARCHBOX_LISTENERS          = 139;
     private static final int AUTO_LOGIN                          = 140;
     private static final int CLIENT_CERT_REQUEST                 = 141;
+    private static final int SEARCHBOX_IS_SUPPORTED_CALLBACK     = 142;
 
     // Message triggered by the client to resume execution
     private static final int NOTIFY                              = 200;
@@ -796,13 +797,14 @@
                     mWebChromeClient.setInstallableWebApp();
                 }
                 break;
-            case NOTIFY_SEARCHBOX_LISTENERS:
+            case NOTIFY_SEARCHBOX_LISTENERS: {
                 SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox();
 
                 @SuppressWarnings("unchecked")
                 List<String> suggestions = (List<String>) msg.obj;
                 searchBox.handleSuggestions(msg.getData().getString("query"), suggestions);
                 break;
+            }
             case AUTO_LOGIN: {
                 if (mWebViewClient != null) {
                     String realm = msg.getData().getString("realm");
@@ -813,6 +815,12 @@
                 }
                 break;
             }
+            case SEARCHBOX_IS_SUPPORTED_CALLBACK: {
+                SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox();
+                Boolean supported = (Boolean) msg.obj;
+                searchBox.handleIsSupportedCallback(supported);
+                break;
+            }
         }
     }
 
@@ -1627,4 +1635,10 @@
 
         sendMessage(msg);
     }
+
+    void onIsSupportedCallback(boolean isSupported) {
+        Message msg = obtainMessage(SEARCHBOX_IS_SUPPORTED_CALLBACK);
+        msg.obj = new Boolean(isSupported);
+        sendMessage(msg);
+    }
 }
diff --git a/core/java/android/webkit/CertTool.java b/core/java/android/webkit/CertTool.java
index 4c534f9..a2325c3 100644
--- a/core/java/android/webkit/CertTool.java
+++ b/core/java/android/webkit/CertTool.java
@@ -21,31 +21,27 @@
 import com.android.org.bouncycastle.jce.netscape.NetscapeCertRequest;
 import com.android.org.bouncycastle.util.encoders.Base64;
 
-import android.content.ActivityNotFoundException;
 import android.content.Context;
-import android.content.Intent;
 import android.security.Credentials;
+import android.security.KeyChain;
 import android.util.Log;
 
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.util.HashMap;
 
-class CertTool {
+final class CertTool {
     private static final String LOGTAG = "CertTool";
 
     private static final AlgorithmIdentifier MD5_WITH_RSA =
             new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption);
 
-    static final String CERT = Credentials.CERTIFICATE;
-    static final String PKCS12 = Credentials.PKCS12;
-
     private static HashMap<String, String> sCertificateTypeMap;
     static {
         sCertificateTypeMap = new HashMap<String, String>();
-        sCertificateTypeMap.put("application/x-x509-ca-cert", CertTool.CERT);
-        sCertificateTypeMap.put("application/x-x509-user-cert", CertTool.CERT);
-        sCertificateTypeMap.put("application/x-pkcs12", CertTool.PKCS12);
+        sCertificateTypeMap.put("application/x-x509-ca-cert", KeyChain.EXTRA_CERTIFICATE);
+        sCertificateTypeMap.put("application/x-x509-user-cert", KeyChain.EXTRA_CERTIFICATE);
+        sCertificateTypeMap.put("application/x-pkcs12", KeyChain.EXTRA_PKCS12);
     }
 
     static String[] getKeyStrengthList() {
@@ -77,7 +73,7 @@
 
     static String getCertType(String mimeType) {
         return sCertificateTypeMap.get(mimeType);
-  }
+    }
 
     private CertTool() {}
 }
diff --git a/core/java/android/webkit/HTML5VideoFullScreen.java b/core/java/android/webkit/HTML5VideoFullScreen.java
index 4cae9d8..0ea27a0 100644
--- a/core/java/android/webkit/HTML5VideoFullScreen.java
+++ b/core/java/android/webkit/HTML5VideoFullScreen.java
@@ -104,9 +104,14 @@
 
         public void surfaceDestroyed(SurfaceHolder holder)
         {
-            // after we return from this we can't use the surface any more
-            mSurfaceHolder = null;
+            // After we return from this we can't use the surface any more.
             // The current Video View will be destroy when we play a new video.
+            pauseAndDispatch(mProxy);
+            mPlayer.release();
+            mSurfaceHolder = null;
+            if (mMediaController != null) {
+                mMediaController.hide();
+            }
         }
     };
 
@@ -210,7 +215,6 @@
                 // which happens when the video view is detached from its parent
                 // view. This happens in the WebChromeClient before this method
                 // is invoked.
-                pauseAndDispatch(mProxy);
                 mProxy.dispatchOnStopFullScreen();
                 mLayout.removeView(getSurfaceView());
 
@@ -223,6 +227,10 @@
                 mProxy.getWebView().getViewManager().showAll();
 
                 mProxy = null;
+
+                // Don't show the controller after exiting the full screen.
+                mMediaController = null;
+                mCurrentState = STATE_RELEASED;
             }
         };
 
diff --git a/core/java/android/webkit/HTML5VideoView.java b/core/java/android/webkit/HTML5VideoView.java
index 5983a44..67660b8 100644
--- a/core/java/android/webkit/HTML5VideoView.java
+++ b/core/java/android/webkit/HTML5VideoView.java
@@ -34,6 +34,7 @@
     static final int STATE_NOTPREPARED        = 1;
     static final int STATE_PREPARED           = 2;
     static final int STATE_PLAYING            = 3;
+    static final int STATE_RELEASED           = 4;
     protected int mCurrentState;
 
     protected HTML5VideoViewProxy mProxy;
@@ -84,7 +85,7 @@
     }
 
     public void pause() {
-        if (mCurrentState == STATE_PREPARED && mPlayer.isPlaying()) {
+        if (isPlaying()) {
             mPlayer.pause();
         } else if (mCurrentState == STATE_NOTPREPARED) {
             mPauseDuringPreparing = true;
@@ -120,11 +121,18 @@
     }
 
     public boolean isPlaying() {
-        return mPlayer.isPlaying();
+        if (mCurrentState == STATE_PREPARED) {
+            return mPlayer.isPlaying();
+        } else {
+            return false;
+        }
     }
 
     public void release() {
-        mPlayer.release();
+        if (mCurrentState != STATE_RELEASED) {
+            mPlayer.release();
+        }
+        mCurrentState = STATE_RELEASED;
     }
 
     public void stopPlayback() {
@@ -228,7 +236,7 @@
 
 
     public int getCurrentState() {
-        if (mPlayer.isPlaying()) {
+        if (isPlaying()) {
             return STATE_PLAYING;
         } else {
             return mCurrentState;
diff --git a/core/java/android/webkit/L10nUtils.java b/core/java/android/webkit/L10nUtils.java
index 5b4fb1d..f9d0067d 100644
--- a/core/java/android/webkit/L10nUtils.java
+++ b/core/java/android/webkit/L10nUtils.java
@@ -70,7 +70,12 @@
         com.android.internal.R.string.autofill_expiration_month_re,         // IDS_AUTOFILL_EXPIRATION_MONTH_RE
         com.android.internal.R.string.autofill_expiration_date_re,          // IDS_AUTOFILL_EXPIRATION_DATE_RE
         com.android.internal.R.string.autofill_card_ignored_re,             // IDS_AUTOFILL_CARD_IGNORED_RE
-        com.android.internal.R.string.autofill_fax_re                       // IDS_AUTOFILL_FAX_RE
+        com.android.internal.R.string.autofill_fax_re,                      // IDS_AUTOFILL_FAX_RE
+        com.android.internal.R.string.autofill_country_code_re,             // IDS_AUTOFILL_COUNTRY_CODE_RE
+        com.android.internal.R.string.autofill_area_code_notext_re,         // IDS_AUTOFILL_AREA_CODE_NOTEXT_RE
+        com.android.internal.R.string.autofill_phone_prefix_separator_re,   // IDS_AUTOFILL_PHONE_PREFIX_SEPARATOR_RE
+        com.android.internal.R.string.autofill_phone_suffix_separator_re,   // IDS_AUTOFILL_PHONE_SUFFIX_SEPARATOR_RE
+        com.android.internal.R.string.credit_card_number_preview_format     // IDS_CREDIT_CARD_NUMBER_PREVIEW_FORMAT
     };
 
     private static Context mApplicationContext;
diff --git a/core/java/android/webkit/SearchBox.java b/core/java/android/webkit/SearchBox.java
index 57c7b03..5075302 100644
--- a/core/java/android/webkit/SearchBox.java
+++ b/core/java/android/webkit/SearchBox.java
@@ -83,10 +83,19 @@
     void removeSearchBoxListener(SearchBoxListener l);
 
     /**
+     * Indicates if the searchbox API is supported in the current page.
+     */
+    void isSupported(IsSupportedCallback callback);
+
+    /**
      * Listeners (if any) will be called on the thread that created the
      * webview.
      */
     interface SearchBoxListener {
         void onSuggestionsReceived(String query, List<String> suggestions);
     }
+
+    interface IsSupportedCallback {
+        void searchBoxIsSupported(boolean supported);
+    }
 }
diff --git a/core/java/android/webkit/SearchBoxImpl.java b/core/java/android/webkit/SearchBoxImpl.java
index 480f5d7..61fb2ce 100644
--- a/core/java/android/webkit/SearchBoxImpl.java
+++ b/core/java/android/webkit/SearchBoxImpl.java
@@ -92,9 +92,19 @@
             = "if (window.chrome && window.chrome.searchBox &&"
             + "  window.chrome.searchBox.on%1$s) { window.chrome.searchBox.on%1$s(); }";
 
+    private static final String IS_SUPPORTED_SCRIPT
+            = "if (window.searchBoxJavaBridge_) {"
+            + "  if (window.chrome && window.chrome.searchBox && "
+            + "  window.chrome.searchBox.onsubmit) {"
+            + "    window.searchBoxJavaBridge_.isSupportedCallback(true);"
+            + "  } else {"
+            + "    window.searchBoxJavaBridge_.isSupportedCallback(false);"
+            + "  }}";
+
     private final List<SearchBoxListener> mListeners;
     private final WebViewCore mWebViewCore;
     private final CallbackProxy mCallbackProxy;
+    private IsSupportedCallback mSupportedCallback;
 
     SearchBoxImpl(WebViewCore webViewCore, CallbackProxy callbackProxy) {
         mListeners = new ArrayList<SearchBoxListener>();
@@ -173,6 +183,25 @@
         }
     }
 
+    @Override
+    public void isSupported(IsSupportedCallback callback) {
+        mSupportedCallback = callback;
+        dispatchJs(IS_SUPPORTED_SCRIPT);
+    }
+
+    // Called by Javascript through the Java bridge.
+    public void isSupportedCallback(boolean isSupported) {
+        mCallbackProxy.onIsSupportedCallback(isSupported);
+    }
+
+    public void handleIsSupportedCallback(boolean isSupported) {
+        IsSupportedCallback callback = mSupportedCallback;
+        mSupportedCallback = null;
+        if (callback != null) {
+            callback.searchBoxIsSupported(isSupported);
+        }
+    }
+
     // This is used as a hackish alternative to javascript escaping.
     // There appears to be no such functionality in the core framework.
     private String jsonSerialize(String query) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 9f632d1..7ba86a5 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1971,9 +1971,14 @@
     }
 
     /**
-     * Load the given data into the WebView using a 'data' scheme URL. Content
-     * loaded in this way does not have the ability to load content from the
-     * network.
+     * Load the given data into the WebView using a 'data' scheme URL.
+     * <p>
+     * Note that JavaScript's same origin policy means that script running in a
+     * page loaded using this method will be unable to access content loaded
+     * using any scheme other than 'data', including 'http(s)'. To avoid this
+     * restriction, use {@link
+     * #loadDataWithBaseURL(String,String,String,String,String)
+     * loadDataWithBaseURL()} with an appropriate base URL.
      * <p>
      * If the value of the encoding parameter is 'base64', then the data must
      * be encoded as base64. Otherwise, the data must use ASCII encoding for
@@ -2000,21 +2005,26 @@
     }
 
     /**
-     * Load the given data into the WebView, use the provided URL as the base
-     * URL for the content. The base URL is the URL that represents the page
-     * that is loaded through this interface. As such, it is used to resolve any
-     * relative URLs. The historyUrl is used for the history entry.
+     * Load the given data into the WebView, using baseUrl as the base URL for
+     * the content. The base URL is used both to resolve relative URLs and when
+     * applying JavaScript's same origin policy. The historyUrl is used for the
+     * history entry.
      * <p>
      * Note that content specified in this way can access local device files
      * (via 'file' scheme URLs) only if baseUrl specifies a scheme other than
      * 'http', 'https', 'ftp', 'ftps', 'about' or 'javascript'.
-     * @param baseUrl Url to resolve relative paths with, if null defaults to
-     *            "about:blank"
+     * <p>
+     * If the base URL uses the data scheme, this method is equivalent to
+     * calling {@link #loadData(String,String,String) loadData()} and the
+     * historyUrl is ignored.
+     * @param baseUrl URL to use as the page's base URL. If null defaults to
+     *            'about:blank'
      * @param data A String of data in the given encoding.
-     * @param mimeType The MIMEType of the data. i.e. text/html. If null,
-     *            defaults to "text/html"
-     * @param encoding The encoding of the data. i.e. utf-8, us-ascii
-     * @param historyUrl URL to use as the history entry.  Can be null.
+     * @param mimeType The MIMEType of the data, e.g. 'text/html'. If null,
+     *            defaults to 'text/html'.
+     * @param encoding The encoding of the data.
+     * @param historyUrl URL to use as the history entry, if null defaults to
+     *            'about:blank'.
      */
     public void loadDataWithBaseURL(String baseUrl, String data,
             String mimeType, String encoding, String historyUrl) {
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 7e41d36..c652e55 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1950,6 +1950,7 @@
     // mInitialViewState is set by didFirstLayout() and then reset in the
     // next webkitDraw after passing the state to the UI thread.
     private ViewState mInitialViewState = null;
+    private boolean mFirstLayoutForNonStandardLoad;
 
     static class ViewState {
         float mMinScale;
@@ -1977,6 +1978,7 @@
         int mMinPrefWidth;
         // only non-null if it is for the first picture set after the first layout
         ViewState mViewState;
+        boolean mFirstLayoutForNonStandardLoad;
         boolean mFocusSizeChanged;
     }
 
@@ -2026,6 +2028,10 @@
                 draw.mViewState = mInitialViewState;
                 mInitialViewState = null;
             }
+            if (mFirstLayoutForNonStandardLoad) {
+                draw.mFirstLayoutForNonStandardLoad = true;
+                mFirstLayoutForNonStandardLoad = false;
+            }
             if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw NEW_PICTURE_MSG_ID");
             Message.obtain(mWebView.mPrivateHandler,
                     WebView.NEW_PICTURE_MSG_ID, draw).sendToTarget();
@@ -2229,16 +2235,15 @@
 
     // called by JNI
     private void updateViewport() {
-        // if updateViewport is called before first layout, wait until first
-        // layout to update the viewport. In the rare case, this is called after
-        // first layout, force an update as we have just parsed the viewport
-        // meta tag.
-        if (mBrowserFrame.firstLayoutDone()) {
-            setupViewport(true);
-        }
+        // Update viewport asap to make sure we get correct one.
+        setupViewport(true);
     }
 
     private void setupViewport(boolean updateViewState) {
+        if (mWebView == null || mSettings == null) {
+            // We've been destroyed or are being destroyed, return early
+            return;
+        }
         // set the viewport settings from WebKit
         setViewportSettingsFromNative();
 
@@ -2312,6 +2317,8 @@
 
         // if mViewportWidth is 0, it means device-width, always update.
         if (mViewportWidth != 0 && !updateViewState) {
+            // For non standard load, since updateViewState will be false.
+            mFirstLayoutForNonStandardLoad = true;
             ViewState viewState = new ViewState();
             viewState.mMinScale = mViewportMinimumScale / 100.0f;
             viewState.mMaxScale = mViewportMaximumScale / 100.0f;
@@ -2367,8 +2374,12 @@
                         (float) webViewWidth / mViewportWidth;
             } else {
                 mInitialViewState.mTextWrapScale = adjust;
-                // 0 will trigger WebView to turn on zoom overview mode
-                mInitialViewState.mViewScale = 0;
+                if (mSettings.getUseWideViewPort()) {
+                    // 0 will trigger WebView to turn on zoom overview mode
+                    mInitialViewState.mViewScale = 0;
+                } else {
+                    mInitialViewState.mViewScale = adjust;
+                }
             }
         }
 
@@ -2399,7 +2410,7 @@
             mEventHub.removeMessages(EventHub.VIEW_SIZE_CHANGED);
             mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null,
                     EventHub.VIEW_SIZE_CHANGED, data));
-        } else if (mSettings.getUseWideViewPort()) {
+        } else {
             if (viewportWidth == 0) {
                 // Trick to ensure VIEW_SIZE_CHANGED will be sent from WebView
                 // to WebViewCore
@@ -2471,9 +2482,10 @@
     // called by JNI
     private void restoreScale(float scale, float textWrapScale) {
         if (mBrowserFrame.firstLayoutDone() == false) {
-            mRestoredScale = scale;
+            final float defaultScale = mWebView.getDefaultZoomScale();
+            mRestoredScale = (scale <= 0.0) ? defaultScale : scale;
             if (mSettings.getUseWideViewPort()) {
-                mRestoredTextWrapScale = textWrapScale;
+                mRestoredTextWrapScale = (textWrapScale <= 0.0) ? defaultScale : textWrapScale;
             }
         }
     }
diff --git a/core/java/android/webkit/WebViewFragment.java b/core/java/android/webkit/WebViewFragment.java
index 466f174..852878b 100644
--- a/core/java/android/webkit/WebViewFragment.java
+++ b/core/java/android/webkit/WebViewFragment.java
@@ -30,6 +30,7 @@
  */
 public class WebViewFragment extends Fragment {
     private WebView mWebView;
+    private boolean mIsWebViewAvailable;
 
     public WebViewFragment() {
     }
@@ -40,7 +41,11 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
+        if (mWebView != null) {
+            mWebView.destroy();
+        }
         mWebView = new WebView(getActivity());
+        mIsWebViewAvailable = true;
         return mWebView;
     }
 
@@ -63,19 +68,31 @@
     }
 
     /**
-     * Called when the view has been detached from the fragment. Destroys the WebView.
+     * Called when the WebView has been detached from the fragment.
+     * The WebView is no longer available after this time.
      */
     @Override
     public void onDestroyView() {
-        mWebView.destroy();
-        mWebView = null;
+        mIsWebViewAvailable = false;
         super.onDestroyView();
     }
 
     /**
+     * Called when the fragment is no longer in use. Destroys the internal state of the WebView.
+     */
+    @Override
+    public void onDestroy() {
+        if (mWebView != null) {
+            mWebView.destroy();
+            mWebView = null;
+        }
+        super.onDestroy();
+    }
+
+    /**
      * Gets the WebView.
      */
     public WebView getWebView() {
-        return mWebView;
+        return mIsWebViewAvailable ? mWebView : null;
     }
 }
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 883656b..7d3f313 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -300,7 +300,7 @@
     }
 
     public final float getDefaultScale() {
-        return mDefaultScale;
+        return mInitialScale > 0 ? mInitialScale : mDefaultScale;
     }
 
     public final float getReadingLevelScale() {
@@ -1024,6 +1024,11 @@
         } else {
             mInZoomOverview = !scaleHasDiff;
         }
+        if (drawData.mFirstLayoutForNonStandardLoad && settings.getLoadWithOverviewMode()) {
+            // Set mInitialZoomOverview in case this is the first picture for non standard load,
+            // so next new picture could be forced into overview mode if it's true.
+            mInitialZoomOverview = mInZoomOverview;
+        }
     }
 
     /**
@@ -1082,6 +1087,7 @@
             float scale;
             if (mInitialScale > 0) {
                 scale = mInitialScale;
+                mTextWrapScale = scale;
             } else if (viewState.mViewScale > 0) {
                 mTextWrapScale = viewState.mTextWrapScale;
                 scale = viewState.mViewScale;
@@ -1100,14 +1106,21 @@
             }
             boolean reflowText = false;
             if (!viewState.mIsRestored) {
-                if (settings.getUseFixedViewport()) {
+                if (settings.getUseFixedViewport() && mInitialScale == 0) {
                     // Override the scale only in case of fixed viewport.
                     scale = Math.max(scale, overviewScale);
                     mTextWrapScale = Math.max(mTextWrapScale, overviewScale);
                 }
                 reflowText = exceedsMinScaleIncrement(mTextWrapScale, scale);
+            } else {
+                // In case of restored scale, treat defaultScale as overview since
+                // it usually means the previous scale is not saved.
+                if (scale == mDefaultScale && settings.getLoadWithOverviewMode()) {
+                    scale = overviewScale;
+                }
             }
-            mInitialZoomOverview = !exceedsMinScaleIncrement(scale, overviewScale);
+            mInitialZoomOverview = settings.getLoadWithOverviewMode() &&
+                    !exceedsMinScaleIncrement(scale, overviewScale);
             setZoomScale(scale, reflowText);
 
             // update the zoom buttons as the scale can be changed
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 3fe8149..1449b18 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -55,6 +55,8 @@
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
@@ -1257,6 +1259,33 @@
         onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
     }
 
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setScrollable(true);
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setScrollable(true);
+        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            event.setFromIndex(mFirstPosition);
+            event.setToIndex(mFirstPosition +  getChildCount());
+            event.setItemCount(mItemCount);
+        }
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        // Do not append text content to scroll events they are fired frequently
+        // and the client has already received another event type with the text.
+        if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            super.dispatchPopulateAccessibilityEvent(event);
+        }
+        return false;
+    }
+
     /**
      * Indicates whether the children's drawing cache is used during a scroll.
      * By default, the drawing cache is enabled but this will consume more memory.
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java
new file mode 100644
index 0000000..83f80ff
--- /dev/null
+++ b/core/java/android/widget/ActivityChooserModel.java
@@ -0,0 +1,1115 @@
+/*
+ * 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.widget;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.database.DataSetObservable;
+import android.database.DataSetObserver;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Xml;
+
+import com.android.internal.content.PackageMonitor;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <p>
+ * This class represents a data model for choosing a component for handing a
+ * given {@link Intent}. The model is responsible for querying the system for
+ * activities that can handle the given intent and order found activities
+ * based on historical data of previous choices. The historical data is stored
+ * in an application private file. If a client does not want to have persistent
+ * choice history the file can be omitted, thus the activities will be ordered
+ * based on historical usage for the current session.
+ * <p>
+ * </p>
+ * For each backing history file there is a singleton instance of this class. Thus,
+ * several clients that specify the same history file will share the same model. Note
+ * that if multiple clients are sharing the same model they should implement semantically
+ * equivalent functionality since setting the model intent will change the found
+ * activities and they may be inconsistent with the functionality of some of the clients.
+ * For example, choosing a share activity can be implemented by a single backing
+ * model and two different views for performing the selection. If however, one of the
+ * views is used for sharing but the other for importing, for example, then each
+ * view should be backed by a separate model.
+ * </p>
+ * <p>
+ * The way clients interact with this class is as follows:
+ * </p>
+ * <p>
+ * <pre>
+ * <code>
+ *  // Get a model and set it to a couple of clients with semantically similar function.
+ *  ActivityChooserModel dataModel =
+ *      ActivityChooserModel.get(context, "task_specific_history_file_name.xml");
+ *
+ *  ActivityChooserModelClient modelClient1 = getActivityChooserModelClient1();
+ *  modelClient1.setActivityChooserModel(dataModel);
+ *
+ *  ActivityChooserModelClient modelClient2 = getActivityChooserModelClient2();
+ *  modelClient2.setActivityChooserModel(dataModel);
+ *
+ *  // Set an intent to choose a an activity for.
+ *  dataModel.setIntent(intent);
+ * <pre>
+ * <code>
+ * </p>
+ * <p>
+ * <strong>Note:</strong> This class is thread safe.
+ * </p>
+ *
+ * @hide
+ */
+public class ActivityChooserModel extends DataSetObservable {
+
+    /**
+     * Client that utilizes an {@link ActivityChooserModel}.
+     */
+    public interface ActivityChooserModelClient {
+
+        /**
+         * Sets the {@link ActivityChooserModel}.
+         *
+         * @param dataModel The model.
+         */
+        public void setActivityChooserModel(ActivityChooserModel dataModel);
+    }
+
+    /**
+     * Defines a sorter that is responsible for sorting the activities
+     * based on the provided historical choices and an intent.
+     */
+    public interface ActivitySorter {
+
+        /**
+         * Sorts the <code>activities</code> in descending order of relevance
+         * based on previous history and an intent.
+         *
+         * @param intent The {@link Intent}.
+         * @param activities Activities to be sorted.
+         * @param historicalRecords Historical records.
+         */
+        // This cannot be done by a simple comparator since an Activity weight
+        // is computed from history. Note that Activity implements Comparable.
+        public void sort(Intent intent, List<Activity> activities,
+                List<HistoricalRecord> historicalRecords);
+    }
+
+    /**
+     * Flag for selecting debug mode.
+     */
+    private static final boolean DEBUG = false;
+
+    /**
+     * Tag used for logging.
+     */
+    private static final String LOG_TAG = ActivityChooserModel.class.getSimpleName();
+
+    /**
+     * The root tag in the history file.
+     */
+    private static final String TAG_HISTORICAL_RECORDS = "historical-records";
+
+    /**
+     * The tag for a record in the history file.
+     */
+    private static final String TAG_HISTORICAL_RECORD = "historical-record";
+
+    /**
+     * Attribute for the activity.
+     */
+    private static final String ATTRIBUTE_ACTIVITY = "activity";
+
+    /**
+     * Attribute for the choice time.
+     */
+    private static final String ATTRIBUTE_TIME = "time";
+
+    /**
+     * Attribute for the choice weight.
+     */
+    private static final String ATTRIBUTE_WEIGHT = "weight";
+
+    /**
+     * The default name of the choice history file.
+     */
+    public static final String DEFAULT_HISTORY_FILE_NAME =
+        "activity_choser_model_history.xml";
+
+    /**
+     * The default maximal length of the choice history.
+     */
+    public static final int DEFAULT_HISTORY_MAX_LENGTH = 50;
+
+    /**
+     * The amount with which to inflate a chosen activity when set as default.
+     */
+    private static final int DEFAULT_ACTIVITY_INFLATION = 5;
+
+    /**
+     * Default weight for a choice record.
+     */
+    private static final float DEFAULT_HISTORICAL_RECORD_WEIGHT = 1.0f;
+
+    /**
+     * The extension of the history file.
+     */
+    private static final String HISTORY_FILE_EXTENSION = ".xml";
+
+    /**
+     * An invalid item index.
+     */
+    private static final int INVALID_INDEX = -1;
+
+    /**
+     * Lock to guard the model registry.
+     */
+    private static final Object sRegistryLock = new Object();
+
+    /**
+     * This the registry for data models.
+     */
+    private static final Map<String, ActivityChooserModel> sDataModelRegistry =
+        new HashMap<String, ActivityChooserModel>();
+
+    /**
+     * Lock for synchronizing on this instance.
+     */
+    private final Object mInstanceLock = new Object();
+
+    /**
+     * List of activities that can handle the current intent.
+     */
+    private final List<Activity> mActivitys = new ArrayList<Activity>();
+
+    /**
+     * List with historical choice records.
+     */
+    private final List<HistoricalRecord> mHistoricalRecords = new ArrayList<HistoricalRecord>();
+
+    /**
+     * Monitor for added and removed packages.
+     */
+    private final PackageMonitor mPackageMonitor = new DataModelPackageMonitor();
+
+    /**
+     * Context for accessing resources.
+     */
+    private final Context mContext;
+
+    /**
+     * The name of the history file that backs this model.
+     */
+    private final String mHistoryFileName;
+
+    /**
+     * The intent for which a activity is being chosen.
+     */
+    private Intent mIntent;
+
+    /**
+     * The sorter for ordering activities based on intent and past choices.
+     */
+    private ActivitySorter mActivitySorter = new DefaultSorter();
+
+    /**
+     * The maximal length of the choice history.
+     */
+    private int mHistoryMaxSize = DEFAULT_HISTORY_MAX_LENGTH;
+
+    /**
+     * Flag whether choice history can be read. In general many clients can
+     * share the same data model and {@link #readHistoricalData()} may be called
+     * by arbitrary of them any number of times. Therefore, this class guarantees
+     * that the very first read succeeds and subsequent reads can be performed
+     * only after a call to {@link #persistHistoricalData()} followed by change
+     * of the share records.
+     */
+    private boolean mCanReadHistoricalData = true;
+
+    /**
+     * Flag whether the choice history was read. This is used to enforce that
+     * before calling {@link #persistHistoricalData()} a call to
+     * {@link #persistHistoricalData()} has been made. This aims to avoid a
+     * scenario in which a choice history file exits, it is not read yet and
+     * it is overwritten. Note that always all historical records are read in
+     * full and the file is rewritten. This is necessary since we need to
+     * purge old records that are outside of the sliding window of past choices.
+     */
+    private boolean mReadShareHistoryCalled = false;
+
+    /**
+     * Flag whether the choice records have changed. In general many clients can
+     * share the same data model and {@link #persistHistoricalData()} may be called
+     * by arbitrary of them any number of times. Therefore, this class guarantees
+     * that choice history will be persisted only if it has changed.
+     */
+    private boolean mHistoricalRecordsChanged = true;
+
+    /**
+     * Hander for scheduling work on client tread.
+     */
+    private final Handler mHandler = new Handler();
+
+    /**
+     * Gets the data model backed by the contents of the provided file with historical data.
+     * Note that only one data model is backed by a given file, thus multiple calls with
+     * the same file name will return the same model instance. If no such instance is present
+     * it is created.
+     * <p>
+     * <strong>Note:</strong> To use the default historical data file clients should explicitly
+     * pass as file name {@link #DEFAULT_HISTORY_FILE_NAME}. If no persistence of the choice
+     * history is desired clients should pass <code>null</code> for the file name. In such
+     * case a new model is returned for each invocation.
+     * </p>
+     *
+     * <p>
+     * <strong>Always use difference historical data files for semantically different actions.
+     * For example, sharing is different from importing.</strong>
+     * </p>
+     *
+     * @param context Context for loading resources.
+     * @param historyFileName File name with choice history, <code>null</code>
+     *        if the model should not be backed by a file. In this case the activities
+     *        will be ordered only by data from the current session.
+     *
+     * @return The model.
+     */
+    public static ActivityChooserModel get(Context context, String historyFileName) {
+        if (historyFileName == null) {
+            return new ActivityChooserModel(context, historyFileName);
+        }
+        synchronized (sRegistryLock) {
+            ActivityChooserModel dataModel = sDataModelRegistry.get(historyFileName);
+            if (dataModel == null) {
+                dataModel = new ActivityChooserModel(context, historyFileName);
+                sDataModelRegistry.put(historyFileName, dataModel);
+            }
+            return dataModel;
+        }
+    }
+
+    /**
+     * Creates a new instance.
+     *
+     * @param context Context for loading resources.
+     * @param historyFileName The history XML file.
+     */
+    private ActivityChooserModel(Context context, String historyFileName) {
+        mContext = context.getApplicationContext();
+        if (!TextUtils.isEmpty(historyFileName)
+                && !historyFileName.endsWith(HISTORY_FILE_EXTENSION)) {
+            mHistoryFileName = historyFileName + HISTORY_FILE_EXTENSION;
+        } else {
+            mHistoryFileName = historyFileName;
+        }
+        mPackageMonitor.register(mContext, true);
+    }
+
+    /**
+     * Sets an intent for which to choose a activity.
+     * <p>
+     * <strong>Note:</strong> Clients must set only semantically similar
+     * intents for each data model.
+     * <p>
+     *
+     * @param intent The intent.
+     */
+    public void setIntent(Intent intent) {
+        synchronized (mInstanceLock) {
+            if (mIntent == intent) {
+                return;
+            }
+            mIntent = intent;
+            loadActivitiesLocked();
+        }
+    }
+
+    /**
+     * Gets the intent for which a activity is being chosen.
+     *
+     * @return The intent.
+     */
+    public Intent getIntent() {
+        synchronized (mInstanceLock) {
+            return mIntent;
+        }
+    }
+
+    /**
+     * Gets the number of activities that can handle the intent.
+     *
+     * @return The activity count.
+     *
+     * @see #setIntent(Intent)
+     */
+    public int getActivityCount() {
+        synchronized (mInstanceLock) {
+            return mActivitys.size();
+        }
+    }
+
+    /**
+     * Gets an activity at a given index.
+     *
+     * @return The activity.
+     *
+     * @see Activity
+     * @see #setIntent(Intent)
+     */
+    public ResolveInfo getActivity(int index) {
+        synchronized (mInstanceLock) {
+            return mActivitys.get(index).resolveInfo;
+        }
+    }
+
+    /**
+     * Gets the index of a the given activity.
+     *
+     * @param activity The activity index.
+     *
+     * @return The index if found, -1 otherwise.
+     */
+    public int getActivityIndex(ResolveInfo activity) {
+        List<Activity> activities = mActivitys;
+        final int activityCount = activities.size();
+        for (int i = 0; i < activityCount; i++) {
+            Activity currentActivity = activities.get(i);
+            if (currentActivity.resolveInfo == activity) {
+                return i;
+            }
+        }
+        return INVALID_INDEX;
+    }
+
+    /**
+     * Chooses a activity to handle the current intent. This will result in
+     * adding a historical record for that action and construct intent with
+     * its component name set such that it can be immediately started by the
+     * client.
+     * <p>
+     * <strong>Note:</strong> By calling this method the client guarantees
+     * that the returned intent will be started. This intent is returned to
+     * the client solely to let additional customization before the start.
+     * </p>
+     *
+     * @return Whether adding succeeded.
+     *
+     * @see HistoricalRecord
+     */
+    public Intent chooseActivity(int index) {
+        Activity chosenActivity = mActivitys.get(index);
+        Activity defaultActivity = mActivitys.get(0);
+
+        ComponentName chosenName = new ComponentName(
+                chosenActivity.resolveInfo.activityInfo.packageName,
+                chosenActivity.resolveInfo.activityInfo.name);
+        HistoricalRecord historicalRecord = new HistoricalRecord(chosenName,
+                System.currentTimeMillis(), DEFAULT_HISTORICAL_RECORD_WEIGHT);
+        addHisoricalRecord(historicalRecord);
+
+        Intent choiceIntent = new Intent(mIntent);
+        choiceIntent.setComponent(chosenName);
+
+        return choiceIntent;
+    }
+
+    /**
+     * Gets the default activity, The default activity is defined as the one
+     * with highest rank i.e. the first one in the list of activities that can
+     * handle the intent.
+     *
+     * @return The default activity, <code>null</code> id not activities.
+     *
+     * @see #getActivity(int)
+     */
+    public ResolveInfo getDefaultActivity() {
+        synchronized (mInstanceLock) {
+            if (!mActivitys.isEmpty()) {
+                return mActivitys.get(0).resolveInfo;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Sets the default activity. The default activity is set by adding a
+     * historical record with weight high enough that this activity will
+     * become the highest ranked. Such a strategy guarantees that the default
+     * will eventually change if not used. Also the weight of the record for
+     * setting a default is inflated with a constant amount to guarantee that
+     * it will stay as default for awhile.
+     *
+     * @param index The index of the activity to set as default.
+     */
+    public void setDefaultActivity(int index) {
+        Activity newDefaultActivity = mActivitys.get(index);
+        Activity oldDefaultActivity = mActivitys.get(0);
+
+        final float weight;
+        if (oldDefaultActivity != null) {
+            // Add a record with weight enough to boost the chosen at the top.
+            weight = oldDefaultActivity.weight - newDefaultActivity.weight
+                + DEFAULT_ACTIVITY_INFLATION;
+        } else {
+            weight = DEFAULT_HISTORICAL_RECORD_WEIGHT;
+        }
+
+        ComponentName defaultName = new ComponentName(
+                newDefaultActivity.resolveInfo.activityInfo.packageName,
+                newDefaultActivity.resolveInfo.activityInfo.name);
+        HistoricalRecord historicalRecord = new HistoricalRecord(defaultName,
+                System.currentTimeMillis(), weight);
+        addHisoricalRecord(historicalRecord);
+    }
+
+    /**
+     * Reads the history data from the backing file if the latter
+     * was provided. Calling this method more than once before a call
+     * to {@link #persistHistoricalData()} has been made has no effect.
+     * <p>
+     * <strong>Note:</strong> Historical data is read asynchronously and
+     *       as soon as the reading is completed any registered
+     *       {@link DataSetObserver}s will be notified. Also no historical
+     *       data is read until this method is invoked.
+     * <p>
+     */
+    public void readHistoricalData() {
+        synchronized (mInstanceLock) {
+            if (!mCanReadHistoricalData || !mHistoricalRecordsChanged) {
+                return;
+            }
+            mCanReadHistoricalData = false;
+            mReadShareHistoryCalled = true;
+            if (!TextUtils.isEmpty(mHistoryFileName)) {
+                AsyncTask.SERIAL_EXECUTOR.execute(new HistoryLoader());
+            }
+        }
+    }
+
+    /**
+     * Persists the history data to the backing file if the latter
+     * was provided. Calling this method before a call to {@link #readHistoricalData()}
+     * throws an exception. Calling this method more than one without choosing an
+     * activity has not effect.
+     *
+     * @throws IllegalStateException If this method is called before a call to
+     *         {@link #readHistoricalData()}.
+     */
+    public void persistHistoricalData() {
+        synchronized (mInstanceLock) {
+            if (!mReadShareHistoryCalled) {
+                throw new IllegalStateException("No preceding call to #readHistoricalData");
+            }
+            if (!mHistoricalRecordsChanged) {
+                return;
+            }
+            mHistoricalRecordsChanged = false;
+            mCanReadHistoricalData = true;
+            if (!TextUtils.isEmpty(mHistoryFileName)) {
+                AsyncTask.SERIAL_EXECUTOR.execute(new HistoryPersister());
+            }
+        }
+    }
+
+    /**
+     * Sets the sorter for ordering activities based on historical data and an intent.
+     *
+     * @param activitySorter The sorter.
+     *
+     * @see ActivitySorter
+     */
+    public void setActivitySorter(ActivitySorter activitySorter) {
+        synchronized (mInstanceLock) {
+            if (mActivitySorter == activitySorter) {
+                return;
+            }
+            mActivitySorter = activitySorter;
+            sortActivities();
+        }
+    }
+
+    /**
+     * Sorts the activities based on history and an intent. If
+     * a sorter is not specified this a default implementation is used.
+     *
+     * @see #setActivitySorter(ActivitySorter)
+     */
+    private void sortActivities() {
+        synchronized (mInstanceLock) {
+            if (mActivitySorter != null && !mActivitys.isEmpty()) {
+                mActivitySorter.sort(mIntent, mActivitys,
+                        Collections.unmodifiableList(mHistoricalRecords));
+                notifyChanged();
+            }
+        }
+    }
+
+    /**
+     * Sets the maximal size of the historical data. Defaults to
+     * {@link #DEFAULT_HISTORY_MAX_LENGTH}
+     * <p>
+     *   <strong>Note:</strong> Setting this property will immediately
+     *   enforce the specified max history size by dropping enough old
+     *   historical records to enforce the desired size. Thus, any
+     *   records that exceed the history size will be discarded and
+     *   irreversibly lost.
+     * </p>
+     *
+     * @param historyMaxSize The max history size.
+     */
+    public void setHistoryMaxSize(int historyMaxSize) {
+        synchronized (mInstanceLock) {
+            if (mHistoryMaxSize == historyMaxSize) {
+                return;
+            }
+            mHistoryMaxSize = historyMaxSize;
+            pruneExcessiveHistoricalRecordsLocked();
+            sortActivities();
+        }
+    }
+
+    /**
+     * Gets the history max size.
+     *
+     * @return The history max size.
+     */
+    public int getHistoryMaxSize() {
+        synchronized (mInstanceLock) {
+            return mHistoryMaxSize;
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        super.finalize();
+        mPackageMonitor.unregister();
+    }
+
+    /**
+     * Adds a historical record.
+     *
+     * @param historicalRecord The record to add.
+     * @return True if the record was added.
+     */
+    private boolean addHisoricalRecord(HistoricalRecord historicalRecord) {
+        synchronized (mInstanceLock) {
+            final boolean added = mHistoricalRecords.add(historicalRecord);
+            if (added) {
+                mHistoricalRecordsChanged = true;
+                pruneExcessiveHistoricalRecordsLocked();
+                sortActivities();
+            }
+            return added;
+        }
+    }
+
+    /**
+     * Prunes older excessive records to guarantee {@link #mHistoryMaxSize}.
+     */
+    private void pruneExcessiveHistoricalRecordsLocked() {
+        List<HistoricalRecord> choiceRecords = mHistoricalRecords;
+        final int pruneCount = choiceRecords.size() - mHistoryMaxSize;
+        if (pruneCount <= 0) {
+            return;
+        }
+        mHistoricalRecordsChanged = true;
+        for (int i = 0; i < pruneCount; i++) {
+            HistoricalRecord prunedRecord = choiceRecords.remove(0);
+            if (DEBUG) {
+                Log.i(LOG_TAG, "Pruned: " + prunedRecord);
+            }
+        }
+    }
+
+    /**
+     * Loads the activities.
+     */
+    private void loadActivitiesLocked() {
+        mActivitys.clear();
+        if (mIntent != null) {
+            List<ResolveInfo> resolveInfos =
+                mContext.getPackageManager().queryIntentActivities(mIntent, 0);
+            final int resolveInfoCount = resolveInfos.size();
+            for (int i = 0; i < resolveInfoCount; i++) {
+                ResolveInfo resolveInfo = resolveInfos.get(i);
+                mActivitys.add(new Activity(resolveInfo));
+            }
+            sortActivities();
+        } else {
+            notifyChanged();
+        }
+    }
+
+    /**
+     * Prunes historical records for a package that goes away.
+     *
+     * @param packageName The name of the package that goes away.
+     */
+    private void pruneHistoricalRecordsForPackageLocked(String packageName) {
+        boolean recordsRemoved = false;
+
+        List<HistoricalRecord> historicalRecords = mHistoricalRecords;
+        for (int i = 0; i < historicalRecords.size(); i++) {
+            HistoricalRecord historicalRecord = historicalRecords.get(i);
+            String recordPackageName = historicalRecord.activity.getPackageName();
+            if (recordPackageName.equals(packageName)) {
+                historicalRecords.remove(historicalRecord);
+                recordsRemoved = true;
+            }
+        }
+
+        if (recordsRemoved) {
+            mHistoricalRecordsChanged = true;
+            sortActivities();
+        }
+    }
+
+    /**
+     * Represents a record in the history.
+     */
+    public final static class HistoricalRecord {
+
+        /**
+         * The activity name.
+         */
+        public final ComponentName activity;
+
+        /**
+         * The choice time.
+         */
+        public final long time;
+
+        /**
+         * The record weight.
+         */
+        public final float weight;
+
+        /**
+         * Creates a new instance.
+         *
+         * @param activityName The activity component name flattened to string.
+         * @param time The time the activity was chosen.
+         * @param weight The weight of the record.
+         */
+        public HistoricalRecord(String activityName, long time, float weight) {
+            this(ComponentName.unflattenFromString(activityName), time, weight);
+        }
+
+        /**
+         * Creates a new instance.
+         *
+         * @param activityName The activity name.
+         * @param time The time the activity was chosen.
+         * @param weight The weight of the record.
+         */
+        public HistoricalRecord(ComponentName activityName, long time, float weight) {
+            this.activity = activityName;
+            this.time = time;
+            this.weight = weight;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((activity == null) ? 0 : activity.hashCode());
+            result = prime * result + (int) (time ^ (time >>> 32));
+            result = prime * result + Float.floatToIntBits(weight);
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            HistoricalRecord other = (HistoricalRecord) obj;
+            if (activity == null) {
+                if (other.activity != null) {
+                    return false;
+                }
+            } else if (!activity.equals(other.activity)) {
+                return false;
+            }
+            if (time != other.time) {
+                return false;
+            }
+            if (Float.floatToIntBits(weight) != Float.floatToIntBits(other.weight)) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("[");
+            builder.append("; activity:").append(activity);
+            builder.append("; time:").append(time);
+            builder.append("; weight:").append(new BigDecimal(weight));
+            builder.append("]");
+            return builder.toString();
+        }
+    }
+
+    /**
+     * Represents an activity.
+     */
+    public final class Activity implements Comparable<Activity> {
+
+        /**
+         * The {@link ResolveInfo} of the activity.
+         */
+        public final ResolveInfo resolveInfo;
+
+        /**
+         * Weight of the activity. Useful for sorting.
+         */
+        public float weight;
+
+        /**
+         * Creates a new instance.
+         *
+         * @param resolveInfo activity {@link ResolveInfo}.
+         */
+        public Activity(ResolveInfo resolveInfo) {
+            this.resolveInfo = resolveInfo;
+        }
+
+        @Override
+        public int hashCode() {
+            return 31 + Float.floatToIntBits(weight);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            Activity other = (Activity) obj;
+            if (Float.floatToIntBits(weight) != Float.floatToIntBits(other.weight)) {
+                return false;
+            }
+            return true;
+        }
+
+        public int compareTo(Activity another) {
+             return  Float.floatToIntBits(another.weight) - Float.floatToIntBits(weight);
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("[");
+            builder.append("resolveInfo:").append(resolveInfo.toString());
+            builder.append("; weight:").append(new BigDecimal(weight));
+            builder.append("]");
+            return builder.toString();
+        }
+    }
+
+    /**
+     * Default activity sorter implementation.
+     */
+    private final class DefaultSorter implements ActivitySorter {
+        private static final float WEIGHT_DECAY_COEFFICIENT = 0.95f;
+
+        private final Map<String, Activity> mPackageNameToActivityMap =
+            new HashMap<String, Activity>();
+
+        public void sort(Intent intent, List<Activity> activities,
+                List<HistoricalRecord> historicalRecords) {
+            Map<String, Activity> packageNameToActivityMap =
+                mPackageNameToActivityMap;
+            packageNameToActivityMap.clear();
+
+            final int activityCount = activities.size();
+            for (int i = 0; i < activityCount; i++) {
+                Activity activity = activities.get(i);
+                activity.weight = 0.0f;
+                String packageName = activity.resolveInfo.activityInfo.packageName;
+                packageNameToActivityMap.put(packageName, activity);
+            }
+
+            final int lastShareIndex = historicalRecords.size() - 1;
+            float nextRecordWeight = 1;
+            for (int i = lastShareIndex; i >= 0; i--) {
+                HistoricalRecord historicalRecord = historicalRecords.get(i);
+                String packageName = historicalRecord.activity.getPackageName();
+                Activity activity = packageNameToActivityMap.get(packageName);
+                activity.weight += historicalRecord.weight * nextRecordWeight;
+                nextRecordWeight = nextRecordWeight * WEIGHT_DECAY_COEFFICIENT;
+            }
+
+            Collections.sort(activities);
+
+            if (DEBUG) {
+                for (int i = 0; i < activityCount; i++) {
+                    Log.i(LOG_TAG, "Sorted: " + activities.get(i));
+                }
+            }
+        }
+    }
+
+    /**
+     * Command for reading the historical records from a file off the UI thread.
+     */
+    private final class HistoryLoader implements Runnable {
+
+       public void run() {
+            FileInputStream fis = null;
+            try {
+                fis = mContext.openFileInput(mHistoryFileName);
+            } catch (FileNotFoundException fnfe) {
+                if (DEBUG) {
+                    Log.i(LOG_TAG, "Could not open historical records file: " + mHistoryFileName);
+                }
+                return;
+            }
+            try {
+                XmlPullParser parser = Xml.newPullParser();
+                parser.setInput(fis, null);
+
+                int type = XmlPullParser.START_DOCUMENT;
+                while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
+                    type = parser.next();
+                }
+
+                if (!TAG_HISTORICAL_RECORDS.equals(parser.getName())) {
+                    throw new XmlPullParserException("Share records file does not start with "
+                            + TAG_HISTORICAL_RECORDS + " tag.");
+                }
+
+                List<HistoricalRecord> readRecords = new ArrayList<HistoricalRecord>();
+
+                while (true) {
+                    type = parser.next();
+                    if (type == XmlPullParser.END_DOCUMENT) {
+                        break;
+                    }
+                    if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                        continue;
+                    }
+                    String nodeName = parser.getName();
+                    if (!TAG_HISTORICAL_RECORD.equals(nodeName)) {
+                        throw new XmlPullParserException("Share records file not well-formed.");
+                    }
+
+                    String activity = parser.getAttributeValue(null, ATTRIBUTE_ACTIVITY);
+                    final long time =
+                        Long.parseLong(parser.getAttributeValue(null, ATTRIBUTE_TIME));
+                    final float weight =
+                        Float.parseFloat(parser.getAttributeValue(null, ATTRIBUTE_WEIGHT));
+
+                    HistoricalRecord readRecord = new HistoricalRecord(activity, time,
+                            weight);
+                    readRecords.add(readRecord);
+
+                    if (DEBUG) {
+                        Log.i(LOG_TAG, "Read " + readRecord.toString());
+                    }
+                }
+
+                if (DEBUG) {
+                    Log.i(LOG_TAG, "Read " + readRecords.size() + " historical records.");
+                }
+
+                synchronized (mInstanceLock) {
+                    Set<HistoricalRecord> uniqueShareRecords =
+                        new LinkedHashSet<HistoricalRecord>(readRecords);
+
+                    // Make sure no duplicates. Example: Read a file with
+                    // one record, add one record, persist the two records,
+                    // add a record, read the persisted records - the
+                    // read two records should not be added again.
+                    List<HistoricalRecord> historicalRecords = mHistoricalRecords;
+                    final int historicalRecordsCount = historicalRecords.size();
+                    for (int i = historicalRecordsCount - 1; i >= 0; i--) {
+                        HistoricalRecord historicalRecord = historicalRecords.get(i);
+                        uniqueShareRecords.add(historicalRecord);
+                    }
+
+                    if (historicalRecords.size() == uniqueShareRecords.size()) {
+                        return;
+                    }
+
+                    // Make sure the oldest records go to the end.
+                    historicalRecords.clear();
+                    historicalRecords.addAll(uniqueShareRecords);
+
+                    mHistoricalRecordsChanged = true;
+
+                    // Do this on the client thread since the client may be on the UI
+                    // thread, wait for data changes which happen during sorting, and
+                    // perform UI modification based on the data change.
+                    mHandler.post(new Runnable() {
+                        public void run() {
+                            pruneExcessiveHistoricalRecordsLocked();
+                            sortActivities();
+                        }
+                    });
+                }
+            } catch (XmlPullParserException xppe) {
+                Log.e(LOG_TAG, "Error reading historical recrod file: " + mHistoryFileName, xppe);
+            } catch (IOException ioe) {
+                Log.e(LOG_TAG, "Error reading historical recrod file: " + mHistoryFileName, ioe);
+            } finally {
+                if (fis != null) {
+                    try {
+                        fis.close();
+                    } catch (IOException ioe) {
+                        /* ignore */
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Command for persisting the historical records to a file off the UI thread.
+     */
+    private final class HistoryPersister implements Runnable {
+
+        public void run() {
+            FileOutputStream fos = null;
+            List<HistoricalRecord> records = null;
+
+            synchronized (mInstanceLock) {
+                records = new ArrayList<HistoricalRecord>(mHistoricalRecords);
+            }
+
+            try {
+                fos = mContext.openFileOutput(mHistoryFileName, Context.MODE_PRIVATE);
+            } catch (FileNotFoundException fnfe) {
+                Log.e(LOG_TAG, "Error writing historical recrod file: " + mHistoryFileName, fnfe);
+                return;
+            }
+
+            XmlSerializer serializer = Xml.newSerializer();
+
+            try {
+                serializer.setOutput(fos, null);
+                serializer.startDocument("UTF-8", true);
+                serializer.startTag(null, TAG_HISTORICAL_RECORDS);
+
+                final int recordCount = records.size();
+                for (int i = 0; i < recordCount; i++) {
+                    HistoricalRecord record = records.remove(0);
+                    serializer.startTag(null, TAG_HISTORICAL_RECORD);
+                    serializer.attribute(null, ATTRIBUTE_ACTIVITY, record.activity.flattenToString());
+                    serializer.attribute(null, ATTRIBUTE_TIME, String.valueOf(record.time));
+                    serializer.attribute(null, ATTRIBUTE_WEIGHT, String.valueOf(record.weight));
+                    serializer.endTag(null, TAG_HISTORICAL_RECORD);
+                    if (DEBUG) {
+                        Log.i(LOG_TAG, "Wrote " + record.toString());
+                    }
+                }
+
+                serializer.endTag(null, TAG_HISTORICAL_RECORDS);
+                serializer.endDocument();
+
+                if (DEBUG) {
+                    Log.i(LOG_TAG, "Wrote " + recordCount + " historical records.");
+                }
+            } catch (IllegalArgumentException iae) {
+                Log.e(LOG_TAG, "Error writing historical recrod file: " + mHistoryFileName, iae);
+            } catch (IllegalStateException ise) {
+                Log.e(LOG_TAG, "Error writing historical recrod file: " + mHistoryFileName, ise);
+            } catch (IOException ioe) {
+                Log.e(LOG_TAG, "Error writing historical recrod file: " + mHistoryFileName, ioe);
+            } finally {
+                if (fos != null) {
+                    try {
+                        fos.close();
+                    } catch (IOException e) {
+                        /* ignore */
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Keeps in sync the historical records and activities with the installed applications.
+     */
+    private final class DataModelPackageMonitor extends PackageMonitor {
+
+        @Override
+        public void onPackageAdded(String packageName, int uid) {
+            synchronized (mInstanceLock) {
+                loadActivitiesLocked();
+            }
+        }
+
+        @Override
+        public void onPackageAppeared(String packageName, int reason) {
+            synchronized (mInstanceLock) {
+                loadActivitiesLocked();
+            }
+        }
+
+        @Override
+        public void onPackageRemoved(String packageName, int uid) {
+            synchronized (mInstanceLock) {
+                pruneHistoricalRecordsForPackageLocked(packageName);
+                loadActivitiesLocked();
+            }
+        }
+
+        @Override
+        public void onPackageDisappeared(String packageName, int reason) {
+            synchronized (mInstanceLock) {
+                pruneHistoricalRecordsForPackageLocked(packageName);
+                loadActivitiesLocked();
+            }
+        }
+    }
+}
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
new file mode 100644
index 0000000..2fe8162
--- /dev/null
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -0,0 +1,765 @@
+/*
+ * 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.widget;
+
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.os.Debug;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ActivityChooserModel.ActivityChooserModelClient;
+
+import com.android.internal.R;
+
+/**
+ * This class is a view for choosing an activity for handling a given {@link Intent}.
+ * <p>
+ * The view is composed of two adjacent buttons:
+ * <ul>
+ * <li>
+ * The left button is an immediate action and allows one click activity choosing.
+ * Tapping this button immediately executes the intent without requiring any further
+ * user input. Long press on this button shows a popup for changing the default
+ * activity.
+ * </li>
+ * <li>
+ * The right button is an overflow action and provides an optimized menu
+ * of additional activities. Tapping this button shows a popup anchored to this
+ * view, listing the most frequently used activities. This list is initially
+ * limited to a small number of items in frequency used order. The last item,
+ * "Show all..." serves as an affordance to display all available activities.
+ * </li>
+ * </ul>
+ * </p>
+ * </p>
+ * This view is backed by a {@link ActivityChooserModel}. Calling {@link #showPopup()}
+ * while this view is attached to the view hierarchy will show a popup with
+ * activities while if the view is not attached it will show a dialog.
+ * </p>
+ *
+ * @hide
+ */
+public class ActivityChooserView extends ViewGroup implements ActivityChooserModelClient {
+
+    /**
+     * An adapter for displaying the activities in an {@link AdapterView}.
+     */
+    private final ActivityChooserViewAdapter mAdapter;
+
+    /**
+     * Implementation of various interfaces to avoid publishing them in the APIs.
+     */
+    private final Callbacks mCallbacks;
+
+    /**
+     * The content of this view.
+     */
+    private final LinearLayout mActivityChooserContent;
+
+    /**
+     * The expand activities action button;
+     */
+    private final ImageButton mExpandActivityOverflowButton;
+
+    /**
+     * The default activities action button;
+     */
+    private final ImageButton mDefaultActionButton;
+
+    /**
+     * The header for handlers list.
+     */
+    private final View mListHeaderView;
+
+    /**
+     * The footer for handlers list.
+     */
+    private final View mListFooterView;
+
+    /**
+     * The title of the header view.
+     */
+    private TextView mListHeaderViewTitle;
+
+    /**
+     * The title for expanding the activities list.
+     */
+    private final String mListHeaderViewTitleSelectDefault;
+
+    /**
+     * The title if no activity exist.
+     */
+    private final String mListHeaderViewTitleNoActivities;
+
+    /**
+     * Popup window for showing the activity overflow list.
+     */
+    private ListPopupWindow mListPopupWindow;
+
+    /**
+     * Alert dialog for showing the activity overflow list.
+     */
+    private AlertDialog mAlertDialog;
+
+    /**
+     * Listener for the dismissal of the popup/alert.
+     */
+    private PopupWindow.OnDismissListener mOnDismissListener;
+
+    /**
+     * Flag whether a default activity currently being selected.
+     */
+    private boolean mIsSelectingDefaultActivity;
+
+    /**
+     * The count of activities in the popup.
+     */
+    private int mInitialActivityCount = ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT;
+
+    /**
+     * Flag whether this view is attached to a window.
+     */
+    private boolean mIsAttachedToWindow;
+
+    /**
+     * Flag whether this view is showing an alert dialog.
+     */
+    private boolean mIsShowingAlertDialog;
+
+    /**
+     * Flag whether this view is showing a popup window.
+     */
+    private boolean mIsShowingPopuWindow;
+
+    /**
+     * Create a new instance.
+     *
+     * @param context The application environment.
+     */
+    public ActivityChooserView(Context context) {
+        this(context, null);
+    }
+
+    /**
+     * Create a new instance.
+     *
+     * @param context The application environment.
+     * @param attrs A collection of attributes.
+     */
+    public ActivityChooserView(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.actionButtonStyle);
+    }
+
+    /**
+     * Create a new instance.
+     *
+     * @param context The application environment.
+     * @param attrs A collection of attributes.
+     * @param defStyle The default style to apply to this view.
+     */
+    public ActivityChooserView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        TypedArray attributesArray = context.obtainStyledAttributes(attrs,
+                R.styleable.ActivityChooserView, defStyle, 0);
+
+        mInitialActivityCount = attributesArray.getInt(
+                R.styleable.ActivityChooserView_initialActivityCount,
+                ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT);
+
+        Drawable expandActivityOverflowButtonDrawable = attributesArray.getDrawable(
+                R.styleable.ActivityChooserView_expandActivityOverflowButtonDrawable);
+
+        LayoutInflater inflater = (LayoutInflater) context.getSystemService(
+                Context.LAYOUT_INFLATER_SERVICE);
+        inflater.inflate(R.layout.activity_chooser_view, this, true);
+
+        mCallbacks = new Callbacks();
+
+        mActivityChooserContent = (LinearLayout) findViewById(R.id.activity_chooser_view_content);
+
+        mDefaultActionButton = (ImageButton) findViewById(R.id.default_activity_button);
+        mDefaultActionButton.setOnClickListener(mCallbacks);
+        mDefaultActionButton.setOnLongClickListener(mCallbacks);
+
+        mExpandActivityOverflowButton = (ImageButton) findViewById(R.id.expand_activities_button);
+        mExpandActivityOverflowButton.setOnClickListener(mCallbacks);
+        mExpandActivityOverflowButton.setBackgroundDrawable(expandActivityOverflowButtonDrawable);
+
+        mListHeaderView = inflater.inflate(R.layout.activity_chooser_list_header, null);
+        mListFooterView = inflater.inflate(R.layout.activity_chooser_list_footer, null);
+
+        mListHeaderViewTitle = (TextView) mListHeaderView.findViewById(R.id.title);
+        mListHeaderViewTitleSelectDefault = context.getString(
+                R.string.activity_chooser_view_select_default);
+        mListHeaderViewTitleNoActivities = context.getString(
+                R.string.activity_chooser_view_no_activities);
+
+        mAdapter = new ActivityChooserViewAdapter();
+        mAdapter.registerDataSetObserver(new DataSetObserver() {
+            @Override
+            public void onChanged() {
+                super.onChanged();
+                updateButtons();
+            }
+        });
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setActivityChooserModel(ActivityChooserModel dataModel) {
+        mAdapter.setDataModel(dataModel);
+        if (isShowingPopup()) {
+            dismissPopup();
+            showPopup();
+        }
+    }
+
+    /**
+     * Sets the background for the button that expands the activity
+     * overflow list.
+     *
+     * <strong>Note:</strong> Clients would like to set this drawable
+     * as a clue about the action the chosen activity will perform. For
+     * example, if share activity is to be chosen the drawable should
+     * give a clue that sharing is to be performed.
+     *
+     * @param drawable The drawable.
+     */
+    public void setExpandActivityOverflowButtonDrawable(Drawable drawable) {
+        mExpandActivityOverflowButton.setBackgroundDrawable(drawable);
+    }
+
+    /**
+     * Shows the popup window with activities.
+     *
+     * @return True if the popup was shown, false if already showing.
+     */
+    public boolean showPopup() {
+        if (isShowingPopup()) {
+            return false;
+        }
+        mIsSelectingDefaultActivity = false;
+        showPopupUnchecked(mInitialActivityCount);
+        return true;
+    }
+
+    /**
+     * Shows the popup no matter if it was already showing.
+     *
+     * @param maxActivityCount The max number of activities to display.
+     */
+    private void showPopupUnchecked(int maxActivityCount) {
+        mAdapter.setMaxActivityCount(maxActivityCount);
+        if (mIsSelectingDefaultActivity) {
+            if (mAdapter.getActivityCount() > 0) {
+                mListHeaderViewTitle.setText(mListHeaderViewTitleSelectDefault);
+            } else {
+                mListHeaderViewTitle.setText(mListHeaderViewTitleNoActivities);
+            }
+            mAdapter.setHeaderView(mListHeaderView);
+        } else {
+            mAdapter.setHeaderView(null);
+        }
+
+        if (mAdapter.getActivityCount() > maxActivityCount + 1) {
+            mAdapter.setFooterView(mListFooterView);
+        } else {
+            mAdapter.setFooterView(null);
+        }
+
+        if (!mIsAttachedToWindow || mIsShowingAlertDialog) {
+            AlertDialog alertDialog = getAlertDilalog();
+            if (!alertDialog.isShowing()) {
+                alertDialog.setCustomTitle(this);
+                alertDialog.show();
+                mIsShowingAlertDialog = true;
+            }
+        } else {
+            ListPopupWindow popupWindow = getListPopupWindow();
+            if (!popupWindow.isShowing()) {
+                popupWindow.setContentWidth(mAdapter.measureContentWidth());
+                popupWindow.show();
+                mIsShowingPopuWindow = true;
+            }
+        }
+    }
+
+    /**
+     * Dismisses the popup window with activities.
+     *
+     * @return True if dismissed, false if already dismissed.
+     */
+    public boolean dismissPopup() {
+        if (!isShowingPopup()) {
+            return false;
+        }
+        if (mIsShowingAlertDialog) {
+            getAlertDilalog().dismiss();
+        } else if (mIsShowingPopuWindow) {
+            getListPopupWindow().dismiss();
+        }
+        return true;
+    }
+
+    /**
+     * Gets whether the popup window with activities is shown.
+     *
+     * @return True if the popup is shown.
+     */
+    public boolean isShowingPopup() {
+        if (mIsShowingAlertDialog) {
+            return getAlertDilalog().isShowing();
+        } else if (mIsShowingPopuWindow) {
+            return getListPopupWindow().isShowing();
+        }
+        return false;
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        ActivityChooserModel dataModel = mAdapter.getDataModel();
+        if (dataModel != null) {
+            dataModel.readHistoricalData();
+        }
+        mIsAttachedToWindow = true;
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        ActivityChooserModel dataModel = mAdapter.getDataModel();
+        if (dataModel != null) {
+            dataModel.persistHistoricalData();
+        }
+        mIsAttachedToWindow = false;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        mActivityChooserContent.measure(widthMeasureSpec, heightMeasureSpec);
+        setMeasuredDimension(mActivityChooserContent.getMeasuredWidth(),
+                mActivityChooserContent.getMeasuredHeight());
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        mActivityChooserContent.layout(left, top, right, bottom);
+        if (mIsShowingPopuWindow) {
+            if (isShown()) {
+                showPopupUnchecked(mAdapter.getMaxActivityCount());
+            } else {
+                dismissPopup();
+            }
+        }
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        mActivityChooserContent.onDraw(canvas);
+    }
+
+    public ActivityChooserModel getDataModel() {
+        return mAdapter.getDataModel();
+    }
+
+    /**
+     * Sets a listener to receive a callback when the popup is dismissed.
+     *
+     * @param listener The listener to be notified.
+     */
+    public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
+        mOnDismissListener = listener;
+    }
+
+    /**
+     * Sets the initial count of items shown in the activities popup
+     * i.e. the items before the popup is expanded. This is an upper
+     * bound since it is not guaranteed that such number of intent
+     * handlers exist.
+     *
+     * @param itemCount The initial popup item count.
+     */
+    public void setInitialActivityCount(int itemCount) {
+        mInitialActivityCount = itemCount;
+    }
+
+    /**
+     * Gets the list popup window which is lazily initialized.
+     *
+     * @return The popup.
+     */
+    private ListPopupWindow getListPopupWindow() {
+        if (mListPopupWindow == null) {
+            mListPopupWindow = new ListPopupWindow(getContext());
+            mListPopupWindow.setAdapter(mAdapter);
+            mListPopupWindow.setAnchorView(ActivityChooserView.this);
+            mListPopupWindow.setModal(true);
+            mListPopupWindow.setOnItemClickListener(mCallbacks);
+            mListPopupWindow.setOnDismissListener(mCallbacks);
+        }
+        return mListPopupWindow;
+    }
+
+    /**
+     * Gets the alert dialog which is lazily initialized.
+     *
+     * @return The popup.
+     */
+    private AlertDialog getAlertDilalog() {
+        if (mAlertDialog == null) {
+            Builder builder = new Builder(getContext());
+            builder.setAdapter(mAdapter, null);
+            mAlertDialog = builder.create();
+            mAlertDialog.getListView().setOnItemClickListener(mCallbacks);
+            mAlertDialog.setOnDismissListener(mCallbacks);
+        }
+        return mAlertDialog;
+    }
+
+    /**
+     * Updates the buttons state.
+     */
+    private void updateButtons() {
+        final int activityCount = mAdapter.getActivityCount();
+        if (activityCount > 0) {
+            mDefaultActionButton.setVisibility(VISIBLE);
+            if (mAdapter.getCount() > 0) {
+                mExpandActivityOverflowButton.setEnabled(true);
+            } else {
+                mExpandActivityOverflowButton.setEnabled(false);
+            }
+            ResolveInfo activity = mAdapter.getDefaultActivity();
+            PackageManager packageManager = mContext.getPackageManager();
+            mDefaultActionButton.setBackgroundDrawable(activity.loadIcon(packageManager));
+        } else {
+            mDefaultActionButton.setVisibility(View.INVISIBLE);
+            mExpandActivityOverflowButton.setEnabled(false);
+        }
+    }
+
+    /**
+     * Interface implementation to avoid publishing them in the APIs.
+     */
+    private class Callbacks implements AdapterView.OnItemClickListener,
+            View.OnClickListener, View.OnLongClickListener, PopupWindow.OnDismissListener,
+            DialogInterface.OnDismissListener {
+
+        // AdapterView#OnItemClickListener
+        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+            ActivityChooserViewAdapter adapter = (ActivityChooserViewAdapter) parent.getAdapter();
+            final int itemViewType = adapter.getItemViewType(position);
+            switch (itemViewType) {
+                case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_HEADER: {
+                    /* do nothing */
+                } break;
+                case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_FOOTER: {
+                    showPopupUnchecked(ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED);
+                } break;
+                case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_ACTIVITY: {
+                    dismissPopup();
+                    if (mIsSelectingDefaultActivity) {
+                        mAdapter.getDataModel().setDefaultActivity(position);
+                    } else {
+                        // The first item in the model is default action => adjust index
+                        Intent launchIntent = mAdapter.getDataModel().chooseActivity(position + 1);
+                        mContext.startActivity(launchIntent);
+                    }
+                } break;
+                default:
+                    throw new IllegalArgumentException();
+            }
+        }
+
+        // View.OnClickListener
+        public void onClick(View view) {
+            if (view == mDefaultActionButton) {
+                dismissPopup();
+                ResolveInfo defaultActivity = mAdapter.getDefaultActivity();
+                final int index = mAdapter.getDataModel().getActivityIndex(defaultActivity);
+                Intent launchIntent = mAdapter.getDataModel().chooseActivity(index);
+                mContext.startActivity(launchIntent);
+            } else if (view == mExpandActivityOverflowButton) {
+                mIsSelectingDefaultActivity = false;
+                showPopupUnchecked(mInitialActivityCount);
+            } else {
+                throw new IllegalArgumentException();
+            }
+        }
+
+        // OnLongClickListener#onLongClick
+        @Override
+        public boolean onLongClick(View view) {
+            if (view == mDefaultActionButton) {
+                if (mAdapter.getCount() > 0) {
+                    mIsSelectingDefaultActivity = true;
+                    showPopupUnchecked(mInitialActivityCount);
+                }
+            } else {
+                throw new IllegalArgumentException();
+            }
+            return true;
+        }
+
+        // PopUpWindow.OnDismissListener#onDismiss
+        public void onDismiss() {
+            mIsShowingPopuWindow = false;
+            notifyOnDismissListener();
+        }
+
+        // DialogInterface.OnDismissListener#onDismiss
+        @Override
+        public void onDismiss(DialogInterface dialog) {
+            mIsShowingAlertDialog = false;
+            AlertDialog alertDialog = (AlertDialog) dialog;
+            alertDialog.setCustomTitle(null);
+            notifyOnDismissListener();
+        }
+
+        private void notifyOnDismissListener() {
+            if (mOnDismissListener != null) {
+                mOnDismissListener.onDismiss();
+            }
+        }
+    }
+
+    /**
+     * Adapter for backing the list of activities shown in the popup.
+     */
+    private class ActivityChooserViewAdapter extends BaseAdapter {
+
+        public static final int MAX_ACTIVITY_COUNT_UNLIMITED = Integer.MAX_VALUE;
+
+        public static final int MAX_ACTIVITY_COUNT_DEFAULT = 4;
+
+        private static final int ITEM_VIEW_TYPE_HEADER = 0;
+
+        private static final int ITEM_VIEW_TYPE_ACTIVITY = 1;
+
+        private static final int ITEM_VIEW_TYPE_FOOTER = 2;
+
+        private static final int ITEM_VIEW_TYPE_COUNT = 3;
+
+        private final DataSetObserver mDataSetOberver = new DataSetObserver() {
+
+            @Override
+            public void onChanged() {
+                super.onChanged();
+                notifyDataSetChanged();
+            }
+            @Override
+            public void onInvalidated() {
+                super.onInvalidated();
+                notifyDataSetInvalidated();
+            }
+        };
+
+        private ActivityChooserModel mDataModel;
+
+        private int mMaxActivityCount = MAX_ACTIVITY_COUNT_DEFAULT;
+
+        private ResolveInfo mDefaultActivity;
+
+        private View mHeaderView;
+
+        private View mFooterView;
+
+        public void setDataModel(ActivityChooserModel dataModel) {
+            mDataModel = dataModel;
+            mDataModel.registerObserver(mDataSetOberver);
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public void notifyDataSetChanged() {
+            if (mDataModel.getActivityCount() > 0) {
+                mDefaultActivity = mDataModel.getDefaultActivity();
+            } else {
+                mDefaultActivity = null;
+            }
+            super.notifyDataSetChanged();
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            if (mHeaderView != null && position == 0) {
+                return ITEM_VIEW_TYPE_HEADER;
+            } else if (mFooterView != null && position == getCount() - 1) {
+                return ITEM_VIEW_TYPE_FOOTER;
+            } else {
+                return ITEM_VIEW_TYPE_ACTIVITY;
+            }
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return ITEM_VIEW_TYPE_COUNT;
+        }
+
+        public int getCount() {
+            int count = 0;
+            int activityCount = mDataModel.getActivityCount();
+            if (activityCount > 0) {
+                activityCount--;
+            }
+            count = Math.min(activityCount, mMaxActivityCount);
+            if (mHeaderView != null) {
+                count++;
+            }
+            if (mFooterView != null) {
+                count++;
+            }
+            return count;
+        }
+
+        public Object getItem(int position) {
+            final int itemViewType = getItemViewType(position);
+            switch (itemViewType) {
+                case ITEM_VIEW_TYPE_HEADER:
+                    return mHeaderView;
+                case ITEM_VIEW_TYPE_FOOTER:
+                    return mFooterView;
+                case ITEM_VIEW_TYPE_ACTIVITY:
+                    int targetIndex = (mHeaderView == null) ? position : position - 1;
+                    if (mDefaultActivity != null) {
+                        targetIndex++;
+                    }
+                    return mDataModel.getActivity(targetIndex);
+                default:
+                    throw new IllegalArgumentException();
+            }
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public boolean isEnabled(int position) {
+            final int itemViewType = getItemViewType(position);
+            switch (itemViewType) {
+                case ITEM_VIEW_TYPE_HEADER:
+                    return false;
+                case ITEM_VIEW_TYPE_FOOTER:
+                case ITEM_VIEW_TYPE_ACTIVITY:
+                    return true;
+                default:
+                    throw new IllegalArgumentException();
+            }
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            final int itemViewType = getItemViewType(position);
+            switch (itemViewType) {
+                case ITEM_VIEW_TYPE_HEADER:
+                    return mHeaderView;
+                case ITEM_VIEW_TYPE_FOOTER:
+                    return mFooterView;
+                case ITEM_VIEW_TYPE_ACTIVITY:
+                    if (convertView == null || convertView.getId() != R.id.list_item) {
+                        convertView = LayoutInflater.from(getContext()).inflate(
+                                R.layout.activity_chooser_view_list_item, parent, false);
+                    }
+                    PackageManager packageManager = mContext.getPackageManager();
+                    // Set the icon
+                    ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
+                    ResolveInfo activity = (ResolveInfo) getItem(position);
+                    iconView.setBackgroundDrawable(activity.loadIcon(packageManager));
+                    // Set the title.
+                    TextView titleView = (TextView) convertView.findViewById(R.id.title);
+                    titleView.setText(activity.loadLabel(packageManager));
+                    return convertView;
+                default:
+                    throw new IllegalArgumentException();
+            }
+        }
+
+        public int measureContentWidth() {
+            // The user may have specified some of the target not to be show but we
+            // want to measure all of them since after expansion they should fit.
+            final int oldMaxActivityCount = mMaxActivityCount;
+            mMaxActivityCount = MAX_ACTIVITY_COUNT_UNLIMITED;
+
+            int contentWidth = 0;
+            View itemView = null;
+
+            final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+            final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+            final int count = getCount();
+
+            for (int i = 0; i < count; i++) {
+                itemView = getView(i, itemView, null);
+                itemView.measure(widthMeasureSpec, heightMeasureSpec);
+                contentWidth = Math.max(contentWidth, itemView.getMeasuredWidth());
+            }
+
+            mMaxActivityCount = oldMaxActivityCount;
+
+            return contentWidth;
+        }
+
+        public void setMaxActivityCount(int maxActivityCount) {
+            if (mMaxActivityCount != maxActivityCount) {
+                mMaxActivityCount = maxActivityCount;
+                notifyDataSetChanged();
+            }
+        }
+
+        public ResolveInfo getDefaultActivity() {
+            return mDefaultActivity;
+        }
+
+        public void setHeaderView(View headerView) {
+            if (mHeaderView != headerView) {
+                mHeaderView = headerView;
+                notifyDataSetChanged();
+            }
+        }
+
+        public void setFooterView(View footerView) {
+            if (mFooterView != footerView) {
+                mFooterView = footerView;
+                notifyDataSetChanged();
+            }
+        }
+
+        public int getActivityCount() {
+            return mDataModel.getActivityCount();
+        }
+
+        public int getMaxActivityCount() {
+            return mMaxActivityCount;
+        }
+
+        public ActivityChooserModel getDataModel() {
+            return mDataModel;
+        }
+    }
+}
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index ce76bee..0ffd087 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -34,6 +34,8 @@
 import android.view.ViewGroup;
 import android.view.SoundEffectConstants;
 import android.view.ContextMenu.ContextMenuInfo;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.Transformation;
 
 /**
@@ -344,7 +346,34 @@
     int getChildHeight(View child) {
         return child.getMeasuredHeight();
     }
-    
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setScrollable(true);
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setScrollable(true);
+        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            event.setFromIndex(mFirstPosition);
+            event.setToIndex(mFirstPosition +  getChildCount());
+            event.setItemCount(mItemCount);
+        }
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        // Do not append text content to scroll events they are fired frequently
+        // and the client has already received another event type with the text.
+        if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            super.dispatchPopulateAccessibilityEvent(event);
+        }
+        return false;
+    }
+
     /**
      * Tracks a motion scroll. In reality, this is used to do just about any
      * movement to items (touch scroll, arrow-key scroll, set an item as selected).
@@ -382,7 +411,9 @@
         mRecycler.clear();
         
         setSelectionToCenterChild();
-        
+
+        onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
+
         invalidate();
     }
 
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 1570224..c2759e5 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -24,6 +24,7 @@
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.Pair;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
@@ -33,7 +34,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -67,7 +67,7 @@
  *
  * <h4>Default Cell Assignment</h4>
  *
- * If no child specifies the row and column indices of the cell it
+ * If a child does not specify the row and column indices of the cell it
  * wishes to occupy, GridLayout assigns cell locations automatically using its:
  * {@link GridLayout#setOrientation(int) orientation},
  * {@link GridLayout#setRowCount(int) rowCount} and
@@ -92,10 +92,8 @@
  *
  * <h4>Excess Space Distribution</h4>
  *
- * Like {@link LinearLayout}, a child's ability to stretch is controlled
- * using <em>weights</em>, which are specified using the
- * {@link GridLayout.LayoutParams#rowWeight rowWeight} and
- * {@link GridLayout.LayoutParams#columnWeight columnWeight} layout parameters.
+ * A child's ability to stretch is controlled using the {@link Group#flexibility flexibility}
+ * properties of its row and column groups.
  * <p>
  * <p>
  * See {@link GridLayout.LayoutParams} for a full description of the
@@ -171,9 +169,7 @@
     private static final String TAG = GridLayout.class.getName();
     private static final boolean DEBUG = false;
     private static final double GOLDEN_RATIO = (1 + Math.sqrt(5)) / 2;
-    private static final int MIN = 0;
     private static final int PRF = 1;
-    private static final int MAX = 2;
 
     // Defaults
 
@@ -184,6 +180,7 @@
     private static final int DEFAULT_ALIGNMENT_MODE = ALIGN_MARGINS;
     // todo remove this
     private static final int DEFAULT_CONTAINER_MARGIN = 20;
+    private static final int MAX_SIZE = 100000;
 
     // TypedArray indices
 
@@ -205,36 +202,16 @@
     private int mAlignmentMode = DEFAULT_ALIGNMENT_MODE;
     private int mDefaultGravity = Gravity.NO_GRAVITY;
 
-    /* package */ boolean accommodateBothMinAndMax = false;
-
     // Constructors
 
     /**
      * {@inheritDoc}
      */
-    public GridLayout(Context context) {
-        this(context, null, 0);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
     public GridLayout(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         if (DEBUG) {
             setWillNotDraw(false);
         }
-        processAttributes(context, attrs);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public GridLayout(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    private void processAttributes(Context context, AttributeSet attrs) {
         TypedArray a = context.obtainStyledAttributes(attrs, styleable.GridLayout);
         try {
             setRowCount(a.getInt(ROW_COUNT, DEFAULT_COUNT));
@@ -249,6 +226,20 @@
         }
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public GridLayout(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public GridLayout(Context context) {
+        this(context, null);
+    }
+
     // Implementation
 
     /**
@@ -527,11 +518,10 @@
         return result;
     }
 
-    private static int sum(float[] a) {
-        int result = 0;
-        for (int i = 0, length = a.length; i < length; i++) {
-            result += a[i];
-        }
+    private static <T> T[] append(T[] a, T[] b) {
+        T[] result = (T[]) Array.newInstance(a.getClass().getComponentType(), a.length + b.length);
+        System.arraycopy(a, 0, result, 0, a.length);
+        System.arraycopy(b, 0, result, a.length, b.length);
         return result;
     }
 
@@ -603,13 +593,13 @@
                     if (isGone(c)) continue;
                     LayoutParams lp = getLayoutParams1(c);
 
-                    Group colGroup = lp.columnGroup;
-                    Interval cols = colGroup.span;
-                    int colSpan = cols.size();
+                    final Group colGroup = lp.columnGroup;
+                    final Interval cols = colGroup.span;
+                    final int colSpan = cols.size();
 
-                    Group rowGroup = lp.rowGroup;
-                    Interval rows = rowGroup.span;
-                    int rowSpan = rows.size();
+                    final Group rowGroup = lp.rowGroup;
+                    final Interval rows = rowGroup.span;
+                    final int rowSpan = rows.size();
 
                     if (horizontal) {
                         row = valueIfDefined2(rows.min, row);
@@ -700,8 +690,8 @@
     }
 
     private void drawRectangle(Canvas graphics, int x1, int y1, int x2, int y2, Paint paint) {
-        // x2 = x2 - 1;
-        // y2 = y2 - 1;
+        x2 = x2 - 1;
+        y2 = y2 - 1;
         graphics.drawLine(x1, y1, x1, y2, paint);
         graphics.drawLine(x1, y1, x2, y1, paint);
         graphics.drawLine(x1, y2, x2, y2, paint);
@@ -734,9 +724,9 @@
                     drawLine(canvas, 0, y, width - 1, y, paint);
                 }
             }
+
             // Draw bounds
             paint.setColor(Color.BLUE);
-
             for (int i = 0; i < getChildCount(); i++) {
                 View c = getChildAt(i);
                 drawRectangle(canvas,
@@ -748,7 +738,6 @@
 
             // Draw margins
             paint.setColor(Color.YELLOW);
-
             for (int i = 0; i < getChildCount(); i++) {
                 View c = getChildAt(i);
                 drawRectangle(canvas,
@@ -819,11 +808,11 @@
     protected void onMeasure(int widthSpec, int heightSpec) {
         measureChildrenWithMargins(widthSpec, heightSpec);
 
-        int computedWidth = getPaddingLeft() + mHorizontalAxis.getMin() + getPaddingRight();
-        int computedHeight = getPaddingTop() + mVerticalAxis.getMin() + getPaddingBottom();
+        int width = getPaddingLeft() + mHorizontalAxis.getMeasure(widthSpec) + getPaddingRight();
+        int height = getPaddingTop() + mVerticalAxis.getMeasure(heightSpec) + getPaddingBottom();
 
-        int measuredWidth = Math.max(computedWidth, getSuggestedMinimumWidth());
-        int measuredHeight = Math.max(computedHeight, getSuggestedMinimumHeight());
+        int measuredWidth = Math.max(width, getSuggestedMinimumWidth());
+        int measuredHeight = Math.max(height, getSuggestedMinimumHeight());
 
         setMeasuredDimension(
                 resolveSizeAndState(measuredWidth, widthSpec, 0),
@@ -834,12 +823,12 @@
         return (alignment == UNDEFINED) ? 0 : alignment;
     }
 
-    private int getMeasurement(View c, boolean horizontal, int measurementType) {
+    private int getMeasurement(View c, boolean horizontal) {
         return horizontal ? c.getMeasuredWidth() : c.getMeasuredHeight();
     }
 
-    private int getMeasurementIncludingMargin(View c, boolean horizontal, int measurementType) {
-        int result = getMeasurement(c, horizontal, measurementType);
+    private int getMeasurementIncludingMargin(View c, boolean horizontal) {
+        int result = getMeasurement(c, horizontal);
         if (mAlignmentMode == ALIGN_MARGINS) {
             return result + getTotalMargin(c, horizontal);
         }
@@ -889,17 +878,17 @@
             Interval colSpan = columnGroup.span;
             Interval rowSpan = rowGroup.span;
 
-            int x1 = mHorizontalAxis.getLocationIncludingMargin(c, true, colSpan.min);
-            int y1 = mVerticalAxis.getLocationIncludingMargin(c, true, rowSpan.min);
+            int x1 = mHorizontalAxis.getLocationIncludingMargin(true, colSpan.min);
+            int y1 = mVerticalAxis.getLocationIncludingMargin(true, rowSpan.min);
 
-            int x2 = mHorizontalAxis.getLocationIncludingMargin(c, false, colSpan.max);
-            int y2 = mVerticalAxis.getLocationIncludingMargin(c, false, rowSpan.max);
+            int x2 = mHorizontalAxis.getLocationIncludingMargin(false, colSpan.max);
+            int y2 = mVerticalAxis.getLocationIncludingMargin(false, rowSpan.max);
 
             int cellWidth = x2 - x1;
             int cellHeight = y2 - y1;
 
-            int pWidth = getMeasurement(c, true, PRF);
-            int pHeight = getMeasurement(c, false, PRF);
+            int pWidth = getMeasurement(c, true);
+            int pHeight = getMeasurement(c, false);
 
             Alignment hAlign = columnGroup.alignment;
             Alignment vAlign = rowGroup.alignment;
@@ -910,9 +899,8 @@
             Bounds rowBounds = mVerticalAxis.getGroupBounds().getValue(i);
 
             // Gravity offsets: the location of the alignment group relative to its cell group.
-            int type = PRF;
-            int c2ax = protect(hAlign.getAlignmentValue(null, cellWidth - colBounds.size(), type));
-            int c2ay = protect(vAlign.getAlignmentValue(null, cellHeight - rowBounds.size(), type));
+            int c2ax = protect(hAlign.getAlignmentValue(null, cellWidth - colBounds.size(true)));
+            int c2ay = protect(vAlign.getAlignmentValue(null, cellHeight - rowBounds.size(true)));
 
             if (mAlignmentMode == ALIGN_MARGINS) {
                 int leftMargin = getMargin(c, true, true);
@@ -925,8 +913,8 @@
                 int mHeight = topMargin + pHeight + bottomMargin;
 
                 // Alignment offsets: the location of the view relative to its alignment group.
-                int a2vx = colBounds.getOffset(c, hAlign, type, mWidth);
-                int a2vy = rowBounds.getOffset(c, vAlign, type, mHeight);
+                int a2vx = colBounds.getOffset(c, hAlign, mWidth);
+                int a2vy = rowBounds.getOffset(c, vAlign, mHeight);
 
                 dx = c2ax + a2vx + leftMargin;
                 dy = c2ay + a2vy + topMargin;
@@ -935,13 +923,14 @@
                 cellHeight -= topMargin + bottomMargin;
             } else {
                 // Alignment offsets: the location of the view relative to its alignment group.
-                int a2vx = colBounds.getOffset(c, hAlign, type, pWidth);
-                int a2vy = rowBounds.getOffset(c, vAlign, type, pHeight);
+                int a2vx = colBounds.getOffset(c, hAlign, pWidth);
+                int a2vy = rowBounds.getOffset(c, vAlign, pHeight);
 
                 dx = c2ax + a2vx;
                 dy = c2ay + a2vy;
             }
 
+            int type = PRF;
             int width = hAlign.getSizeInCell(c, pWidth, cellWidth, type);
             int height = vAlign.getSizeInCell(c, pHeight, cellHeight, type);
 
@@ -962,7 +951,7 @@
     private class Axis {
         private static final int MIN_VALUE = -1000000;
 
-        private static final int UNVISITED = 0;
+        private static final int NEW = 0;
         private static final int PENDING = 1;
         private static final int COMPLETE = 2;
 
@@ -975,8 +964,11 @@
         PackedMap<Group, Bounds> groupBounds;
         public boolean groupBoundsValid = false;
 
-        PackedMap<Interval, MutableInt> spanSizes;
-        public boolean spanSizesValid = false;
+        PackedMap<Interval, MutableInt> forwardLinks;
+        public boolean forwardLinksValid = false;
+
+        PackedMap<Interval, MutableInt> backwardLinks;
+        public boolean backwardLinksValid = false;
 
         public int[] leadingMargins;
         public boolean leadingMarginsValid = false;
@@ -987,14 +979,14 @@
         public Arc[] arcs;
         public boolean arcsValid = false;
 
-        public int[] minima;
-        public boolean minimaValid = false;
-
-        public float[] weights;
         public int[] locations;
+        public boolean locationsValid = false;
 
         private boolean mOrderPreserved = DEFAULT_ORDER_PRESERVED;
 
+        private MutableInt parentMin = new MutableInt(0);
+        private MutableInt parentMax = new MutableInt(-MAX_SIZE);
+
         private Axis(boolean horizontal) {
             this.horizontal = horizontal;
         }
@@ -1036,22 +1028,19 @@
         }
 
         private PackedMap<Group, Bounds> createGroupBounds() {
-            int N = getChildCount();
-            Group[] groups = new Group[N];
-            Arrays.fill(groups, Group.GONE);
-            Bounds[] bounds = new Bounds[N];
-            Arrays.fill(bounds, Bounds.GONE);
-            for (int i = 0; i < N; i++) {
+            Assoc<Group, Bounds> assoc = Assoc.of(Group.class, Bounds.class);
+            for (int i = 0, N = getChildCount(); i < N; i++) {
                 View c = getChildAt(i);
-                if (isGone(c)) continue;
-                LayoutParams lp = getLayoutParams(c);
-                Group group = horizontal ? lp.columnGroup : lp.rowGroup;
-
-                groups[i] = group;
-                bounds[i] = group.alignment.getBounds();
+                if (isGone(c)) {
+                    assoc.put(Group.GONE, Bounds.GONE);
+                } else {
+                    LayoutParams lp = getLayoutParams(c);
+                    Group group = horizontal ? lp.columnGroup : lp.rowGroup;
+                    Bounds bounds = group.alignment.getBounds();
+                    assoc.put(group, bounds);
+                }
             }
-
-            return new PackedMap<Group, Bounds>(groups, bounds);
+            return assoc.pack();
         }
 
         private void computeGroupBounds() {
@@ -1064,13 +1053,7 @@
                 if (isGone(c)) continue;
                 LayoutParams lp = getLayoutParams(c);
                 Group g = horizontal ? lp.columnGroup : lp.rowGroup;
-
-                Bounds bounds = groupBounds.getValue(i);
-
-                int size = getMeasurementIncludingMargin(c, horizontal, PRF);
-                // todo test this works correctly when the returned value is UNDEFINED
-                int before = g.alignment.getAlignmentValue(c, size, PRF);
-                bounds.include(before, size - before);
+                groupBounds.getValue(i).include(c, g, GridLayout.this, this);
             }
         }
 
@@ -1086,75 +1069,90 @@
         }
 
         // Add values computed by alignment - taking the max of all alignments in each span
-        private PackedMap<Interval, MutableInt> createSpanSizes() {
-            PackedMap<Group, Bounds> groupBounds = getGroupBounds();
-            int N = groupBounds.keys.length;
-            Interval[] spans = new Interval[N];
-            MutableInt[] values = new MutableInt[N];
-            for (int i = 0; i < N; i++) {
-                Interval key = groupBounds.keys[i].span;
-
-                spans[i] = key;
-                values[i] = new MutableInt();
+        private PackedMap<Interval, MutableInt> createLinks(boolean min) {
+            Assoc<Interval, MutableInt> result = Assoc.of(Interval.class, MutableInt.class);
+            Group[] keys = getGroupBounds().keys;
+            for (int i = 0, N = keys.length; i < N; i++) {
+                Interval span = min ? keys[i].span : keys[i].span.inverse();
+                result.put(span, new MutableInt());
             }
-            return new PackedMap<Interval, MutableInt>(spans, values);
+            return result.pack();
         }
 
-        private void computeSpanSizes() {
-            MutableInt[] spans = spanSizes.values;
+        private void computeLinks(PackedMap<Interval, MutableInt> links, boolean min) {
+            MutableInt[] spans = links.values;
             for (int i = 0; i < spans.length; i++) {
                 spans[i].reset();
             }
 
-            Bounds[] bounds = getGroupBounds().values;  // use getter to trigger a re-evaluation
+            // Use getter to trigger a re-evaluation
+            Bounds[] bounds = getGroupBounds().values;
             for (int i = 0; i < bounds.length; i++) {
-                int value = bounds[i].size();
-
-                MutableInt valueHolder = spanSizes.getValue(i);
-                valueHolder.value = max(valueHolder.value, value);
+                int size = bounds[i].size(min);
+                MutableInt valueHolder = links.getValue(i);
+                if (min) {
+                    valueHolder.value = max(valueHolder.value, size);
+                }
+                else {
+                    valueHolder.value = -max(-valueHolder.value, size);
+                }
             }
         }
 
-        private PackedMap<Interval, MutableInt> getSpanSizes() {
-            if (spanSizes == null) {
-                spanSizes = createSpanSizes();
+        private PackedMap<Interval, MutableInt> getForwardLinks() {
+            if (forwardLinks == null) {
+                forwardLinks = createLinks(true);
             }
-            if (!spanSizesValid) {
-                computeSpanSizes();
-                spanSizesValid = true;
+            if (!forwardLinksValid) {
+                computeLinks(forwardLinks, true);
+                forwardLinksValid = true;
             }
-            return spanSizes;
+            return forwardLinks;
         }
 
-        private void include(List<Arc> arcs, Interval key, MutableInt size) {
+        private PackedMap<Interval, MutableInt> getBackwardLinks() {
+            if (backwardLinks == null) {
+                backwardLinks = createLinks(false);
+            }
+            if (!backwardLinksValid) {
+                computeLinks(backwardLinks, false);
+                backwardLinksValid = true;
+            }
+            return backwardLinks;
+        }
+
+        private void include(List<Arc> arcs, Interval key, MutableInt size,
+                boolean ignoreIfAlreadyPresent) {
+            /*
+            Remove self referential links.
+            These appear:
+                . as parental constraints when GridLayout has no children
+                . when components have been marked as GONE
+            */
+            if (key.size() == 0) {
+                return;
+            }
             // this bit below should really be computed outside here -
-            // its just to stop default (col>0) constraints obliterating valid entries
-            for (Arc arc : arcs) {
-                Interval span = arc.span;
-                if (span.equals(key)) {
-                    return;
+            // its just to stop default (row/col > 0) constraints obliterating valid entries
+            if (ignoreIfAlreadyPresent) {
+                for (Arc arc : arcs) {
+                    Interval span = arc.span;
+                    if (span.equals(key)) {
+                        return;
+                    }
                 }
             }
             arcs.add(new Arc(key, size));
         }
 
-        private void include2(List<Arc> arcs, Interval span, MutableInt min, MutableInt max,
-                boolean both) {
-            include(arcs, span, min);
-            if (both) {
-                // todo
-//                include(arcs, span.inverse(), max.neg());
-            }
-        }
-
-        private void include2(List<Arc> arcs, Interval span, int min, int max, boolean both) {
-            include2(arcs, span, new MutableInt(min), new MutableInt(max), both);
+        private void include(List<Arc> arcs, Interval key, MutableInt size) {
+            include(arcs, key, size, true);
         }
 
         // Group arcs by their first vertex, returning an array of arrays.
         // This is linear in the number of arcs.
         private Arc[][] groupArcsByFirstVertex(Arc[] arcs) {
-            int N = getCount() + 1;// the number of vertices
+            int N = getCount() + 1; // the number of vertices
             Arc[][] result = new Arc[N][];
             int[] sizes = new int[N];
             for (Arc arc : arcs) {
@@ -1173,38 +1171,46 @@
             return result;
         }
 
-        private Arc[] topologicalSort(final Arc[] arcs, int start) {
-            // todo ensure the <start> vertex is added in edge cases
-            final List<Arc> result = new ArrayList<Arc>();
-            new Object() {
-                Arc[][] arcsByFirstVertex = groupArcsByFirstVertex(arcs);
+        private Arc[] topologicalSort(final Arc[] arcs) {
+            return new Object() {
+                Arc[] result = new Arc[arcs.length];
+                int cursor = result.length - 1;
+                Arc[][] arcsByVertex = groupArcsByFirstVertex(arcs);
                 int[] visited = new int[getCount() + 1];
 
-                boolean completesCycle(int loc) {
-                    int state = visited[loc];
-                    if (state == UNVISITED) {
-                        visited[loc] = PENDING;
-                        for (Arc arc : arcsByFirstVertex[loc]) {
-                            Interval span = arc.span;
-                            // the recursive call
-                            if (completesCycle(span.max)) {
-                                // which arcs get set here is dependent on the order
-                                // in which we explore nodes
-                                arc.completesCycle = true;
+                void walk(int loc) {
+                    switch (visited[loc]) {
+                        case NEW: {
+                            visited[loc] = PENDING;
+                            for (Arc arc : arcsByVertex[loc]) {
+                                walk(arc.span.max);
+                                result[cursor--] = arc;
                             }
-                            result.add(arc);
+                            visited[loc] = COMPLETE;
+                            break;
                         }
-                        visited[loc] = COMPLETE;
-                    } else if (state == PENDING) {
-                        return true;
-                    } else if (state == COMPLETE) {
+                        case PENDING: {
+                            assert false;
+                            break;
+                        }
+                        case COMPLETE: {
+                            break;
+                        }
                     }
-                    return false;
                 }
-            }.completesCycle(start);
-            Collections.reverse(result);
-            assert arcs.length == result.size();
-            return result.toArray(new Arc[result.size()]);
+
+                Arc[] sort() {
+                    for (int loc = 0, N = arcsByVertex.length; loc < N; loc++) {
+                        walk(loc);
+                    }
+                    assert cursor == -1;
+                    return result;
+                }
+            }.sort();
+        }
+
+        private Arc[] topologicalSort(List<Arc> arcs) {
+            return topologicalSort(arcs.toArray(new Arc[arcs.size()]));
         }
 
         private boolean[] findUsed(Collection<Arc> arcs) {
@@ -1254,43 +1260,64 @@
             return result;
         }
 
-        private Arc[] createArcs() {
-            List<Arc> result = new ArrayList<Arc>();
-
-            // Add all the preferred elements that were not defined by the user.
-            PackedMap<Interval, MutableInt> spanSizes = getSpanSizes();
-            for (int i = 0; i < spanSizes.keys.length; i++) {
-                Interval key = spanSizes.keys[i];
-                if (key == Interval.GONE) continue;
-                MutableInt value = spanSizes.values[i];
-                // todo remove value duplicate
-                include2(result, key, value, value, accommodateBothMinAndMax);
+        private void addComponentSizes(List<Arc> result, PackedMap<Interval, MutableInt> links) {
+            for (int i = 0; i < links.keys.length; i++) {
+                Interval key = links.keys[i];
+                include(result, key, links.values[i], false);
             }
+        }
+
+        private Arc[] createArcs() {
+            List<Arc> mins = new ArrayList<Arc>();
+            List<Arc> maxs = new ArrayList<Arc>();
+
+            // Add the minimum values from the components.
+            addComponentSizes(mins, getForwardLinks());
+            // Add the maximum values from the components.
+            addComponentSizes(maxs, getBackwardLinks());
 
             // Find redundant rows/cols and glue them together with 0-length arcs to link the tree
-            boolean[] used = findUsed(result);
+            boolean[] used = findUsed(mins);
             for (int i = 0; i < getCount(); i++) {
                 if (!used[i]) {
                     Interval span = new Interval(i, i + 1);
-                    include(result, span, new MutableInt(0));
-                    include(result, span.inverse(), new MutableInt(0));
+                    include(mins, span, new MutableInt(0));
+                    include(maxs, span.inverse(), new MutableInt(0));
                 }
             }
 
+            // Add ordering constraints to prevent row/col sizes from going negative
             if (mOrderPreserved) {
-                // Add preferred gaps
+                // Add a constraint for every row/col
                 for (int i = 0; i < getCount(); i++) {
                     if (used[i]) {
-                        include2(result, new Interval(i, i + 1), 0, 0, false);
+                        include(mins, new Interval(i, i + 1), new MutableInt(0));
                     }
                 }
             } else {
+                // Add a constraint for each row/col that separates opposing component edges
                 for (Interval gap : getSpacers()) {
-                    include2(result, gap, 0, 0, false);
+                    include(mins, gap, new MutableInt(0));
                 }
             }
-            Arc[] arcs = result.toArray(new Arc[result.size()]);
-            return topologicalSort(arcs, 0);
+
+            // Add the container constraints. Use the version of include that allows
+            // duplicate entries in case a child spans the entire grid.
+            int N = getCount();
+            include(mins, new Interval(0, N), parentMin, false);
+            include(maxs, new Interval(N, 0), parentMax, false);
+
+            // Sort
+            Arc[] sMins = topologicalSort(mins);
+            Arc[] sMaxs = topologicalSort(maxs);
+
+            return append(sMins, sMaxs);
+        }
+
+        private void computeArcs() {
+            // getting the links validates the values that are shared by the arc list
+            getForwardLinks();
+            getBackwardLinks();
         }
 
         public Arc[] getArcs() {
@@ -1298,13 +1325,16 @@
                 arcs = createArcs();
             }
             if (!arcsValid) {
-                getSpanSizes();
+                computeArcs();
                 arcsValid = true;
             }
             return arcs;
         }
 
         private boolean relax(int[] locations, Arc entry) {
+            if (!entry.valid) {
+                return false;
+            }
             Interval span = entry.span;
             int u = span.min;
             int v = span.max;
@@ -1351,7 +1381,8 @@
         typical layout problems complete after the first iteration and the algorithm
         completes in O(N) steps with very low constants.
         */
-        private int[] solve(Arc[] arcs, int[] locations) {
+        private void solve(Arc[] arcs, int[] locations) {
+            String axis = horizontal ? "horizontal" : "vertical";
             int N = getCount() + 1; // The number of vertices is the number of columns/rows + 1.
 
             boolean changed = false;
@@ -1359,20 +1390,44 @@
             for (int i = 0; i < N; i++) {
                 changed = false;
                 for (int j = 0, length = arcs.length; j < length; j++) {
-                    changed = changed | relax(locations, arcs[j]);
+                    changed |= relax(locations, arcs[j]);
                 }
                 if (!changed) {
                     if (DEBUG) {
-                        Log.d(TAG, "Iteration " +
-                                " completed after " + (1 + i) + " steps out of " + N);
+                        Log.d(TAG, axis + " iteration completed in " + (1 + i) + " steps of " + N);
                     }
+                    return;
+                }
+            }
+
+            Log.d(TAG, "The " + axis + " constraints contained a contradiction. Resolving... ");
+            Log.d(TAG, Arrays.toString(arcs));
+
+            boolean[] culprits = new boolean[arcs.length];
+            for (int i = 0; i < N; i++) {
+                for (int j = 0, length = arcs.length; j < length; j++) {
+                    culprits[j] |= relax(locations, arcs[j]);
+                }
+            }
+            for (int i = 0; i < culprits.length; i++) {
+                if (culprits[i]) {
+                    Arc arc = arcs[i];
+                    // Only remove max values, min values alone cannot be inconsistent
+                    if (arc.span.min < arc.span.max) {
+                        continue;
+                    }
+                    Log.d(TAG, "Removing: " + arc);
+                    arc.valid = false;
                     break;
                 }
             }
-            if (changed) {
-                Log.d(TAG, "*** Algorithm failed to terminate ***");
-            }
-            return locations;
+            solve1(arcs, locations);
+        }
+
+        private void solve1(Arc[] arcs, int[] a) {
+            Arrays.fill(a, MIN_VALUE);
+            a[0] = 0;
+            solve(arcs, a);
         }
 
         private void computeMargins(boolean leading) {
@@ -1418,11 +1473,11 @@
             for (int i = 0, N = getCount(); i < N; i++) {
                 int margins = leadingMargins[i] + trailingMargins[i + 1];
                 delta += margins;
-                minima[i + 1] += delta;
+                locations[i + 1] += delta;
             }
         }
 
-        private int getLocationIncludingMargin(View view, boolean leading, int index) {
+        private int getLocationIncludingMargin(boolean leading, int index) {
             int location = locations[index];
             int margin;
             if (mAlignmentMode != ALIGN_MARGINS) {
@@ -1433,53 +1488,22 @@
             return leading ? (location + margin) : (location - margin);
         }
 
-        private void computeMinima(int[] a) {
-            Arrays.fill(a, MIN_VALUE);
-            a[0] = 0;
-            solve(getArcs(), a);
+        private void computeLocations(int[] a) {
+            solve1(getArcs(), a);
             if (mAlignmentMode != ALIGN_MARGINS) {
                 addMargins();
             }
         }
 
-        private int[] getMinima() {
-            if (minima == null) {
-                int N = getCount() + 1;
-                minima = new int[N];
-            }
-            if (!minimaValid) {
-                computeMinima(minima);
-                minimaValid = true;
-            }
-            return minima;
-        }
-
-        private void computeWeights() {
-            for (int i = 0, N = getChildCount(); i < N; i++) {
-                View c = getChildAt(i);
-                if (isGone(c)) continue;
-                LayoutParams lp = getLayoutParams(c);
-                Group g = horizontal ? lp.columnGroup : lp.rowGroup;
-                Interval span = g.span;
-                int penultimateIndex = span.max - 1;
-                weights[penultimateIndex] += horizontal ? lp.columnWeight : lp.rowWeight;
-            }
-        }
-
-        private float[] getWeights() {
-            if (weights == null) {
-                int N = getCount();
-                weights = new float[N];
-            }
-            computeWeights();
-            return weights;
-        }
-
         private int[] getLocations() {
             if (locations == null) {
                 int N = getCount() + 1;
                 locations = new int[N];
             }
+            if (!locationsValid) {
+                computeLocations(locations);
+                locationsValid = true;
+            }
             return locations;
         }
 
@@ -1489,48 +1513,53 @@
             return max2(locations, 0) - locations[0];
         }
 
-        private int getMin() {
-            return size(getMinima());
+        private void setParentConstraints(int min, int max) {
+            parentMin.value = min;
+            parentMax.value = -max;
+            locationsValid = false;
         }
 
-        private void layout(int targetSize) {
-            int[] mins = getMinima();
+        private int getMeasure(int min, int max) {
+            setParentConstraints(min, max);
+            return size(getLocations());
+        }
 
-            int totalDelta = max(0, targetSize - size(mins)); // confine to expansion
-
-            float[] weights = getWeights();
-            float totalWeight = sum(weights);
-
-            if (totalWeight == 0f && weights.length > 0) {
-                weights[weights.length - 1] = 1;
-                totalWeight = 1;
+        private int getMeasure(int measureSpec) {
+            int mode = MeasureSpec.getMode(measureSpec);
+            int size = MeasureSpec.getSize(measureSpec);
+            switch (mode) {
+                case MeasureSpec.UNSPECIFIED: {
+                     return getMeasure(0, MAX_SIZE);
+                }
+                case MeasureSpec.EXACTLY: {
+                    return getMeasure(size, size);
+                }
+                case MeasureSpec.AT_MOST: {
+                    return getMeasure(0, size);
+                }
+                default: {
+                    assert false;
+                    return 0;
+                }
             }
+        }
 
-            int[] locations = getLocations();
-            int cumulativeDelta = 0;
-
-            // note |weights| = |locations| - 1
-            for (int i = 0; i < weights.length; i++) {
-                float weight = weights[i];
-                int delta = (int) (totalDelta * weight / totalWeight);
-                cumulativeDelta += delta;
-                locations[i + 1] = mins[i + 1] + cumulativeDelta;
-
-                totalDelta -= delta;
-                totalWeight -= weight;
-            }
+        private void layout(int size) {
+            setParentConstraints(size, size);
+            getLocations();
         }
 
         private void invalidateStructure() {
             countValid = false;
 
             groupBounds = null;
-            spanSizes = null;
+            forwardLinks = null;
+            backwardLinks = null;
+
             leadingMargins = null;
             trailingMargins = null;
             arcs = null;
-            minima = null;
-            weights = null;
+
             locations = null;
 
             invalidateValues();
@@ -1538,11 +1567,14 @@
 
         private void invalidateValues() {
             groupBoundsValid = false;
-            spanSizesValid = false;
-            arcsValid = false;
+            forwardLinksValid = false;
+            backwardLinksValid = false;
+
             leadingMarginsValid = false;
             trailingMarginsValid = false;
-            minimaValid = false;
+            arcsValid = false;
+
+            locationsValid = false;
         }
     }
 
@@ -1592,16 +1624,14 @@
      *     <li>{@link #rowGroup}{@code .alignment} = {@link #BASELINE} </li>
      *     <li>{@link #columnGroup}{@code .span} = {@code [0, 1]} </li>
      *     <li>{@link #columnGroup}{@code .alignment} = {@link #LEFT} </li>
-     *     <li>{@link #rowWeight} = {@code 0f} </li>
-     *     <li>{@link #columnWeight} = {@code 0f} </li>
      * </ul>
      *
      * @attr ref android.R.styleable#GridLayout_Layout_layout_row
      * @attr ref android.R.styleable#GridLayout_Layout_layout_rowSpan
-     * @attr ref android.R.styleable#GridLayout_Layout_layout_rowWeight
+     * @attr ref android.R.styleable#GridLayout_Layout_layout_rowFlexibility
      * @attr ref android.R.styleable#GridLayout_Layout_layout_column
      * @attr ref android.R.styleable#GridLayout_Layout_layout_columnSpan
-     * @attr ref android.R.styleable#GridLayout_Layout_layout_columnWeight
+     * @attr ref android.R.styleable#GridLayout_Layout_layout_columnFlexibility
      * @attr ref android.R.styleable#GridLayout_Layout_layout_gravity
      */
     public static class LayoutParams extends MarginLayoutParams {
@@ -1617,12 +1647,6 @@
         private static final int DEFAULT_SPAN_SIZE = DEFAULT_SPAN.size();
         private static final Alignment DEFAULT_COLUMN_ALIGNMENT = LEFT;
         private static final Alignment DEFAULT_ROW_ALIGNMENT = BASELINE;
-        private static final Group DEFAULT_COLUMN_GROUP =
-                new Group(DEFAULT_SPAN, DEFAULT_COLUMN_ALIGNMENT);
-        private static final Group DEFAULT_ROW_GROUP =
-                new Group(DEFAULT_SPAN, DEFAULT_ROW_ALIGNMENT);
-        private static final int DEFAULT_WEIGHT_0 = 0;
-        private static final int DEFAULT_WEIGHT_1 = 1;
 
         // Misc
 
@@ -1641,10 +1665,14 @@
 
         private static final int COLUMN = styleable.GridLayout_Layout_layout_column;
         private static final int COLUMN_SPAN = styleable.GridLayout_Layout_layout_columnSpan;
-        private static final int COLUMN_WEIGHT = styleable.GridLayout_Layout_layout_columnWeight;
+        private static final int COLUMN_FLEXIBILITY =
+                styleable.GridLayout_Layout_layout_columnFlexibility;
+
         private static final int ROW = styleable.GridLayout_Layout_layout_row;
         private static final int ROW_SPAN = styleable.GridLayout_Layout_layout_rowSpan;
-        private static final int ROW_WEIGHT = styleable.GridLayout_Layout_layout_rowWeight;
+        private static final int ROW_FLEXIBILITY =
+                styleable.GridLayout_Layout_layout_rowFlexibility;
+
         private static final int GRAVITY = styleable.GridLayout_Layout_layout_gravity;
 
         // Instance variables
@@ -1659,29 +1687,17 @@
          * described by these layout parameters.
          */
         public Group columnGroup;
-        /**
-         * The proportional space that should be taken by the associated row group
-         * during excess space distribution.
-         */
-        public float rowWeight;
-        /**
-         * The proportional space that should be taken by the associated column group
-         * during excess space distribution.
-         */
-        public float columnWeight;
 
         // Constructors
 
         private LayoutParams(
                 int width, int height,
                 int left, int top, int right, int bottom,
-                Group rowGroup, Group columnGroup, float rowWeight, float columnWeight) {
+                Group rowGroup, Group columnGroup) {
             super(width, height);
             setMargins(left, top, right, bottom);
             this.rowGroup = rowGroup;
             this.columnGroup = columnGroup;
-            this.rowWeight = rowWeight;
-            this.columnWeight = columnWeight;
         }
 
         /**
@@ -1695,14 +1711,15 @@
         public LayoutParams(Group rowGroup, Group columnGroup) {
             this(DEFAULT_WIDTH, DEFAULT_HEIGHT,
                     DEFAULT_MARGIN, DEFAULT_MARGIN, DEFAULT_MARGIN, DEFAULT_MARGIN,
-                    rowGroup, columnGroup, DEFAULT_WEIGHT_0, DEFAULT_WEIGHT_0);
+                    rowGroup, columnGroup);
         }
 
         /**
          * Constructs a new LayoutParams with default values as defined in {@link LayoutParams}.
          */
         public LayoutParams() {
-            this(DEFAULT_ROW_GROUP, DEFAULT_COLUMN_GROUP);
+            this(new Group(DEFAULT_SPAN, DEFAULT_ROW_ALIGNMENT),
+                 new Group(DEFAULT_SPAN, DEFAULT_COLUMN_ALIGNMENT));
         }
 
         // Copying constructors
@@ -1726,10 +1743,8 @@
          */
         public LayoutParams(LayoutParams that) {
             super(that);
-            this.columnGroup = that.columnGroup;
-            this.rowGroup = that.rowGroup;
-            this.columnWeight = that.columnWeight;
-            this.rowWeight = that.rowWeight;
+            this.columnGroup = new Group(that.columnGroup);
+            this.rowGroup = new Group(that.rowGroup);
         }
 
         // AttributeSet constructors
@@ -1793,7 +1808,7 @@
 
         // Gravity. For conversion from the static the integers defined in the Gravity class,
         // use Gravity.apply() to apply gravity to a view of zero size and see where it ends up.
-        private static Alignment getColumnAlignment(int gravity, int width) {
+        private static Alignment getColAlignment(int gravity, int width) {
             Rect r = new Rect(0, 0, 0, 0);
             Gravity.apply(gravity, 0, 0, CONTAINER_BOUNDS, r);
 
@@ -1813,11 +1828,6 @@
                     !definesVertical(gravity), defaultAlignment);
         }
 
-        private int getDefaultWeight(int size) {
-            //return (size == MATCH_PARENT) ? DEFAULT_WEIGHT_1 : DEFAULT_WEIGHT_0;
-            return DEFAULT_WEIGHT_0;
-        }
-
         private void init(Context context, AttributeSet attrs, int defaultGravity) {
             TypedArray a = context.obtainStyledAttributes(attrs, styleable.GridLayout_Layout);
             try {
@@ -1826,14 +1836,14 @@
                 int column = a.getInt(COLUMN, DEFAULT_COLUMN);
                 int columnSpan = a.getInt(COLUMN_SPAN, DEFAULT_SPAN_SIZE);
                 Interval hSpan = new Interval(column, column + columnSpan);
-                this.columnGroup = new Group(hSpan, getColumnAlignment(gravity, width));
-                this.columnWeight = a.getFloat(COLUMN_WEIGHT, getDefaultWeight(width));
+                int hFlexibility = a.getInt(COLUMN_FLEXIBILITY, Group.DEFAULT_FLEXIBILITY);
+                this.columnGroup = new Group(hSpan, getColAlignment(gravity, width), hFlexibility);
 
                 int row = a.getInt(ROW, DEFAULT_ROW);
                 int rowSpan = a.getInt(ROW_SPAN, DEFAULT_SPAN_SIZE);
                 Interval vSpan = new Interval(row, row + rowSpan);
-                this.rowGroup = new Group(vSpan, getRowAlignment(gravity, height));
-                this.rowWeight = a.getFloat(ROW_WEIGHT, getDefaultWeight(height));
+                int vFlexibility = a.getInt(ROW_FLEXIBILITY, Group.DEFAULT_FLEXIBILITY);
+                this.rowGroup = new Group(vSpan, getRowAlignment(gravity, height), vFlexibility);
             } finally {
                 a.recycle();
             }
@@ -1848,7 +1858,7 @@
          * @attr ref android.R.styleable#GridLayout_Layout_layout_gravity
          */
         public void setGravity(int gravity) {
-            columnGroup = columnGroup.copyWriteAlignment(getColumnAlignment(gravity, width));
+            columnGroup = columnGroup.copyWriteAlignment(getColAlignment(gravity, width));
             rowGroup = rowGroup.copyWriteAlignment(getRowAlignment(gravity, height));
         }
 
@@ -1874,7 +1884,7 @@
     private static class Arc {
         public final Interval span;
         public final MutableInt value;
-        public boolean completesCycle;
+        public boolean valid = true;
 
         public Arc(Interval span, MutableInt value) {
             this.span = span;
@@ -1883,7 +1893,7 @@
 
         @Override
         public String toString() {
-            return span + " " + (completesCycle ? "+>" : "->") + " " + value;
+            return span + " " + (!valid ? "+>" : "->") + " " + value;
         }
     }
 
@@ -1903,6 +1913,41 @@
         private void reset() {
             value = Integer.MIN_VALUE;
         }
+
+        @Override
+        public String toString() {
+            return Integer.toString(value);
+        }
+    }
+
+    private static class Assoc<K, V> extends ArrayList<Pair<K, V>> {
+        private final Class<K> keyType;
+        private final Class<V> valueType;
+
+        private Assoc(Class<K> keyType, Class<V> valueType) {
+            this.keyType = keyType;
+            this.valueType = valueType;
+        }
+
+        private static <K, V> Assoc<K, V> of(Class<K> keyType, Class<V> valueType) {
+            return new Assoc<K, V>(keyType, valueType);
+        }
+
+        public void put(K key, V value) {
+            add(Pair.create(key, value));
+        }
+
+        @SuppressWarnings(value = "unchecked")
+        public PackedMap<K, V> pack() {
+            int N = size();
+            K[] keys = (K[]) Array.newInstance(keyType, N);
+            V[] values = (V[]) Array.newInstance(valueType, N);
+            for (int i = 0; i < N; i++) {
+                keys[i] = get(i).first;
+                values[i] = get(i).second;
+            }
+            return new PackedMap<K, V>(keys, values);
+        }
     }
 
     /*
@@ -1989,6 +2034,7 @@
 
         public int before;
         public int after;
+        public int flexibility;
 
         private Bounds() {
             reset();
@@ -1997,6 +2043,7 @@
         protected void reset() {
             before = Integer.MIN_VALUE;
             after = Integer.MIN_VALUE;
+            flexibility = UNDEFINED_FLEXIBILITY;
         }
 
         protected void include(int before, int after) {
@@ -2004,12 +2051,28 @@
             this.after = max(this.after, after);
         }
 
-        protected int size() {
+        protected int size(boolean min) {
+            if (!min) {
+                // Note in the usual case, components don't define anything
+                // leaving their flexibility is undefined and their stretchability
+                // defined as if the CAN_STRETCH flag was false.
+                if (canStretch(flexibility) && !isUndefined(flexibility)) {
+                    return MAX_SIZE;
+                }
+            }
             return before + after;
         }
 
-        protected int getOffset(View c, Alignment alignment, int type, int size) {
-            return before - alignment.getAlignmentValue(c, size, type);
+        protected int getOffset(View c, Alignment alignment, int size) {
+            return before - alignment.getAlignmentValue(c, size);
+        }
+
+        protected void include(View c, Group group, GridLayout gridLayout, Axis axis) {
+            this.flexibility &= group.flexibility;
+            int size = gridLayout.getMeasurementIncludingMargin(c, axis.horizontal);
+            // todo test this works correctly when the returned value is UNDEFINED
+            int before = group.alignment.getAlignmentValue(c, size);
+            include(before, size - before);
         }
 
         @Override
@@ -2032,7 +2095,7 @@
      * Intervals are often written as {@code [min, max]} and represent the set of values
      * {@code x} such that {@code min <= x < max}.
      */
-    /* package */ static class Interval {
+    static class Interval {
         private static final Interval GONE = new Interval(UNDEFINED, UNDEFINED);
 
         /**
@@ -2120,6 +2183,8 @@
      * {@code span} and {@code alignment}.
      */
     public static class Group {
+        private static final int DEFAULT_FLEXIBILITY = UNDEFINED_FLEXIBILITY;
+
         private static final Group GONE = new Group(Interval.GONE, Alignment.GONE);
 
         /**
@@ -2129,7 +2194,7 @@
          * See {@link GridLayout} for a description of the conventions used by GridLayout
          * for grid indices.
          */
-        /* package */ final Interval span;
+        final Interval span;
         /**
          * Specifies how cells should be aligned in this group.
          * For row groups, this specifies the vertical alignment.
@@ -2138,6 +2203,18 @@
         public final Alignment alignment;
 
         /**
+         * The flexibility field tells GridLayout how to derive minimum and maximum size
+         * values for a component. Specifications are made with respect to a child's
+         * 'measured size'. A child's measured size is, in turn, controlled by its
+         * height and width layout parameters which either specify a size or, in
+         * the case of {@link LayoutParams#WRAP_CONTENT WRAP_CONTENT}, defer to
+         * the computed size of the component.
+         *
+         * @see GridLayout#CAN_STRETCH
+         */
+         public int flexibility = DEFAULT_FLEXIBILITY;
+
+        /**
          * Construct a new Group, {@code group}, where:
          * <ul>
          *     <li> {@code group.span = span} </li>
@@ -2147,11 +2224,24 @@
          * @param span      the span
          * @param alignment the alignment
          */
-        /* package */ Group(Interval span, Alignment alignment) {
+        private Group(Interval span, Alignment alignment) {
             this.span = span;
             this.alignment = alignment;
         }
 
+        private Group(Interval span, Alignment alignment, int flexibility) {
+            this.span = span;
+            this.alignment = alignment;
+            this.flexibility = flexibility;
+        }
+
+        /* Copying constructor */
+        private Group(Group that) {
+            this.span = that.span;
+            this.alignment = that.alignment;
+            this.flexibility = that.flexibility;
+        }
+
         /**
          * Construct a new Group, {@code group}, where:
          * <ul>
@@ -2182,11 +2272,11 @@
         }
 
         private Group copyWriteSpan(Interval span) {
-            return new Group(span, alignment);
+            return new Group(span, alignment, flexibility);
         }
 
         private Group copyWriteAlignment(Alignment alignment) {
-            return new Group(span, alignment);
+            return new Group(span, alignment, flexibility);
         }
 
         /**
@@ -2248,17 +2338,16 @@
      * so that the locations defined by the alignment values
      * are the same for all of the views in a group.
      * <p>
-
      */
     public static abstract class Alignment {
         private static final Alignment GONE = new Alignment() {
-            public int getAlignmentValue(View view, int viewSize, int measurementType) {
+            public int getAlignmentValue(View view, int viewSize) {
                 assert false;
                 return 0;
             }
         };
 
-        /*pp*/ Alignment() {
+        Alignment() {
         }
 
         /**
@@ -2269,12 +2358,9 @@
          *
          * @param view              the view to which this alignment should be applied
          * @param viewSize          the measured size of the view
-         * @param measurementType   This parameter is currently unused as GridLayout only supports
-         *                          one type of measurement: {@link View#measure(int, int)}.
-         *
          * @return the alignment value
          */
-        /*pp*/ abstract int getAlignmentValue(View view, int viewSize, int measurementType);
+        abstract int getAlignmentValue(View view, int viewSize);
 
         /**
          * Returns the size of the view specified by this alignment.
@@ -2291,24 +2377,24 @@
          *
          * @return the aligned size
          */
-        /*pp*/ int getSizeInCell(View view, int viewSize, int cellSize, int measurementType) {
+        int getSizeInCell(View view, int viewSize, int cellSize, int measurementType) {
             return viewSize;
         }
 
-        /*pp*/ Bounds getBounds() {
+        Bounds getBounds() {
             return new Bounds();
         }
     }
 
     private static final Alignment LEADING = new Alignment() {
-        public int getAlignmentValue(View view, int viewSize, int measurementType) {
+        public int getAlignmentValue(View view, int viewSize) {
             return 0;
         }
 
     };
 
     private static final Alignment TRAILING = new Alignment() {
-        public int getAlignmentValue(View view, int viewSize, int measurementType) {
+        public int getAlignmentValue(View view, int viewSize) {
             return viewSize;
         }
     };
@@ -2343,7 +2429,7 @@
      * LayoutParams#columnGroup columnGroups}.
      */
     public static final Alignment CENTER = new Alignment() {
-        public int getAlignmentValue(View view, int viewSize, int measurementType) {
+        public int getAlignmentValue(View view, int viewSize) {
             return viewSize >> 1;
         }
     };
@@ -2356,7 +2442,7 @@
      * @see View#getBaseline()
      */
     public static final Alignment BASELINE = new Alignment() {
-        public int getAlignmentValue(View view, int viewSize, int measurementType) {
+        public int getAlignmentValue(View view, int viewSize) {
             if (view == null) {
                 return UNDEFINED;
             }
@@ -2378,7 +2464,7 @@
                 @Override
                 protected void reset() {
                     super.reset();
-                    size = 0;
+                    size = Integer.MIN_VALUE;
                 }
 
                 @Override
@@ -2388,13 +2474,13 @@
                 }
 
                 @Override
-                protected int size() {
-                    return max(super.size(), size);
+                protected int size(boolean min) {
+                    return max(super.size(min), size);
                 }
 
                 @Override
-                protected int getOffset(View c, Alignment alignment, int type, int size) {
-                    return max(0, super.getOffset(c, alignment, type, size));
+                protected int getOffset(View c, Alignment alignment, int size) {
+                    return max(0, super.getOffset(c, alignment, size));
                 }
             };
         }
@@ -2406,7 +2492,7 @@
      * {@link LayoutParams#columnGroup columnGroups}.
      */
     public static final Alignment FILL = new Alignment() {
-        public int getAlignmentValue(View view, int viewSize, int measurementType) {
+        public int getAlignmentValue(View view, int viewSize) {
             return UNDEFINED;
         }
 
@@ -2415,4 +2501,55 @@
             return cellSize;
         }
     };
+
+    private static boolean canStretch(int flexibility) {
+        return (flexibility & CAN_STRETCH) != 0;
+    }
+
+    private static boolean isUndefined(int flexibility) {
+        return (flexibility & UNDEFINED) != 0;
+    }
+
+    /**
+     * Indicates that a view requests precisely the size specified by its layout parameters.
+     *
+     * @see Group#flexibility
+     *
+     * @hide
+     */
+    public static final int FIXED = 0;
+
+    /**
+     * Indicates that a view's size should lie between its minimum and the size specified by
+     * its layout parameters.
+     *
+     * @see Group#flexibility
+     *
+     * @hide
+     */
+    public static final int CAN_SHRINK = 1;
+
+    /**
+     * Indicates that a view's size should be greater than or equal to the size specified by
+     * its layout parameters.
+     *
+     * @see Group#flexibility
+     */
+    public static final int CAN_STRETCH = 2;
+
+    /**
+     * Indicates that a view will ignore its measurement, and can take any size that is greater
+     * than its minimum.
+     *
+     * @see Group#flexibility
+     */
+    private static final int CAN_SHRINK_OR_STRETCH = CAN_SHRINK | CAN_STRETCH;
+
+    /**
+     * A default value for flexibility.
+     *
+     * @see Group#flexibility
+     */
+    private static final int UNDEFINED_FLEXIBILITY = UNDEFINED | CAN_SHRINK | CAN_STRETCH;
+
 }
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 17b3bda..7c9be1e 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -35,6 +35,8 @@
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AnimationUtils;
 
 import java.util.List;
@@ -692,6 +694,28 @@
         awakenScrollBars();
     }
 
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setScrollable(true);
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setScrollable(true);
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        // Do not append text content to scroll events they are fired frequently
+        // and the client has already received another event type with the text.
+        if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            super.dispatchPopulateAccessibilityEvent(event);
+        }
+        return false;
+    }
+
     private int getScrollRange() {
         int scrollRange = 0;
         if (getChildCount() > 0) {
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index fc8bce8..427fd3e 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -301,49 +301,55 @@
 
     void drawDividersVertical(Canvas canvas) {
         final int count = getVirtualChildCount();
-        int top = getPaddingTop();
         for (int i = 0; i < count; i++) {
             final View child = getVirtualChildAt(i);
 
-            if (child == null) {
-                top += measureNullChild(i);
-            } else if (child.getVisibility() != GONE) {
+            if (child != null && child.getVisibility() != GONE) {
                 if (hasDividerBeforeChildAt(i)) {
+                    final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                    final int top = child.getTop() - lp.topMargin;
                     drawHorizontalDivider(canvas, top);
-                    top += mDividerHeight;
                 }
-
-                LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                top += lp.topMargin + child.getHeight() + lp.bottomMargin;
             }
         }
 
         if (hasDividerBeforeChildAt(count)) {
-            drawHorizontalDivider(canvas, top);
+            final View child = getVirtualChildAt(count - 1);
+            int bottom = 0;
+            if (child == null) {
+                bottom = getHeight() - getPaddingBottom() - mDividerHeight;
+            } else {
+                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                bottom = child.getBottom() + lp.bottomMargin;
+            }
+            drawHorizontalDivider(canvas, bottom);
         }
     }
 
     void drawDividersHorizontal(Canvas canvas) {
         final int count = getVirtualChildCount();
-        int left = getPaddingLeft();
         for (int i = 0; i < count; i++) {
             final View child = getVirtualChildAt(i);
 
-            if (child == null) {
-                left += measureNullChild(i);
-            } else if (child.getVisibility() != GONE) {
+            if (child != null && child.getVisibility() != GONE) {
                 if (hasDividerBeforeChildAt(i)) {
+                    final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                    final int left = child.getLeft() - lp.leftMargin;
                     drawVerticalDivider(canvas, left);
-                    left += mDividerWidth;
                 }
-
-                LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                left += lp.leftMargin + child.getWidth() + lp.rightMargin;
             }
         }
 
         if (hasDividerBeforeChildAt(count)) {
-            drawVerticalDivider(canvas, left);
+            final View child = getVirtualChildAt(count - 1);
+            int right = 0;
+            if (child == null) {
+                right = getWidth() - getPaddingRight() - mDividerWidth;
+            } else {
+                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                right = child.getRight() + lp.rightMargin;
+            }
+            drawVerticalDivider(canvas, right);
         }
     }
 
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 2947ebe..aa23ad0 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1201,18 +1201,15 @@
     private void initializeScrollWheel() {
         if (mInitialScrollOffset != Integer.MIN_VALUE) {
             return;
-
         }
         int[] selectorIndices = getSelectorIndices();
         int totalTextHeight = selectorIndices.length * mTextSize;
-        int totalTextGapHeight = (mBottom - mTop) - totalTextHeight;
-        int textGapCount = selectorIndices.length - 1;
-        int selectorTextGapHeight = totalTextGapHeight / textGapCount;
-        // compensate for integer division loss of the components used to
-        // calculate the text gap
-        int integerDivisionLoss = (mTextSize + mBottom - mTop) % textGapCount;
-        mInitialScrollOffset = mCurrentScrollOffset = mTextSize - integerDivisionLoss / 2;
+        float totalTextGapHeight = (mBottom - mTop) - totalTextHeight;
+        float textGapCount = selectorIndices.length - 1;
+        int selectorTextGapHeight = (int) (totalTextGapHeight / textGapCount + 0.5f);
         mSelectorElementHeight = mTextSize + selectorTextGapHeight;
+        mInitialScrollOffset = mTextSize - 3 * (mSelectorElementHeight % 2);
+        mCurrentScrollOffset = mInitialScrollOffset;
         updateInputTextView();
     }
 
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 27edb88..12775a4 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -36,6 +36,8 @@
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AnimationUtils;
 
 import java.util.List;
@@ -690,6 +692,28 @@
         awakenScrollBars();
     }
 
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setScrollable(true);
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setScrollable(true);
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        // Do not append text content to scroll events they are fired frequently
+        // and the client has already received another event type with the text.
+        if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+            super.dispatchPopulateAccessibilityEvent(event);
+        }
+        return false;
+    }
+
     private int getScrollRange() {
         int scrollRange = 0;
         if (getChildCount() > 0) {
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
new file mode 100644
index 0000000..d6e426f
--- /dev/null
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -0,0 +1,164 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.util.TypedValue;
+import android.view.ActionProvider;
+import android.view.MenuItem;
+import android.view.View;
+
+import com.android.internal.R;
+
+/**
+ * This is a provider for a share action. It is responsible for creating views
+ * that enable data sharing and also to perform a default action for showing
+ * a share dialog.
+ * <p>
+ * Here is how to use the action provider with custom backing file in a {@link MenuItem}:
+ * </p>
+ * <p>
+ * <pre>
+ * <code>
+ *  // In Activity#onCreateOptionsMenu
+ *  public boolean onCreateOptionsMenu(Menu menu) {
+ *      // Get the menu item.
+ *      MenuItem menuItem = menu.findItem(R.id.my_menu_item);
+ *      // Get the provider and hold onto it to set/change the share intent.
+ *      mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
+ *      // Set history different from the default before getting the action
+ *      // view since a call to {@link MenuItem#getActionView() MenuItem.getActionView()} calls
+ *      // {@link ActionProvider#onCreateActionView()} which uses the backing file name. Omit this
+ *      // line if using the default share history file is desired.
+ *      mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
+ *      // Get the action view and hold onto it to set the share intent.
+ *      mActionView = menuItem.getActionView();
+ *      . . .
+ *  }
+ *
+ *  // Somewhere in the application.
+ *  public void doShare(Intent shareIntent) {
+ *      // When you want to share set the share intent.
+ *      mShareActionProvider.setShareIntent(mActionView, shareIntent);
+ *  }
+ * </pre>
+ * </code>
+ * </p>
+ * <p>
+ * <strong>Note:</strong> While the sample snippet demonstrates how to use this provider
+ * in the context of a menu item, the use of the provider is not limited to menu items.
+ * </p>
+ *
+ * @see ActionProvider
+ */
+public class ShareActionProvider extends ActionProvider {
+
+    /**
+     * The default name for storing share history.
+     */
+    public static final String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
+
+    private final Context mContext;
+    private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param context Context for accessing resources.
+     */
+    public ShareActionProvider(Context context) {
+        super(context);
+        mContext = context;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public View onCreateActionView() {
+        ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
+        ActivityChooserView activityChooserView = new ActivityChooserView(mContext);
+        activityChooserView.setActivityChooserModel(dataModel);
+        TypedValue outTypedValue = new TypedValue();
+        mContext.getTheme().resolveAttribute(R.attr.actionModeShareDrawable, outTypedValue, true);
+        Drawable drawable = mContext.getResources().getDrawable(outTypedValue.resourceId);
+        activityChooserView.setExpandActivityOverflowButtonDrawable(drawable);
+        return activityChooserView;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onPerformDefaultAction(View actionView) {
+        if (actionView instanceof ActivityChooserView) {
+            ActivityChooserView activityChooserView = (ActivityChooserView) actionView;
+            activityChooserView.showPopup();
+        } else {
+            throw new IllegalArgumentException("actionView not instance of ActivityChooserView");
+        }
+    }
+
+    /**
+     * Sets the file name of a file for persisting the share history which
+     * history will be used for ordering share targets. This file will be used
+     * for all view created by {@link #onCreateActionView()}. Defaults to
+     * {@link #DEFAULT_SHARE_HISTORY_FILE_NAME}. Set to <code>null</code>
+     * if share history should not be persisted between sessions.
+     * <p>
+     * <strong>Note:</strong> The history file name can be set any time, however
+     * only the action views created by {@link #onCreateActionView()} after setting
+     * the file name will be backed by the provided file.
+     * <p>
+     *
+     * @param shareHistoryFile The share history file name.
+     */
+    public void setShareHistoryFileName(String shareHistoryFile) {
+        mShareHistoryFileName = shareHistoryFile;
+    }
+
+    /**
+     * Sets an intent with information about the share action. Here is a
+     * sample for constructing a share intent:
+     * <p>
+     * <pre>
+     * <code>
+     *  Intent shareIntent = new Intent(Intent.ACTION_SEND);
+     *  shareIntent.setType("image/*");
+     *  Uri uri = Uri.fromFile(new File(getFilesDir(), "foo.jpg"));
+     *  shareIntent.putExtra(Intent.EXTRA_STREAM, uri.toString());
+     * </pre>
+     * </code>
+     * </p>
+     *
+     * @param actionView An action view created by {@link #onCreateActionView()}.
+     * @param shareIntent The share intent.
+     *
+     * @see Intent#ACTION_SEND
+     * @see Intent#ACTION_SEND_MULTIPLE
+     */
+    public void setShareIntent(View actionView, Intent shareIntent) {
+        if (actionView instanceof ActivityChooserView) {
+            ActivityChooserView activityChooserView = (ActivityChooserView) actionView;
+            activityChooserView.getDataModel().setIntent(shareIntent);
+        } else {
+            throw new IllegalArgumentException("actionView not instance of ActivityChooserView");
+        }
+    }
+}
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index b23a855..485c678 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -231,7 +231,8 @@
         }
 
         if (child != null) {
-            return child.getTop() + child.getBaseline();
+            final int childBaseline = child.getBaseline();
+            return childBaseline >= 0 ? child.getTop() + childBaseline : -1;
         } else {
             return -1;
         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 17aea8b..e350ec4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -16,6 +16,11 @@
 
 package android.widget;
 
+import com.android.internal.util.FastMath;
+import com.android.internal.widget.EditableInputConnection;
+
+import org.xmlpull.v1.XmlPullParserException;
+
 import android.R;
 import android.content.ClipData;
 import android.content.ClipData.Item;
@@ -62,6 +67,7 @@
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.text.TextWatcher;
+import android.text.method.AllCapsTransformationMethod;
 import android.text.method.ArrowKeyMovementMethod;
 import android.text.method.DateKeyListener;
 import android.text.method.DateTimeKeyListener;
@@ -76,6 +82,7 @@
 import android.text.method.TextKeyListener;
 import android.text.method.TimeKeyListener;
 import android.text.method.TransformationMethod;
+import android.text.method.TransformationMethod2;
 import android.text.method.WordIterator;
 import android.text.style.ClickableSpan;
 import android.text.style.ParagraphStyle;
@@ -125,11 +132,6 @@
 import android.view.inputmethod.InputMethodManager;
 import android.widget.RemoteViews.RemoteView;
 
-import com.android.internal.util.FastMath;
-import com.android.internal.widget.EditableInputConnection;
-
-import org.xmlpull.v1.XmlPullParserException;
-
 import java.io.IOException;
 import java.lang.ref.WeakReference;
 import java.text.BreakIterator;
@@ -340,6 +342,16 @@
 
     private WordIterator mWordIterator;
 
+    // The alignment to pass to Layout, or null if not resolved.
+    private Layout.Alignment mLayoutAlignment;
+
+    // The default value for mTextAlign.
+    private TextAlign mTextAlign = TextAlign.INHERIT;
+
+    private static enum TextAlign {
+        INHERIT, GRAVITY, TEXT_START, TEXT_END, CENTER, VIEW_START, VIEW_END;
+    }
+
     /*
      * Kick-start the font cache for the zygote process (to pay the cost of
      * initializing freetype for our default font only once).
@@ -414,6 +426,7 @@
         int textSize = 15;
         int typefaceIndex = -1;
         int styleIndex = -1;
+        boolean allCaps = false;
 
         /*
          * Look the appearance up without checking first if it exists because
@@ -461,6 +474,10 @@
                 case com.android.internal.R.styleable.TextAppearance_textStyle:
                     styleIndex = appearance.getInt(attr, -1);
                     break;
+
+                case com.android.internal.R.styleable.TextAppearance_textAllCaps:
+                    allCaps = appearance.getBoolean(attr, false);
+                    break;
                 }
             }
 
@@ -812,6 +829,10 @@
             case com.android.internal.R.styleable.TextView_suggestionsEnabled:
                 mSuggestionsEnabled = a.getBoolean(attr, true);
                 break;
+
+            case com.android.internal.R.styleable.TextView_textAllCaps:
+                allCaps = a.getBoolean(attr, false);
+                break;
             }
         }
         a.recycle();
@@ -994,6 +1015,10 @@
         }
         setRawTextSize(textSize);
 
+        if (allCaps) {
+            setTransformationMethod(new AllCapsTransformationMethod(getContext()));
+        }
+
         if (password || passwordInputType || webPasswordInputType || numberPasswordInputType) {
             setTransformationMethod(PasswordTransformationMethod.getInstance());
             typefaceIndex = MONOSPACE;
@@ -1321,6 +1346,14 @@
 
         mTransformation = method;
 
+        if (method instanceof TransformationMethod2) {
+            TransformationMethod2 method2 = (TransformationMethod2) method;
+            mAllowTransformationLengthChange = !mTextIsSelectable && !(mText instanceof Editable);
+            method2.setLengthChangesAllowed(mAllowTransformationLengthChange);
+        } else {
+            mAllowTransformationLengthChange = false;
+        }
+
         setText(mText);
     }
 
@@ -1765,6 +1798,11 @@
 
         setTypefaceByIndex(typefaceIndex, styleIndex);
         
+        if (appearance.getBoolean(com.android.internal.R.styleable.TextAppearance_textAllCaps,
+                false)) {
+            setTransformationMethod(new AllCapsTransformationMethod(getContext()));
+        }
+
         appearance.recycle();
     }
 
@@ -2813,14 +2851,15 @@
         mBufferType = type;
         mText = text;
 
-        if (mTransformation == null)
+        if (mTransformation == null) {
             mTransformed = text;
-        else
+        } else {
             mTransformed = mTransformation.getTransformation(text, this);
+        }
 
         final int textLength = text.length();
 
-        if (text instanceof Spannable) {
+        if (text instanceof Spannable && !mAllowTransformationLengthChange) {
             Spannable sp = (Spannable) text;
 
             // Remove any ChangeWatchers that might have come
@@ -2842,7 +2881,6 @@
 
             if (mTransformation != null) {
                 sp.setSpan(mTransformation, 0, textLength, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
-
             }
 
             if (mMovement != null) {
@@ -4948,7 +4986,10 @@
                         if (mMovement != null && mText instanceof Editable
                                 && mLayout != null && onCheckIsTextEditor()) {
                             InputMethodManager imm = InputMethodManager.peekInstance();
-                            if (imm != null) imm.showSoftInput(this, 0);
+                            if (imm != null) {
+                                imm.viewClicked(this);
+                                imm.showSoftInput(this, 0);
+                            }
                         }
                     }
                 }
@@ -5529,6 +5570,73 @@
                       physicalWidth, false);
     }
 
+    @Override
+    protected void resetResolvedLayoutDirection() {
+        super.resetResolvedLayoutDirection();
+
+        if (mLayoutAlignment != null &&
+                (mTextAlign == TextAlign.VIEW_START ||
+                mTextAlign == TextAlign.VIEW_END)) {
+            mLayoutAlignment = null;
+        }
+    }
+
+    private Layout.Alignment getLayoutAlignment() {
+        if (mLayoutAlignment == null) {
+            Layout.Alignment alignment;
+            TextAlign textAlign = mTextAlign;
+            switch (textAlign) {
+                case INHERIT:
+                    // fall through to gravity temporarily
+                    // intention is to inherit value through view hierarchy.
+                case GRAVITY:
+                    switch (mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) {
+                        case Gravity.START:
+                            alignment = Layout.Alignment.ALIGN_NORMAL;
+                            break;
+                        case Gravity.END:
+                            alignment = Layout.Alignment.ALIGN_OPPOSITE;
+                            break;
+                        case Gravity.LEFT:
+                            alignment = Layout.Alignment.ALIGN_LEFT;
+                            break;
+                        case Gravity.RIGHT:
+                            alignment = Layout.Alignment.ALIGN_RIGHT;
+                            break;
+                        case Gravity.CENTER_HORIZONTAL:
+                            alignment = Layout.Alignment.ALIGN_CENTER;
+                            break;
+                        default:
+                            alignment = Layout.Alignment.ALIGN_NORMAL;
+                            break;
+                    }
+                    break;
+                case TEXT_START:
+                    alignment = Layout.Alignment.ALIGN_NORMAL;
+                    break;
+                case TEXT_END:
+                    alignment = Layout.Alignment.ALIGN_OPPOSITE;
+                    break;
+                case CENTER:
+                    alignment = Layout.Alignment.ALIGN_CENTER;
+                    break;
+                case VIEW_START:
+                    alignment = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
+                            Layout.Alignment.ALIGN_RIGHT : Layout.Alignment.ALIGN_LEFT;
+                    break;
+                case VIEW_END:
+                    alignment = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
+                            Layout.Alignment.ALIGN_LEFT : Layout.Alignment.ALIGN_RIGHT;
+                    break;
+                default:
+                    alignment = Layout.Alignment.ALIGN_NORMAL;
+                    break;
+            }
+            mLayoutAlignment = alignment;
+        }
+        return mLayoutAlignment;
+    }
+
     /**
      * The width passed in is now the desired layout width,
      * not the full view width with padding.
@@ -5549,25 +5657,7 @@
             hintWidth = 0;
         }
 
-        final int layoutDirection = getResolvedLayoutDirection();
-        final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-
-        Layout.Alignment alignment;
-        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
-            case Gravity.CENTER_HORIZONTAL:
-                alignment = Layout.Alignment.ALIGN_CENTER;
-                break;
-
-            case Gravity.RIGHT:
-                // Note, Layout resolves ALIGN_OPPOSITE to left or
-                // right based on the paragraph direction.
-                alignment = Layout.Alignment.ALIGN_OPPOSITE;
-                break;
-
-            default:
-                alignment = Layout.Alignment.ALIGN_NORMAL;
-        }
-
+        Layout.Alignment alignment = getLayoutAlignment();
         boolean shouldEllipsize = mEllipsize != null && mInput == null;
 
         if (mText instanceof Spannable) {
@@ -6508,6 +6598,26 @@
     }
 
     /**
+     * Sets the properties of this field to transform input to ALL CAPS
+     * display. This may use a "small caps" formatting if available.
+     * This setting will be ignored if this field is editable or selectable.
+     *
+     * This call replaces the current transformation method. Disabling this
+     * will not necessarily restore the previous behavior from before this
+     * was enabled.
+     *
+     * @see #setTransformationMethod(TransformationMethod)
+     * @attr ref android.R.styleable#TextView_textAllCaps
+     */
+    public void setAllCaps(boolean allCaps) {
+        if (allCaps) {
+            setTransformationMethod(new AllCapsTransformationMethod(getContext()));
+        } else {
+            setTransformationMethod(null);
+        }
+    }
+
+    /**
      * If true, sets the properties of this field (number of lines, horizontally scrolling,
      * transformation method) to be for a single-line input; if false, restores these to the default
      * conditions.
@@ -6834,9 +6944,9 @@
      * @param selEnd The new selection end location.
      */
     protected void onSelectionChanged(int selStart, int selEnd) {
-        // intentionally empty
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
     }
-    
+
     /**
      * Adds a TextWatcher to the list of those whose methods are called
      * whenever this TextView's text changes.
@@ -7398,8 +7508,11 @@
 
             if ((isTextEditable() || mTextIsSelectable) && touchIsFinished) {
                 // Show the IME, except when selecting in read-only text.
+                final InputMethodManager imm = InputMethodManager.peekInstance();
+                if (imm != null) {
+                    imm.viewClicked(this);
+                }
                 if (!mTextIsSelectable) {
-                    final InputMethodManager imm = InputMethodManager.peekInstance();
                     handled |= imm != null && imm.showSoftInput(this, 0);
                 }
 
@@ -7922,6 +8035,12 @@
 
         final boolean isPassword = hasPasswordTransformationMethod();
         event.setPassword(isPassword);
+
+        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED) {
+            event.setFromIndex(Selection.getSelectionStart(mText));
+            event.setToIndex(Selection.getSelectionEnd(mText));
+            event.setItemCount(mText.length());
+        }
     }
 
     @Override
@@ -8830,7 +8949,7 @@
             TypedArray styledAttributes = mContext.obtainStyledAttributes(R.styleable.Theme);
 
             boolean allowText = getContext().getResources().getBoolean(
-                    com.android.internal.R.bool.allow_action_menu_item_text_with_icon);
+                    com.android.internal.R.bool.config_allowActionMenuItemTextWithIcon);
 
             mode.setTitle(allowText ? 
                     mContext.getString(com.android.internal.R.string.textSelectionCABTitle) : null);
@@ -10004,6 +10123,172 @@
         return mInBatchEditControllers;
     }
 
+    /**
+     * Resolve the text direction.
+     *
+     * Text direction of paragraphs in a TextView is determined using a heuristic. If the correct
+     * text direction cannot be determined by the heuristic, the view’s resolved layout direction
+     * determines the direction.
+     *
+     * This heuristic and result is applied individually to each paragraph in a TextView, based on
+     * the text and style content of that paragraph. Paragraph text styles can also be used to force
+     * a particular direction.
+     */
+    @Override
+    protected void resolveTextDirection() {
+        int resolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+        switch(mTextDirection) {
+            default:
+            case TEXT_DIRECTION_INHERIT:
+                // Try to the text direction from the parent layout. If not possible, then we will
+                // use the default layout direction to decide later
+                if (mParent != null && mParent instanceof ViewGroup) {
+                    resolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection();
+                }
+                break;
+            case TEXT_DIRECTION_FIRST_STRONG:
+                resolvedTextDirection = getTextDirectionFromFirstStrong(mText);
+                break;
+            case TEXT_DIRECTION_ANY_RTL:
+                resolvedTextDirection = getTextDirectionFromAnyRtl(mText);
+                break;
+            case TEXT_DIRECTION_CHAR_COUNT:
+                resolvedTextDirection = getTextDirectionFromCharCount(mText);
+                break;
+            case TEXT_DIRECTION_LTR:
+                resolvedTextDirection = TEXT_DIRECTION_LTR;
+                break;
+            case TEXT_DIRECTION_RTL:
+                resolvedTextDirection = TEXT_DIRECTION_RTL;
+                break;
+        }
+        // if we have been so far unable to get the text direction from the heuristics, then we are
+        // falling back using the layout direction
+        if (resolvedTextDirection == TEXT_DIRECTION_UNDEFINED) {
+            switch(getResolvedLayoutDirection()) {
+                default:
+                case LAYOUT_DIRECTION_LTR:
+                    resolvedTextDirection = TEXT_DIRECTION_LTR;
+                    break;
+                case LAYOUT_DIRECTION_RTL:
+                    resolvedTextDirection = TEXT_DIRECTION_RTL;
+                    break;
+            }
+        }
+        mResolvedTextDirection = resolvedTextDirection;
+    }
+
+    /**
+     * Get text direction following the "first strong" heuristic.
+     *
+     * @param cs the CharSequence used to get the text direction.
+     *
+     * @return {@link #TEXT_DIRECTION_RTL} if direction it RTL, {@link #TEXT_DIRECTION_LTR} if
+     * direction it LTR or {@link #TEXT_DIRECTION_UNDEFINED} if direction cannot be found.
+     */
+    private static int getTextDirectionFromFirstStrong(final CharSequence cs) {
+        final int length = cs.length();
+        if (length == 0) {
+            return TEXT_DIRECTION_UNDEFINED;
+        }
+        for(int i = 0; i < length; i++) {
+            final char c = cs.charAt(i);
+            final byte dir = Character.getDirectionality(c);
+            if (isStrongLtrChar(dir)) {
+                return TEXT_DIRECTION_LTR;
+            } else if (isStrongRtlChar(dir)) {
+                return TEXT_DIRECTION_RTL;
+            }
+        }
+        return TEXT_DIRECTION_UNDEFINED;
+    }
+
+    /**
+     * Get text direction following the "any RTL" heuristic.
+     *
+     * @param cs the CharSequence used to get the text direction.
+     *
+     * @return {@link #TEXT_DIRECTION_RTL} if direction it RTL, {@link #TEXT_DIRECTION_LTR} if
+     * direction it LTR or {@link #TEXT_DIRECTION_UNDEFINED} if direction cannot be found.
+     */
+    private static int getTextDirectionFromAnyRtl(final CharSequence cs) {
+        final int length = cs.length();
+        if (length == 0) {
+            return TEXT_DIRECTION_UNDEFINED;
+        }
+        boolean foundStrongLtr = false;
+        boolean foundStrongRtl = false;
+        for(int i = 0; i < length; i++) {
+            final char c = cs.charAt(i);
+            final byte dir = Character.getDirectionality(c);
+            if (isStrongLtrChar(dir)) {
+                foundStrongLtr = true;
+            } else if (isStrongRtlChar(dir)) {
+                foundStrongRtl = true;
+                break;
+            }
+        }
+        if (foundStrongRtl) {
+            return TEXT_DIRECTION_RTL;
+        }
+        if (foundStrongLtr) {
+            return TEXT_DIRECTION_LTR;
+        }
+        return TEXT_DIRECTION_UNDEFINED;
+    }
+
+    /**
+     * Get text direction following the "char count" heuristic.
+     *
+     * @param cs the CharSequence used to get the text direction.
+     *
+     * @return {@link #TEXT_DIRECTION_RTL} if direction it RTL, {@link #TEXT_DIRECTION_LTR} if
+     * direction it LTR or {@link #TEXT_DIRECTION_UNDEFINED} if direction cannot be found.
+     */
+    private int getTextDirectionFromCharCount(CharSequence cs) {
+        final int length = cs.length();
+        if (length == 0) {
+            return TEXT_DIRECTION_UNDEFINED;
+        }
+        int countLtr = 0;
+        int countRtl = 0;
+        for(int i = 0; i < length; i++) {
+            final char c = cs.charAt(i);
+            final byte dir = Character.getDirectionality(c);
+            if (isStrongLtrChar(dir)) {
+                countLtr++;
+            } else if (isStrongRtlChar(dir)) {
+                countRtl++;
+            }
+        }
+        final float percentLtr = ((float) countLtr) / (countLtr + countRtl);
+        if (percentLtr > DEFAULT_TEXT_DIRECTION_CHAR_COUNT_THRESHOLD) {
+            return TEXT_DIRECTION_LTR;
+        }
+        final float percentRtl = ((float) countRtl) / (countLtr + countRtl);
+        if (percentRtl > DEFAULT_TEXT_DIRECTION_CHAR_COUNT_THRESHOLD) {
+            return TEXT_DIRECTION_RTL;
+        }
+        return TEXT_DIRECTION_UNDEFINED;
+    }
+
+    /**
+     * Return true if the char direction is corresponding to a "strong RTL char" following the
+     * Unicode Bidirectional Algorithm (UBA).
+     */
+    private static boolean isStrongRtlChar(final byte dir) {
+        return (dir == Character.DIRECTIONALITY_RIGHT_TO_LEFT ||
+                dir == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC);
+    }
+
+    /**
+     * Return true if the char direction is corresponding to a "strong LTR char" following the
+     * Unicode Bidirectional Algorithm (UBA).
+     */
+    private static boolean isStrongLtrChar(final byte dir) {
+        return (dir == Character.DIRECTIONALITY_LEFT_TO_RIGHT);
+    }
+
     @ViewDebug.ExportedProperty(category = "text")
     private CharSequence            mText;
     private CharSequence            mTransformed;
@@ -10017,6 +10302,7 @@
 
     private MovementMethod          mMovement;
     private TransformationMethod    mTransformation;
+    private boolean                 mAllowTransformationLengthChange;
     private ChangeWatcher           mChangeWatcher;
 
     private ArrayList<TextWatcher>  mListeners = null;
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 8d5df6f..519acf5 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.app;
 
-import com.android.internal.R;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuPopupHelper;
 import com.android.internal.view.menu.SubMenuBuilder;
@@ -36,7 +35,6 @@
 import android.app.FragmentTransaction;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.view.ActionMode;
@@ -580,6 +578,9 @@
 
         mActionView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
         mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE);
+        if (mTabScrollView != null && !mActionView.hasEmbeddedTabs() && mActionView.isCollapsed()) {
+            mTabScrollView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
+        }
     }
 
     /**
@@ -620,6 +621,7 @@
 
             // Clear out the context mode views after the animation finishes
             mContextView.closeMode();
+
             mActionMode = null;
 
             if (mWasHiddenBeforeMode) {
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index b57046c..ec64552 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -135,6 +135,16 @@
         return null;
    }
 
+   public static String getSdFilesystem(String cid) {
+       try {
+            return getMountService().getSecureContainerFilesystemPath(cid);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to get container path for " + cid +
+                " with exception " + e);
+        }
+        return null;
+   }
+
     public static boolean finalizeSdDir(String cid) {
         try {
             int rc = getMountService().finalizeSecureContainer(cid);
diff --git a/core/java/com/android/internal/net/LegacyVpnInfo.aidl b/core/java/com/android/internal/net/LegacyVpnInfo.aidl
new file mode 100644
index 0000000..0ca2627
--- /dev/null
+++ b/core/java/com/android/internal/net/LegacyVpnInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.net;
+
+parcelable LegacyVpnInfo;
diff --git a/core/java/com/android/internal/net/LegacyVpnInfo.java b/core/java/com/android/internal/net/LegacyVpnInfo.java
new file mode 100644
index 0000000..b620aba
--- /dev/null
+++ b/core/java/com/android/internal/net/LegacyVpnInfo.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.net;
+
+import android.app.PendingIntent;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A simple container used to carry information of the ongoing legacy VPN.
+ * Internal use only.
+ *
+ * @hide
+ */
+public class LegacyVpnInfo implements Parcelable {
+    public static final int STATE_DISCONNECTED = 0;
+    public static final int STATE_INITIALIZING = 1;
+    public static final int STATE_CONNECTING = 2;
+    public static final int STATE_CONNECTED = 3;
+    public static final int STATE_TIMEOUT = 4;
+    public static final int STATE_FAILED = 5;
+
+    public String key;
+    public int state = -1;
+    public PendingIntent intent;
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(key);
+        out.writeInt(state);
+        out.writeParcelable(intent, flags);
+    }
+
+    public static final Parcelable.Creator<LegacyVpnInfo> CREATOR =
+            new Parcelable.Creator<LegacyVpnInfo>() {
+        @Override
+        public LegacyVpnInfo createFromParcel(Parcel in) {
+            LegacyVpnInfo info = new LegacyVpnInfo();
+            info.key = in.readString();
+            info.state = in.readInt();
+            info.intent = in.readParcelable(null);
+            return info;
+        }
+
+        @Override
+        public LegacyVpnInfo[] newArray(int size) {
+            return new LegacyVpnInfo[size];
+        }
+    };
+}
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index 773be5b..d36be10 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -21,7 +21,8 @@
 import android.content.Intent;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.SystemClock;
+
+import java.util.List;
 
 /**
  * A simple container used to carry information in VpnBuilder, VpnDialogs,
@@ -33,11 +34,7 @@
 
     public static final String ACTION_VPN_REVOKED = "android.net.vpn.action.REVOKED";
 
-    public static void enforceCallingPackage(String packageName) {
-        if (!"com.android.vpndialogs".equals(packageName)) {
-            throw new SecurityException("Unauthorized Caller");
-        }
-    }
+    public static final String LEGACY_VPN = "[Legacy VPN]";
 
     public static Intent getIntentForConfirmation() {
         Intent intent = new Intent();
@@ -45,24 +42,25 @@
         return intent;
     }
 
-    public static PendingIntent getIntentForNotification(Context context, VpnConfig config) {
-        config.startTime = SystemClock.elapsedRealtime();
+    public static PendingIntent getIntentForStatusPanel(Context context, VpnConfig config) {
         Intent intent = new Intent();
         intent.setClassName("com.android.vpndialogs", "com.android.vpndialogs.ManageDialog");
         intent.putExtra("config", config);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY |
                 Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-        return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+        return PendingIntent.getActivity(context, 0, intent, (config == null) ?
+                PendingIntent.FLAG_NO_CREATE : PendingIntent.FLAG_CANCEL_CURRENT);
     }
 
-    public String packageName;
-    public String sessionName;
-    public String interfaceName;
-    public String configureActivity;
+    public String packagz;
+    public String interfaze;
+    public String session;
     public int mtu = -1;
     public String addresses;
     public String routes;
-    public String dnsServers;
+    public List<String> dnsServers;
+    public List<String> searchDomains;
+    public PendingIntent configureIntent;
     public long startTime = -1;
 
     @Override
@@ -72,14 +70,15 @@
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
-        out.writeString(packageName);
-        out.writeString(sessionName);
-        out.writeString(interfaceName);
-        out.writeString(configureActivity);
+        out.writeString(packagz);
+        out.writeString(interfaze);
+        out.writeString(session);
         out.writeInt(mtu);
         out.writeString(addresses);
         out.writeString(routes);
-        out.writeString(dnsServers);
+        out.writeStringList(dnsServers);
+        out.writeStringList(searchDomains);
+        out.writeParcelable(configureIntent, flags);
         out.writeLong(startTime);
     }
 
@@ -88,14 +87,15 @@
         @Override
         public VpnConfig createFromParcel(Parcel in) {
             VpnConfig config = new VpnConfig();
-            config.packageName = in.readString();
-            config.sessionName = in.readString();
-            config.interfaceName = in.readString();
-            config.configureActivity = in.readString();
+            config.packagz = in.readString();
+            config.interfaze = in.readString();
+            config.session = in.readString();
             config.mtu = in.readInt();
             config.addresses = in.readString();
             config.routes = in.readString();
-            config.dnsServers = in.readString();
+            config.dnsServers = in.createStringArrayList();
+            config.searchDomains = in.createStringArrayList();
+            config.configureIntent = in.readParcelable(null);
             config.startTime = in.readLong();
             return config;
         }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 12687a1..7b65964 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -41,6 +41,7 @@
 import android.util.Printer;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.TimeUtils;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -4870,8 +4871,8 @@
         return 0;
     }
 
-    void readHistory(Parcel in) {
-        mHistoryBaseTime = in.readLong();
+    void readHistory(Parcel in, boolean andOldHistory) {
+        final long historyBaseTime = in.readLong();
 
         mHistoryBuffer.setDataSize(0);
         mHistoryBuffer.setDataPosition(0);
@@ -4889,15 +4890,35 @@
             in.setDataPosition(curPos + bufSize);
         }
 
-        long oldnow = SystemClock.elapsedRealtime() - (5*60*1000);
-        if (oldnow > 0) {
-            // If the system process has restarted, but not the entire
-            // system, then the mHistoryBaseTime already accounts for
-            // much of the elapsed time.  We thus want to adjust it back,
-            // to avoid large gaps in the data.  We determine we are
-            // in this case by arbitrarily saying it is so if at this
-            // point in boot the elapsed time is already more than 5 minutes.
-            mHistoryBaseTime -= oldnow;
+        if (andOldHistory) {
+            readOldHistory(in);
+        }
+
+        if (DEBUG_HISTORY) {
+            StringBuilder sb = new StringBuilder(128);
+            sb.append("****************** OLD mHistoryBaseTime: ");
+            TimeUtils.formatDuration(mHistoryBaseTime, sb);
+            Slog.i(TAG, sb.toString());
+        }
+        mHistoryBaseTime = historyBaseTime;
+        if (DEBUG_HISTORY) {
+            StringBuilder sb = new StringBuilder(128);
+            sb.append("****************** NEW mHistoryBaseTime: ");
+            TimeUtils.formatDuration(mHistoryBaseTime, sb);
+            Slog.i(TAG, sb.toString());
+        }
+
+        // We are just arbitrarily going to insert 1 minute from the sample of
+        // the last run until samples in this run.
+        if (mHistoryBaseTime > 0) {
+            long oldnow = SystemClock.elapsedRealtime();
+            mHistoryBaseTime = (mHistoryBaseTime - oldnow) + 60*1000;
+            if (DEBUG_HISTORY) {
+                StringBuilder sb = new StringBuilder(128);
+                sb.append("****************** ADJUSTED mHistoryBaseTime: ");
+                TimeUtils.formatDuration(mHistoryBaseTime, sb);
+                Slog.i(TAG, sb.toString());
+            }
         }
     }
 
@@ -4910,12 +4931,24 @@
         }
     }
 
-    void writeHistory(Parcel out) {
-        out.writeLong(mLastHistoryTime);
+    void writeHistory(Parcel out, boolean andOldHistory) {
+        if (DEBUG_HISTORY) {
+            StringBuilder sb = new StringBuilder(128);
+            sb.append("****************** WRITING mHistoryBaseTime: ");
+            TimeUtils.formatDuration(mHistoryBaseTime, sb);
+            sb.append(" mLastHistoryTime: ");
+            TimeUtils.formatDuration(mLastHistoryTime, sb);
+            Slog.i(TAG, sb.toString());
+        }
+        out.writeLong(mHistoryBaseTime + mLastHistoryTime);
         out.writeInt(mHistoryBuffer.dataSize());
         if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
                 + mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
         out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
+
+        if (andOldHistory) {
+            writeOldHistory(out);
+        }
     }
 
     void writeOldHistory(Parcel out) {
@@ -4935,8 +4968,7 @@
             return;
         }
 
-        readHistory(in);
-        readOldHistory(in);
+        readHistory(in, true);
 
         mStartCount = in.readInt();
         mBatteryUptime = in.readLong();
@@ -5136,8 +5168,7 @@
 
         out.writeInt(VERSION);
 
-        writeHistory(out);
-        writeOldHistory(out);
+        writeHistory(out, true);
 
         out.writeInt(mStartCount);
         out.writeLong(computeBatteryUptime(NOW_SYS, STATS_SINCE_CHARGED));
@@ -5340,7 +5371,7 @@
             throw new ParcelFormatException("Bad magic number");
         }
 
-        readHistory(in);
+        readHistory(in, false);
 
         mStartCount = in.readInt();
         mBatteryUptime = in.readLong();
@@ -5461,7 +5492,7 @@
 
         out.writeInt(MAGIC);
 
-        writeHistory(out);
+        writeHistory(out, false);
 
         out.writeInt(mStartCount);
         out.writeLong(mBatteryUptime);
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 5e9cd23..53516c0 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -25,16 +25,13 @@
 import android.os.SystemProperties;
 import android.util.Log;
 import android.util.Slog;
-
 import com.android.internal.logging.AndroidConfig;
-
+import com.android.server.NetworkManagementSocketTagger;
 import dalvik.system.VMRuntime;
-
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.util.logging.LogManager;
 import java.util.TimeZone;
-
+import java.util.logging.LogManager;
 import org.apache.harmony.luni.internal.util.TimezoneGetter;
 
 /**
@@ -129,6 +126,11 @@
         System.setProperty("http.agent", userAgent);
 
         /*
+         * Wire socket tagging to traffic stats.
+         */
+        NetworkManagementSocketTagger.install();
+
+        /*
          * If we're running in an emulator launched with "-trace", put the
          * VM into emulator trace profiling mode so that the user can hit
          * F9/F10 at any time to capture traces.  This has performance
@@ -250,9 +252,10 @@
      *   <li> <code> [--] &lt;start class name&gt;  &lt;args&gt;
      * </ul>
      *
+     * @param targetSdkVersion target SDK version
      * @param argv arg strings
      */
-    public static final void zygoteInit(String[] argv)
+    public static final void zygoteInit(int targetSdkVersion, String[] argv)
             throws ZygoteInit.MethodAndArgsCaller {
         if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
 
@@ -261,7 +264,7 @@
         commonInit();
         zygoteInitNative();
 
-        applicationInit(argv);
+        applicationInit(targetSdkVersion, argv);
     }
 
     /**
@@ -272,20 +275,22 @@
      * which calls {@link WrapperInit#main} which then calls this method.
      * So we don't need to call commonInit() here.
      *
+     * @param targetSdkVersion target SDK version
      * @param argv arg strings
      */
-    public static void wrapperInit(String[] argv)
+    public static void wrapperInit(int targetSdkVersion, String[] argv)
             throws ZygoteInit.MethodAndArgsCaller {
         if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from wrapper");
 
-        applicationInit(argv);
+        applicationInit(targetSdkVersion, argv);
     }
 
-    private static void applicationInit(String[] argv)
+    private static void applicationInit(int targetSdkVersion, String[] argv)
             throws ZygoteInit.MethodAndArgsCaller {
         // We want to be fairly aggressive about heap utilization, to avoid
         // holding on to a lot of memory that isn't needed.
         VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
+        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
 
         final Arguments args;
         try {
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index 860a08c..c6b3e7c 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -47,16 +47,22 @@
      * wrapper process instead of by forking Zygote.
      *
      * The first argument specifies the file descriptor for a pipe that should receive
-     * the pid of this process, or 0 if none.  The remaining arguments are passed to
-     * the runtime.
+     * the pid of this process, or 0 if none.
+     *
+     * The second argument is the target SDK version for the app.
+     *
+     * The remaining arguments are passed to the runtime.
      *
      * @param args The command-line arguments.
      */
     public static void main(String[] args) {
         try {
+            // Parse our mandatory arguments.
+            int fdNum = Integer.parseInt(args[0], 10);
+            int targetSdkVersion = Integer.parseInt(args[1], 10);
+
             // Tell the Zygote what our actual PID is (since it only knows about the
             // wrapper that it directly forked).
-            int fdNum = Integer.parseInt(args[0], 10);
             if (fdNum != 0) {
                 try {
                     FileDescriptor fd = ZygoteInit.createFileDescriptor(fdNum);
@@ -73,9 +79,9 @@
             ZygoteInit.preload();
 
             // Launch the application.
-            String[] runtimeArgs = new String[args.length - 1];
-            System.arraycopy(args, 1, runtimeArgs, 0, runtimeArgs.length);
-            RuntimeInit.wrapperInit(runtimeArgs);
+            String[] runtimeArgs = new String[args.length - 2];
+            System.arraycopy(args, 2, runtimeArgs, 0, runtimeArgs.length);
+            RuntimeInit.wrapperInit(targetSdkVersion, runtimeArgs);
         } catch (ZygoteInit.MethodAndArgsCaller caller) {
             caller.run();
         }
@@ -87,11 +93,12 @@
      *
      * @param invokeWith The wrapper command.
      * @param niceName The nice name for the application, or null if none.
+     * @param targetSdkVersion The target SDK version for the app.
      * @param pipeFd The pipe to which the application's pid should be written, or null if none.
      * @param args Arguments for {@link RuntimeInit.main}.
      */
     public static void execApplication(String invokeWith, String niceName,
-            FileDescriptor pipeFd, String[] args) {
+            int targetSdkVersion, FileDescriptor pipeFd, String[] args) {
         StringBuilder command = new StringBuilder(invokeWith);
         command.append(" /system/bin/app_process /system/bin --application");
         if (niceName != null) {
@@ -99,6 +106,8 @@
         }
         command.append(" com.android.internal.os.WrapperInit ");
         command.append(pipeFd != null ? pipeFd.getInt$() : 0);
+        command.append(' ');
+        command.append(targetSdkVersion);
         Zygote.appendQuotedShellArgs(command, args);
         Zygote.execShell(command.toString());
     }
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index b872e22..a3b7795 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -18,6 +18,7 @@
 
 import android.net.Credentials;
 import android.net.LocalSocket;
+import android.os.Build;
 import android.os.Process;
 import android.os.SystemProperties;
 import android.util.Log;
@@ -328,11 +329,15 @@
         boolean peerWait;
 
         /**
-         * From --enable-debugger, --enable-checkjni, --enable-assert, and
-         * --enable-safemode
+         * From --enable-debugger, --enable-checkjni, --enable-assert,
+         * --enable-safemode, and --enable-jni-logging.
          */
         int debugFlags;
 
+        /** from --target-sdk-version. */
+        int targetSdkVersion;
+        boolean targetSdkVersionSpecified;
+
         /** from --classpath */
         String classpath;
 
@@ -402,12 +407,22 @@
                     gidSpecified = true;
                     gid = Integer.parseInt(
                             arg.substring(arg.indexOf('=') + 1));
+                } else if (arg.startsWith("--target-sdk-version=")) {
+                    if (targetSdkVersionSpecified) {
+                        throw new IllegalArgumentException(
+                                "Duplicate target-sdk-version specified");
+                    }
+                    targetSdkVersionSpecified = true;
+                    targetSdkVersion = Integer.parseInt(
+                            arg.substring(arg.indexOf('=') + 1));
                 } else if (arg.equals("--enable-debugger")) {
                     debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
                 } else if (arg.equals("--enable-safemode")) {
                     debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
                 } else if (arg.equals("--enable-checkjni")) {
                     debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
+                } else if (arg.equals("--enable-jni-logging")) {
+                    debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
                 } else if (arg.equals("--enable-assert")) {
                     debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
                 } else if (arg.equals("--peer-wait")) {
@@ -819,9 +834,11 @@
         if (parsedArgs.runtimeInit) {
             if (parsedArgs.invokeWith != null) {
                 WrapperInit.execApplication(parsedArgs.invokeWith,
-                        parsedArgs.niceName, pipeFd, parsedArgs.remainingArgs);
+                        parsedArgs.niceName, parsedArgs.targetSdkVersion,
+                        pipeFd, parsedArgs.remainingArgs);
             } else {
-                RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
+                RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
+                        parsedArgs.remainingArgs);
             }
         } else {
             String className;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index b4a7e52..6ec186d 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -48,7 +48,7 @@
  * Startup class for the zygote process.
  *
  * Pre-initializes some classes, and then waits for commands on a UNIX domain
- * socket. Based on these commands, forks of child processes that inherit
+ * socket. Based on these commands, forks off child processes that inherit
  * the initial state of the VM.
  *
  * Please see {@link ZygoteConnection.Arguments} for documentation on the
@@ -453,12 +453,13 @@
 
         if (parsedArgs.invokeWith != null) {
             WrapperInit.execApplication(parsedArgs.invokeWith,
-                    parsedArgs.niceName, null, parsedArgs.remainingArgs);
+                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
+                    null, parsedArgs.remainingArgs);
         } else {
             /*
              * Pass the remaining arguments to SystemServer.
              */
-            RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
+            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
         }
 
         /* should never reach here */
@@ -491,7 +492,9 @@
             /* Request to fork the system server process */
             pid = Zygote.forkSystemServer(
                     parsedArgs.uid, parsedArgs.gid,
-                    parsedArgs.gids, parsedArgs.debugFlags, null,
+                    parsedArgs.gids,
+                    parsedArgs.debugFlags,
+                    null,
                     parsedArgs.permittedCapabilities,
                     parsedArgs.effectiveCapabilities);
         } catch (IllegalArgumentException ex) {
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index 2e7ec58..b754d94 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -26,6 +26,9 @@
  * codes with Message.what starting at Protocol.WIFI + 1 and less than or equal to Protocol.WIFI +
  * Protocol.MAX_MESSAGE
  *
+ * NOTE: After a value is created and source released a value shouldn't be changed to
+ * maintain backwards compatibility.
+ *
  * {@hide}
  */
 public class Protocol {
@@ -40,7 +43,7 @@
     public static final int BASE_DHCP                                               = 0x00030000;
     public static final int BASE_DATA_CONNECTION                                    = 0x00040000;
     public static final int BASE_DATA_CONNECTION_AC                                 = 0x00041000;
-    public static final int BASE_DATA_CONNECTION_TRACKER                            = 0x00050000;
+    public static final int BASE_DATA_CONNECTION_TRACKER                            = 0x00042000;
 
     //TODO: define all used protocols
 }
diff --git a/core/java/com/android/internal/view/IInputMethodSession.aidl b/core/java/com/android/internal/view/IInputMethodSession.aidl
index 338dcaa..f875cbd 100644
--- a/core/java/com/android/internal/view/IInputMethodSession.aidl
+++ b/core/java/com/android/internal/view/IInputMethodSession.aidl
@@ -36,7 +36,9 @@
     void updateSelection(int oldSelStart, int oldSelEnd,
             int newSelStart, int newSelEnd,
             int candidatesStart, int candidatesEnd);
-    
+
+    void viewClicked(boolean focusChanged);
+
     void updateCursor(in Rect newCursor);
     
     void displayCompletions(in CompletionInfo[] completions);
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java
index a4bcf60..2685046 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItem.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
+import android.view.ActionProvider;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.MenuItem;
 import android.view.SubMenu;
@@ -238,6 +239,16 @@
     }
 
     @Override
+    public ActionProvider getActionProvider() {
+        return null;
+    }
+
+    @Override
+    public MenuItem setActionProvider(ActionProvider actionProvider) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public MenuItem setShowAsActionFlags(int actionEnum) {
         setShowAsAction(actionEnum);
         return this;
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index 479788d..09bebae 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -17,6 +17,7 @@
 package com.android.internal.view.menu;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -38,17 +39,24 @@
 
     private ImageButton mImageButton;
     private Button mTextButton;
+    private boolean mAllowTextWithIcon;
+    private boolean mShowTextAllCaps;
+    private boolean mExpandedFormat;
 
     public ActionMenuItemView(Context context) {
         this(context, null);
     }
 
     public ActionMenuItemView(Context context, AttributeSet attrs) {
-        super(context, attrs);
+        this(context, attrs, 0);
     }
 
     public ActionMenuItemView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
+        final Resources res = context.getResources();
+        mAllowTextWithIcon = res.getBoolean(
+                com.android.internal.R.bool.config_allowActionMenuItemTextWithIcon);
+        mShowTextAllCaps = res.getBoolean(com.android.internal.R.bool.config_actionMenuItemAllCaps);
     }
 
     @Override
@@ -104,9 +112,20 @@
         // TODO Support checkable action items
     }
 
+    public void setExpandedFormat(boolean expandedFormat) {
+        if (mExpandedFormat != expandedFormat) {
+            mExpandedFormat = expandedFormat;
+            if (mItemData != null) {
+                mItemData.actionFormatChanged();
+            }
+        }
+    }
+
     private void updateTextButtonVisibility() {
         boolean visible = !TextUtils.isEmpty(mTextButton.getText());
-        visible = visible && (mImageButton.getDrawable() == null || mItemData.showsTextAsAction());
+        visible &= mImageButton.getDrawable() == null ||
+                (mItemData.showsTextAsAction() && (mAllowTextWithIcon || mExpandedFormat));
+
         mTextButton.setVisibility(visible ? VISIBLE : GONE);
     }
 
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 322a854..b86eb13 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -19,13 +19,14 @@
 import com.android.internal.view.menu.ActionMenuView.ActionMenuChildView;
 
 import android.content.Context;
-import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.util.Log;
 import android.util.SparseBooleanArray;
 import android.view.MenuItem;
 import android.view.SoundEffectConstants;
 import android.view.View;
 import android.view.View.MeasureSpec;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.widget.ImageButton;
 
@@ -47,6 +48,8 @@
     private boolean mStrictWidthLimit;
     private boolean mWidthLimitSet;
 
+    private int mMinCellSize;
+
     // Group IDs that have been added as actions - used temporarily, allocated here for reuse.
     private final SparseBooleanArray mActionButtonGroups = new SparseBooleanArray();
 
@@ -69,9 +72,7 @@
         final Resources res = context.getResources();
 
         if (!mReserveOverflowSet) {
-            // TODO Use the no-buttons specifier instead here
-            mReserveOverflow = res.getConfiguration()
-                    .isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE);
+            mReserveOverflow = !ViewConfiguration.get(context).hasPermanentMenuKey();
         }
 
         if (!mWidthLimitSet) {
@@ -97,6 +98,8 @@
 
         mActionItemWidthLimit = width;
 
+        mMinCellSize = (int) (ActionMenuView.MIN_CELL_SIZE * res.getDisplayMetrics().density);
+
         // Drop a scrap view as it may no longer reflect the proper context/config.
         mScrapActionButtonView = null;
     }
@@ -127,16 +130,30 @@
     @Override
     public View getItemView(MenuItemImpl item, View convertView, ViewGroup parent) {
         View actionView = item.getActionView();
-        actionView = actionView != null && !item.hasCollapsibleActionView() ?
-                actionView : super.getItemView(item, convertView, parent);
+        if (actionView == null || item.hasCollapsibleActionView()) {
+            if (!(convertView instanceof ActionMenuItemView)) {
+                convertView = null;
+            }
+            actionView = super.getItemView(item, convertView, parent);
+        }
         actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE);
+
+        final ActionMenuView menuParent = (ActionMenuView) parent;
+        final ViewGroup.LayoutParams lp = actionView.getLayoutParams();
+        if (!menuParent.checkLayoutParams(lp)) {
+            actionView.setLayoutParams(menuParent.generateLayoutParams(lp));
+        }
         return actionView;
     }
 
     @Override
     public void bindItemView(MenuItemImpl item, MenuView.ItemView itemView) {
         itemView.initialize(item, 0);
-        ((ActionMenuItemView) itemView).setItemInvoker((ActionMenuView) mMenuView);
+
+        final ActionMenuView menuView = (ActionMenuView) mMenuView;
+        ActionMenuItemView actionItemView = (ActionMenuItemView) itemView;
+        actionItemView.setItemInvoker(menuView);
+        if (false) actionItemView.setExpandedFormat(menuView.isExpandedFormat());
     }
 
     @Override
@@ -151,15 +168,14 @@
         if (mReserveOverflow && mMenu.getNonActionItems().size() > 0) {
             if (mOverflowButton == null) {
                 mOverflowButton = new OverflowMenuButton(mContext);
-                mOverflowButton.setLayoutParams(
-                        ((ActionMenuView) mMenuView).generateOverflowButtonLayoutParams());
             }
             ViewGroup parent = (ViewGroup) mOverflowButton.getParent();
             if (parent != mMenuView) {
                 if (parent != null) {
                     parent.removeView(mOverflowButton);
                 }
-                ((ViewGroup) mMenuView).addView(mOverflowButton);
+                ActionMenuView menuView = (ActionMenuView) mMenuView;
+                menuView.addView(mOverflowButton, menuView.generateOverflowButtonLayoutParams());
             }
         } else if (mOverflowButton != null && mOverflowButton.getParent() == mMenuView) {
             ((ViewGroup) mMenuView).removeView(mOverflowButton);
@@ -314,19 +330,29 @@
         final SparseBooleanArray seenGroups = mActionButtonGroups;
         seenGroups.clear();
 
+        int cellSize = 0;
+        int cellsRemaining = 0;
+        if (mStrictWidthLimit) {
+            cellsRemaining = widthLimit / mMinCellSize;
+            final int cellSizeRemaining = widthLimit % mMinCellSize;
+            cellSize = mMinCellSize + cellSizeRemaining / cellsRemaining;
+        }
+
         // Flag as many more requested items as will fit.
         for (int i = 0; i < itemsSize; i++) {
             MenuItemImpl item = visibleItems.get(i);
 
             if (item.requiresActionButton()) {
-                View v = item.getActionView();
-                if (v == null || item.hasCollapsibleActionView()) {
-                    v = getItemView(item, mScrapActionButtonView, parent);
-                    if (mScrapActionButtonView == null) {
-                        mScrapActionButtonView = v;
-                    }
+                View v = getItemView(item, mScrapActionButtonView, parent);
+                if (mScrapActionButtonView == null) {
+                    mScrapActionButtonView = v;
                 }
-                v.measure(querySpec, querySpec);
+                if (mStrictWidthLimit) {
+                    cellsRemaining -= ActionMenuView.measureChildForCells(v,
+                            cellSize, cellsRemaining, querySpec, 0);
+                } else {
+                    v.measure(querySpec, querySpec);
+                }
                 final int measuredWidth = v.getMeasuredWidth();
                 widthLimit -= measuredWidth;
                 if (firstActionWidth == 0) {
@@ -342,18 +368,25 @@
                 // can break the max actions rule, but not the width limit.
                 final int groupId = item.getGroupId();
                 final boolean inGroup = seenGroups.get(groupId);
-                boolean isAction = (maxActions > 0 || inGroup) && widthLimit > 0;
+                boolean isAction = (maxActions > 0 || inGroup) && widthLimit > 0 &&
+                        (!mStrictWidthLimit || cellsRemaining > 0);
                 maxActions--;
 
                 if (isAction) {
-                    View v = item.getActionView();
-                    if (v == null || item.hasCollapsibleActionView()) {
-                        v = getItemView(item, mScrapActionButtonView, parent);
-                        if (mScrapActionButtonView == null) {
-                            mScrapActionButtonView = v;
-                        }
+                    View v = getItemView(item, mScrapActionButtonView, parent);
+                    if (mScrapActionButtonView == null) {
+                        mScrapActionButtonView = v;
                     }
-                    v.measure(querySpec, querySpec);
+                    if (mStrictWidthLimit) {
+                        final int cells = ActionMenuView.measureChildForCells(v,
+                                cellSize, cellsRemaining, querySpec, 0);
+                        cellsRemaining -= cells;
+                        if (cells == 0) {
+                            isAction = false;
+                        }
+                    } else {
+                        v.measure(querySpec, querySpec);
+                    }
                     final int measuredWidth = v.getMeasuredWidth();
                     widthLimit -= measuredWidth;
                     if (firstActionWidth == 0) {
@@ -361,10 +394,10 @@
                     }
 
                     if (mStrictWidthLimit) {
-                        isAction = widthLimit >= 0;
+                        isAction &= widthLimit >= 0;
                     } else {
                         // Did this push the entire first item past the limit?
-                        isAction = widthLimit + firstActionWidth > 0;
+                        isAction &= widthLimit + firstActionWidth > 0;
                     }
                 }
 
@@ -415,7 +448,7 @@
         }
 
         public boolean needsDividerBefore() {
-            return true;
+            return false;
         }
 
         public boolean needsDividerAfter() {
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index 7b4f216..bf2965b 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -30,12 +30,16 @@
 public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvoker, MenuView {
     private static final String TAG = "ActionMenuView";
     
+    static final int MIN_CELL_SIZE = 56; // dips
+
     private MenuBuilder mMenu;
 
     private boolean mReserveOverflow;
     private ActionMenuPresenter mPresenter;
     private boolean mUpdateContentsBeforeMeasure;
     private boolean mFormatItems;
+    private int mMinCellSize;
+    private int mMeasuredExtraWidth;
 
     public ActionMenuView(Context context) {
         this(context, null);
@@ -44,12 +48,17 @@
     public ActionMenuView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setBaselineAligned(false);
+        mMinCellSize = (int) (MIN_CELL_SIZE * context.getResources().getDisplayMetrics().density);
     }
 
     public void setPresenter(ActionMenuPresenter presenter) {
         mPresenter = presenter;
     }
 
+    public boolean isExpandedFormat() {
+        return mFormatItems;
+    }
+
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
@@ -70,13 +79,195 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // If we've been given an exact size to match, apply special formatting during layout.
+        mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY;
         if (mUpdateContentsBeforeMeasure && mMenu != null) {
             mMenu.onItemsChanged(true);
             mUpdateContentsBeforeMeasure = false;
         }
-        // If we've been given an exact size to match, apply special formatting during layout.
-        mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY;
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+        if (mFormatItems) {
+            onMeasureExactFormat(widthMeasureSpec, heightMeasureSpec);
+        } else {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        }
+    }
+
+    private void onMeasureExactFormat(int widthMeasureSpec, int heightMeasureSpec) {
+        // We already know the width mode is EXACTLY if we're here.
+        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+
+        final int widthPadding = getPaddingLeft() + getPaddingRight();
+        final int heightPadding = getPaddingTop() + getPaddingBottom();
+
+        widthSize -= widthPadding;
+
+        // Divide the view into cells.
+        final int cellCount = widthSize / mMinCellSize;
+        final int cellSizeRemaining = widthSize % mMinCellSize;
+        final int cellSize = mMinCellSize + cellSizeRemaining / cellCount;
+
+        int cellsRemaining = cellCount;
+        int maxChildHeight = 0;
+        int maxCellsUsed = 0;
+        int expandableItemCount = 0;
+
+        if (mReserveOverflow) cellsRemaining--;
+
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final View child = getChildAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            lp.expanded = false;
+            lp.extraPixels = 0;
+            lp.cellsUsed = 0;
+            lp.expandable = false;
+
+            // Overflow always gets 1 cell. No more, no less.
+            final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining;
+
+            final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable,
+                    heightMeasureSpec, heightPadding);
+
+            maxCellsUsed = Math.max(maxCellsUsed, cellsUsed);
+            if (lp.expandable) expandableItemCount++;
+
+            cellsRemaining -= cellsUsed;
+            maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());
+        }
+
+        // Divide space for remaining cells if we have items that can expand.
+        // Try distributing whole leftover cells to smaller items first.
+
+        boolean needsExpansion = false;
+        long smallestExpandableItemsAt = 0;
+        while (expandableItemCount > 0 && cellsRemaining > 0) {
+            int minCells = Integer.MAX_VALUE;
+            long minCellsAt = 0; // Bit locations are indices of relevant child views
+            int minCellsItemCount = 0;
+            for (int i = 0; i < childCount; i++) {
+                final View child = getChildAt(i);
+                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+                // Don't try to expand items that shouldn't.
+                if (!lp.expandable) continue;
+
+                // Mark indices of children that can receive an extra cell.
+                if (lp.cellsUsed < minCells) {
+                    minCells = lp.cellsUsed;
+                    minCellsAt = 1 << i;
+                    minCellsItemCount = 1;
+                } else if (lp.cellsUsed == minCells) {
+                    minCellsAt |= 1 << i;
+                    minCellsItemCount++;
+                }
+            }
+
+            if (minCellsItemCount > cellsRemaining) break; // Couldn't expand anything evenly. Stop.
+
+            // Items that get expanded will always be in the set of smallest items when we're done.
+            smallestExpandableItemsAt |= minCellsAt;
+
+            for (int i = 0; i < childCount; i++) {
+                if ((minCellsAt & (1 << i)) == 0) continue;
+
+                final View child = getChildAt(i);
+                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                lp.cellsUsed++;
+                lp.expanded = true;
+                cellsRemaining--;
+            }
+
+            needsExpansion = true;
+        }
+
+        // Divide any space left that wouldn't divide along cell boundaries
+        // evenly among the smallest multi-cell (expandable) items.
+
+        if (cellsRemaining > 0 && smallestExpandableItemsAt != 0) {
+            final int expandCount = Long.bitCount(smallestExpandableItemsAt);
+            final int extraPixels = cellsRemaining * cellSize / expandCount;
+
+            for (int i = 0; i < childCount; i++) {
+                if ((smallestExpandableItemsAt & (1 << i)) == 0) continue;
+
+                final View child = getChildAt(i);
+                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                lp.extraPixels = extraPixels;
+                lp.expanded = true;
+            }
+
+            needsExpansion = true;
+            cellsRemaining = 0;
+        }
+
+        // Remeasure any items that have had extra space allocated to them.
+        if (needsExpansion) {
+            int heightSpec = MeasureSpec.makeMeasureSpec(heightSize - heightPadding, heightMode);
+            for (int i = 0; i < childCount; i++) {
+                final View child = getChildAt(i);
+                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+                if (!lp.expanded) continue;
+
+                final int width = lp.cellsUsed * cellSize + lp.extraPixels;
+                child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), heightSpec);
+            }
+        }
+
+        if (heightMode != MeasureSpec.EXACTLY) {
+            heightSize = maxChildHeight;
+        }
+
+        setMeasuredDimension(widthSize, heightSize);
+        mMeasuredExtraWidth = cellsRemaining * cellSize;
+    }
+
+    /**
+     * Measure a child view to fit within cell-based formatting. The child's width
+     * will be measured to a whole multiple of cellSize.
+     *
+     * <p>Sets the expandable and cellsUsed fields of LayoutParams.
+     *
+     * @param child Child to measure
+     * @param cellSize Size of one cell
+     * @param cellsRemaining Number of cells remaining that this view can expand to fill
+     * @param parentHeightMeasureSpec MeasureSpec used by the parent view
+     * @param parentHeightPadding Padding present in the parent view
+     * @return Number of cells this child was measured to occupy
+     */
+    static int measureChildForCells(View child, int cellSize, int cellsRemaining,
+            int parentHeightMeasureSpec, int parentHeightPadding) {
+        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+        final int childHeightSize = MeasureSpec.getSize(parentHeightMeasureSpec) -
+                parentHeightPadding;
+        final int childHeightMode = MeasureSpec.getMode(parentHeightMeasureSpec);
+        final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode);
+
+        int cellsUsed = 0;
+        if (cellsRemaining > 0) {
+            final int childWidthSpec = MeasureSpec.makeMeasureSpec(
+                    cellSize * cellsRemaining, MeasureSpec.AT_MOST);
+            child.measure(childWidthSpec, childHeightSpec);
+
+            final int measuredWidth = child.getMeasuredWidth();
+            cellsUsed = measuredWidth / cellSize;
+            if (measuredWidth % cellSize != 0) cellsUsed++;
+        }
+
+        final ActionMenuItemView itemView = child instanceof ActionMenuItemView ?
+                (ActionMenuItemView) child : null;
+        final boolean expandable = !lp.isOverflowButton && itemView != null && itemView.hasText();
+        lp.expandable = expandable;
+
+        lp.cellsUsed = cellsUsed;
+        final int targetWidth = cellsUsed * cellSize;
+        child.measure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY),
+                childHeightSpec);
+        return cellsUsed;
     }
 
     @Override
@@ -93,6 +284,7 @@
         int nonOverflowWidth = 0;
         int nonOverflowCount = 0;
         int widthRemaining = right - left - getPaddingRight() - getPaddingLeft();
+        boolean hasOverflow = false;
         for (int i = 0; i < childCount; i++) {
             final View v = getChildAt(i);
             if (v.getVisibility() == GONE) {
@@ -107,15 +299,18 @@
                 }
 
                 int height = v.getMeasuredHeight();
-                int r = getPaddingRight();
+                int r = getWidth() - getPaddingRight();
                 int l = r - overflowWidth;
                 int t = midVertical - (height / 2);
                 int b = t + height;
                 v.layout(l, t, r, b);
 
                 widthRemaining -= overflowWidth;
+                hasOverflow = true;
             } else {
-                nonOverflowWidth += v.getMeasuredWidth() + p.leftMargin + p.rightMargin;
+                final int size = v.getMeasuredWidth() + p.leftMargin + p.rightMargin;
+                nonOverflowWidth += size;
+                widthRemaining -= size;
                 if (hasDividerBeforeChildAt(i)) {
                     nonOverflowWidth += dividerWidth;
                 }
@@ -123,10 +318,8 @@
             }
         }
 
-        // Fill action items from the left. Overflow will always pin to the right edge.
-        if (nonOverflowWidth <= widthRemaining - overflowWidth) {
-            widthRemaining -= overflowWidth;
-        }
+        final int spacerCount = nonOverflowCount - (hasOverflow ? 0 : 1);
+        final int spacerSize = spacerCount > 0 ? widthRemaining / spacerCount : 0;
 
         int startLeft = getPaddingLeft();
         for (int i = 0; i < childCount; i++) {
@@ -141,7 +334,7 @@
             int height = v.getMeasuredHeight();
             int t = midVertical - (height / 2);
             v.layout(startLeft, t, startLeft + width, t + height);
-            startLeft += width + lp.rightMargin;
+            startLeft += width + lp.rightMargin + spacerSize;
         }
     }
 
@@ -168,6 +361,11 @@
     }
     
     @Override
+    public LayoutParams generateLayoutParams(AttributeSet attrs) {
+        return new LayoutParams(getContext(), attrs);
+    }
+
+    @Override
     protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
         if (p instanceof LayoutParams) {
             LayoutParams result = new LayoutParams((LayoutParams) p);
@@ -181,7 +379,7 @@
 
     @Override
     protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
-        return p instanceof LayoutParams;
+        return p != null && p instanceof LayoutParams;
     }
 
     public LayoutParams generateOverflowButtonLayoutParams() {
@@ -224,6 +422,14 @@
     public static class LayoutParams extends LinearLayout.LayoutParams {
         @ViewDebug.ExportedProperty(category = "layout")
         public boolean isOverflowButton;
+        @ViewDebug.ExportedProperty(category = "layout")
+        public int cellsUsed;
+        @ViewDebug.ExportedProperty(category = "layout")
+        public int extraPixels;
+        @ViewDebug.ExportedProperty(category = "layout")
+        public boolean expandable;
+
+        public boolean expanded;
 
         public LayoutParams(Context c, AttributeSet attrs) {
             super(c, attrs);
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 253511c..20b7d80 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -23,6 +23,7 @@
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
 import android.util.Log;
+import android.view.ActionProvider;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
@@ -79,6 +80,7 @@
     private int mShowAsAction = SHOW_AS_ACTION_NEVER;
 
     private View mActionView;
+    private ActionProvider mActionProvider;
     private OnActionExpandListener mOnActionExpandListener;
     private boolean mIsActionViewExpanded = false;
 
@@ -98,10 +100,8 @@
     
     
     /**
-     * Instantiates this menu item. The constructor
-     * {@link #MenuItemData(MenuBuilder, int, int, int, CharSequence, int)} is
-     * preferred due to lazy loading of the icon Drawable.
-     * 
+     * Instantiates this menu item.
+     *
      * @param menu
      * @param group Item ordering grouping control. The item will be added after
      *            all other items whose order is <= this number, and before any
@@ -154,7 +154,7 @@
             mItemCallback.run();
             return true;
         }
-        
+
         if (mIntent != null) {
             try {
                 mMenu.getContext().startActivity(mIntent);
@@ -163,7 +163,14 @@
                 Log.e(TAG, "Can't find activity to handle intent; ignoring", e);
             }
         }
-        
+
+        if (mActionProvider != null) {
+            // The action view is created by the provider in this case.
+            View actionView = getActionView();
+            mActionProvider.onPerformDefaultAction(actionView);
+            return true;
+        }
+
         return false;
     }
     
@@ -499,6 +506,10 @@
         return mMenuInfo;
     }
 
+    public void actionFormatChanged() {
+        mMenu.onItemActionRequestChanged(this);
+    }
+
     /**
      * @return Whether the menu should show icons for menu items.
      */
@@ -527,9 +538,7 @@
     }
 
     public boolean showsTextAsAction() {
-        return (mShowAsAction & SHOW_AS_ACTION_WITH_TEXT) == SHOW_AS_ACTION_WITH_TEXT &&
-                mMenu.getContext().getResources().getBoolean(
-                        com.android.internal.R.bool.allow_action_menu_item_text_with_icon);
+        return (mShowAsAction & SHOW_AS_ACTION_WITH_TEXT) == SHOW_AS_ACTION_WITH_TEXT;
     }
 
     public void setShowAsAction(int actionEnum) {
@@ -551,6 +560,7 @@
 
     public MenuItem setActionView(View view) {
         mActionView = view;
+        mActionProvider = null;
         mMenu.onItemActionRequestChanged(this);
         return this;
     }
@@ -563,7 +573,25 @@
     }
 
     public View getActionView() {
-        return mActionView;
+        if (mActionView != null) {
+            return mActionView;
+        } else if (mActionProvider != null) {
+            mActionView = mActionProvider.onCreateActionView();
+            return mActionView;
+        } else {
+            return null;
+        }
+    }
+
+    public ActionProvider getActionProvider() {
+        return mActionProvider;
+    }
+
+    public MenuItem setActionProvider(ActionProvider actionProvider) {
+        mActionView = null;
+        mActionProvider = actionProvider;
+        mMenu.onItemsChanged(false);
+        return this;
     }
 
     @Override
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index d710cfa..9fef2a9 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -19,6 +19,8 @@
 import android.app.ActionBar;
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.ActionMode;
 import android.view.MotionEvent;
@@ -35,6 +37,12 @@
     private View mTabContainer;
     private ActionBarView mActionBarView;
 
+    private Drawable mBackground;
+    private Drawable mStackedBackground;
+    private Drawable mSplitBackground;
+    private boolean mIsSplit;
+    private boolean mIsStacked;
+
     public ActionBarContainer(Context context) {
         this(context, null);
     }
@@ -42,10 +50,23 @@
     public ActionBarContainer(Context context, AttributeSet attrs) {
         super(context, attrs);
 
+        setBackgroundDrawable(null);
+
         TypedArray a = context.obtainStyledAttributes(attrs,
                 com.android.internal.R.styleable.ActionBar);
-        setBackgroundDrawable(a.getDrawable(com.android.internal.R.styleable.ActionBar_background));
+        mBackground = a.getDrawable(com.android.internal.R.styleable.ActionBar_background);
+        mStackedBackground = a.getDrawable(
+                com.android.internal.R.styleable.ActionBar_backgroundStacked);
+
+        if (getId() == com.android.internal.R.id.split_action_bar) {
+            mIsSplit = true;
+            mSplitBackground = a.getDrawable(
+                    com.android.internal.R.styleable.ActionBar_backgroundSplit);
+        }
         a.recycle();
+
+        setWillNotDraw(mIsSplit ? mSplitBackground == null :
+                mBackground == null && mStackedBackground == null);
     }
 
     @Override
@@ -96,6 +117,24 @@
     }
 
     @Override
+    public void onDraw(Canvas canvas) {
+        if (getWidth() == 0 || getHeight() == 0) {
+            return;
+        }
+
+        if (mIsSplit) {
+            if (mSplitBackground != null) mSplitBackground.draw(canvas);
+        } else {
+            if (mBackground != null) {
+                mBackground.draw(canvas);
+            }
+            if (mStackedBackground != null && mIsStacked) {
+                mStackedBackground.draw(canvas);
+            }
+        }
+    }
+
+    @Override
     public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) {
         // No starting an action mode for an action bar child! (Where would it go?)
         return null;
@@ -105,24 +144,19 @@
     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
-        int nonTabHeight = 0;
-        final int count = getChildCount();
-        for (int i = 0; i < count; i++) {
-            final View child = getChildAt(i);
+        if (mActionBarView == null) return;
 
-            if (child == mTabContainer) continue;
-
-            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-            nonTabHeight = Math.max(nonTabHeight,
-                    child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
-        }
+        final LayoutParams lp = (LayoutParams) mActionBarView.getLayoutParams();
+        final int actionBarViewHeight = mActionBarView.isCollapsed() ? 0 :
+                mActionBarView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
 
         if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
             final int mode = MeasureSpec.getMode(heightMeasureSpec);
             if (mode == MeasureSpec.AT_MOST) {
                 final int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
                 setMeasuredDimension(getMeasuredWidth(),
-                        Math.min(nonTabHeight + mTabContainer.getMeasuredHeight(), maxHeight));
+                        Math.min(actionBarViewHeight + mTabContainer.getMeasuredHeight(),
+                                maxHeight));
             }
         }
     }
@@ -130,6 +164,9 @@
     @Override
     public void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
+
+        final boolean hasTabs = mTabContainer != null && mTabContainer.getVisibility() != GONE;
+
         if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
             final int containerHeight = getMeasuredHeight();
             final int tabHeight = mTabContainer.getMeasuredHeight();
@@ -137,17 +174,42 @@
             if ((mActionBarView.getDisplayOptions() & ActionBar.DISPLAY_SHOW_HOME) == 0) {
                 // Not showing home, put tabs on top.
                 final int count = getChildCount();
-                for (int i = 0; i < count; i++){
+                for (int i = 0; i < count; i++) {
                     final View child = getChildAt(i);
 
                     if (child == mTabContainer) continue;
 
-                    child.offsetTopAndBottom(tabHeight);
+                    if (!mActionBarView.isCollapsed()) {
+                        child.offsetTopAndBottom(tabHeight);
+                    }
                 }
                 mTabContainer.layout(l, 0, r, tabHeight);
             } else {
                 mTabContainer.layout(l, containerHeight - tabHeight, r, containerHeight);
             }
         }
+
+        boolean needsInvalidate = false;
+        if (mIsSplit) {
+            if (mSplitBackground != null) {
+                mSplitBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
+                needsInvalidate = true;
+            }
+        } else {
+            if (mBackground != null) {
+                mBackground.setBounds(mActionBarView.getLeft(), mActionBarView.getTop(),
+                        mActionBarView.getRight(), mActionBarView.getBottom());
+                needsInvalidate = true;
+            }
+            if ((mIsStacked = hasTabs && mStackedBackground != null)) {
+                mStackedBackground.setBounds(mTabContainer.getLeft(), mTabContainer.getTop(),
+                        mTabContainer.getRight(), mTabContainer.getBottom());
+                needsInvalidate = true;
+            }
+        }
+
+        if (needsInvalidate) {
+            invalidate();
+        }
     }
 }
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index fc43994..3e3eeab 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -287,7 +287,7 @@
             availableWidth = measureChildView(mClose, availableWidth, childSpecHeight, 0);
         }
 
-        if (mMenuView != null) {
+        if (mMenuView != null && mMenuView.getParent() == this) {
             availableWidth = measureChildView(mMenuView, availableWidth,
                     childSpecHeight, 0);
         }
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 8d75dff..09bc1fc 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -117,6 +117,7 @@
     private boolean mUserTitle;
     private boolean mIncludeTabs;
     private boolean mIsCollapsable;
+    private boolean mIsCollapsed;
 
     private MenuBuilder mOptionsMenu;
     
@@ -692,6 +693,10 @@
         mIsCollapsable = collapsable;
     }
 
+    public boolean isCollapsed() {
+        return mIsCollapsed;
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int childCount = getChildCount();
@@ -708,9 +713,11 @@
             if (visibleChildren == 0) {
                 // No size for an empty action bar when collapsable.
                 setMeasuredDimension(0, 0);
+                mIsCollapsed = true;
                 return;
             }
         }
+        mIsCollapsed = false;
 
         int widthMode = MeasureSpec.getMode(widthMeasureSpec);
         if (widthMode != MeasureSpec.EXACTLY) {
@@ -988,8 +995,8 @@
             int ypos = 0;
             switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
                 case Gravity.CENTER_VERTICAL:
-                    final int paddedTop = mTop + getPaddingTop();
-                    final int paddedBottom = mBottom - getPaddingBottom();
+                    final int paddedTop = getPaddingTop();
+                    final int paddedBottom = mBottom - mTop - getPaddingBottom();
                     ypos = ((paddedBottom - paddedTop) - customView.getMeasuredHeight()) / 2;
                     break;
                 case Gravity.TOP:
@@ -1000,7 +1007,10 @@
                             - bottomMargin;
                     break;
             }
-            x += positionChild(customView, xpos, ypos, contentHeight);
+            final int customWidth = customView.getMeasuredWidth();
+            customView.layout(xpos, ypos, xpos + customWidth,
+                    ypos + customView.getMeasuredHeight());
+            x += customWidth;
         }
 
         if (mProgressView != null) {
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index 5b4d7ab..40e5e8a 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -15,6 +15,9 @@
  */
 package com.android.internal.widget;
 
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
 import android.app.ActionBar;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
@@ -22,6 +25,7 @@
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.animation.DecelerateInterpolator;
 import android.widget.HorizontalScrollView;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -35,6 +39,13 @@
 
     int mMaxTabWidth;
 
+    protected Animator mVisibilityAnim;
+    protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener();
+
+    private static final TimeInterpolator sAlphaInterpolator = new DecelerateInterpolator();
+
+    private static final int FADE_DURATION = 200;
+
     public ScrollingTabContainerView(Context context) {
         super(context);
         setHorizontalScrollBarEnabled(false);
@@ -76,6 +87,30 @@
         }
     }
 
+    public void animateToVisibility(int visibility) {
+        if (mVisibilityAnim != null) {
+            mVisibilityAnim.cancel();
+        }
+        if (visibility == VISIBLE) {
+            if (getVisibility() != VISIBLE) {
+                setAlpha(0);
+            }
+            ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
+            anim.setDuration(FADE_DURATION);
+            anim.setInterpolator(sAlphaInterpolator);
+
+            anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
+            anim.start();
+        } else {
+            ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
+            anim.setDuration(FADE_DURATION);
+            anim.setInterpolator(sAlphaInterpolator);
+
+            anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
+            anim.start();
+        }
+    }
+
     public void animateToTab(int position) {
         final View tabView = mTabLayout.getChildAt(position);
         if (mTabSelector != null) {
@@ -225,7 +260,6 @@
                     if (mTextView == null) {
                         TextView textView = new TextView(getContext(), null,
                                 com.android.internal.R.attr.actionBarTabTextStyle);
-                        textView.setSingleLine();
                         textView.setEllipsize(TruncateAt.END);
                         LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
                                 LayoutParams.WRAP_CONTENT);
@@ -259,4 +293,38 @@
             }
         }
     }
+
+    protected class VisibilityAnimListener implements Animator.AnimatorListener {
+        private boolean mCanceled = false;
+        private int mFinalVisibility;
+
+        public VisibilityAnimListener withFinalVisibility(int visibility) {
+            mFinalVisibility = visibility;
+            return this;
+        }
+
+        @Override
+        public void onAnimationStart(Animator animation) {
+            setVisibility(VISIBLE);
+            mVisibilityAnim = animation;
+            mCanceled = false;
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            if (mCanceled) return;
+
+            mVisibilityAnim = null;
+            setVisibility(mFinalVisibility);
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            mCanceled = true;
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+        }
+    }
 }
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 3e7b976..04bb689 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -20,7 +20,7 @@
 
 import android.animation.Animator;
 import android.animation.Animator.AnimatorListener;
-import android.animation.ObjectAnimator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -43,9 +43,9 @@
  * A special widget containing a center and outer ring. Moving the center ring to the outer ring
  * causes an event that can be caught by implementing OnTriggerListener.
  */
-public class MultiWaveView extends View implements AnimatorUpdateListener {
+public class MultiWaveView extends View {
     private static final String TAG = "MultiWaveView";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;
 
     // Wave state machine
     private static final int STATE_IDLE = 0;
@@ -67,14 +67,15 @@
     }
 
     // Tune-able parameters
-    private static final int CHEVRON_INCREMENTAL_DELAY = 50;
-    private static final int CHEVRON_ANIMATION_DURATION = 1000;
-    private static final int RETURN_TO_HOME_DURATION = 150;
-    private static final int HIDE_ANIMATION_DELAY = 500;
-    private static final int HIDE_ANIMATION_DURACTION = 2000;
+    private static final int CHEVRON_INCREMENTAL_DELAY = 160;
+    private static final int CHEVRON_ANIMATION_DURATION = 650;
+    private static final int RETURN_TO_HOME_DELAY = 1200;
+    private static final int RETURN_TO_HOME_DURATION = 300;
+    private static final int HIDE_ANIMATION_DELAY = 200;
+    private static final int HIDE_ANIMATION_DURATION = RETURN_TO_HOME_DELAY;
     private static final int SHOW_ANIMATION_DURATION = 0;
     private static final int SHOW_ANIMATION_DELAY = 0;
-    private TimeInterpolator mChevronAnimationInterpolator = Ease.Quint.easeOut;
+    private TimeInterpolator mChevronAnimationInterpolator = Ease.Quad.easeOut;
 
     private ArrayList<TargetDrawable> mTargetDrawables = new ArrayList<TargetDrawable>();
     private ArrayList<TargetDrawable> mChevronDrawables = new ArrayList<TargetDrawable>();
@@ -99,14 +100,31 @@
     private float mHitRadius = 0.0f;
     private float mSnapMargin = 0.0f;
     private boolean mDragging;
+    private int mNewTargetResources;
 
-    private AnimatorListener mResetListener = new Animator.AnimatorListener() {
-        public void onAnimationStart(Animator animation) { }
-        public void onAnimationRepeat(Animator animation) { }
-        public void onAnimationEnd(Animator animation) {
+    private AnimatorListener mResetListener = new AnimatorListenerAdapter() {
+        public void onAnimationEnd(Animator animator) {
             switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
         }
-        public void onAnimationCancel(Animator animation) { }
+    };
+
+    private AnimatorUpdateListener mUpdateListener = new AnimatorUpdateListener() {
+        public void onAnimationUpdate(ValueAnimator animation) {
+            invalidateGlobalRegion(mHandleDrawable);
+            invalidate();
+        }
+    };
+
+    private boolean mAnimatingTargets;
+    private AnimatorListener mTargetUpdateListener = new AnimatorListenerAdapter() {
+        public void onAnimationEnd(Animator animator) {
+            if (mNewTargetResources != 0) {
+                internalSetTargetResources(mNewTargetResources);
+                mNewTargetResources = 0;
+                hideTargets(false);
+            }
+            mAnimatingTargets = false;
+        }
     };
 
     public MultiWaveView(Context context) {
@@ -135,31 +153,23 @@
         mOuterRing = new TargetDrawable(res, a.getDrawable(R.styleable.MultiWaveView_waveDrawable));
 
         // Read chevron animation drawables
-        Drawable leftChevron = a.getDrawable(R.styleable.MultiWaveView_leftChevronDrawable);
-        for (int i = 0; i < mFeedbackCount; i++) {
-            mChevronDrawables.add(
-                    leftChevron != null ? new TargetDrawable(res, leftChevron) : null);
-        }
-        Drawable rightChevron = a.getDrawable(R.styleable.MultiWaveView_rightChevronDrawable);
-        for (int i = 0; i < mFeedbackCount; i++) {
-            mChevronDrawables.add(
-                    rightChevron != null ? new TargetDrawable(res, rightChevron) : null);
-        }
-        Drawable topChevron = a.getDrawable(R.styleable.MultiWaveView_topChevronDrawable);
-        for (int i = 0; i < mFeedbackCount; i++) {
-            mChevronDrawables.add(
-                    topChevron != null ? new TargetDrawable(res, topChevron) : null);
-        }
-        Drawable bottomChevron = a.getDrawable(R.styleable.MultiWaveView_bottomChevronDrawable);
-        for (int i = 0; i < mFeedbackCount; i++) {
-            mChevronDrawables.add(
-                    bottomChevron != null ? new TargetDrawable(res, bottomChevron) : null);
+        final int chevrons[] = { R.styleable.MultiWaveView_leftChevronDrawable,
+                R.styleable.MultiWaveView_rightChevronDrawable,
+                R.styleable.MultiWaveView_topChevronDrawable,
+                R.styleable.MultiWaveView_bottomChevronDrawable
+        };
+        for (int chevron : chevrons) {
+            Drawable chevronDrawable = a.getDrawable(chevron);
+            for (int i = 0; i < mFeedbackCount; i++) {
+                mChevronDrawables.add(
+                    chevronDrawable != null ? new TargetDrawable(res, chevronDrawable) : null);
+            }
         }
 
         // Read array of target drawables
         TypedValue outValue = new TypedValue();
         if (a.getValue(R.styleable.MultiWaveView_targetDrawables, outValue)) {
-            setTargetResources(outValue.resourceId);
+            internalSetTargetResources(outValue.resourceId);
         }
         if (mTargetDrawables == null || mTargetDrawables.size() == 0) {
             throw new IllegalStateException("Must specify at least one target drawable");
@@ -205,7 +215,7 @@
             case STATE_FIRST_TOUCH:
                 stopHandleAnimation();
                 deactivateTargets();
-                showTargets();
+                showTargets(true);
                 mHandleDrawable.setState(TargetDrawable.STATE_ACTIVE);
                 setGrabbedState(OnTriggerListener.CENTER_HANDLE);
                 break;
@@ -224,21 +234,22 @@
 
     /**
      * Animation used to attract user's attention to the target button.
-     * Assumes mChevronDrawables is an a list with an even number of chevrons filled with left
-     * followed by right chevrons.
+     * Assumes mChevronDrawables is an a list with an even number of chevrons filled with
+     * mFeedbackCount items in the order: left, right, top, bottom.
      */
     private void startChevronAnimation() {
-        final float r = mHandleDrawable.getWidth() / 2;
+        final float r = mHandleDrawable.getWidth() * 0.4f;
+        final float chevronAnimationDistance = mOuterRadius * 0.8f;
         final float from[][] = {
                 {mWaveCenterX - r, mWaveCenterY},  // left
                 {mWaveCenterX + r, mWaveCenterY},  // right
                 {mWaveCenterX, mWaveCenterY - r},  // top
                 {mWaveCenterX, mWaveCenterY + r} }; // bottom
         final float to[][] = {
-                {mWaveCenterX - mOuterRadius, mWaveCenterY},  // left
-                {mWaveCenterX + mOuterRadius, mWaveCenterY},  // right
-                {mWaveCenterX, mWaveCenterY - mOuterRadius},  // top
-                {mWaveCenterX, mWaveCenterY + mOuterRadius} }; // bottom
+                {mWaveCenterX - chevronAnimationDistance, mWaveCenterY},  // left
+                {mWaveCenterX + chevronAnimationDistance, mWaveCenterY},  // right
+                {mWaveCenterX, mWaveCenterY - chevronAnimationDistance},  // top
+                {mWaveCenterX, mWaveCenterY + chevronAnimationDistance} }; // bottom
 
         mChevronAnimations.clear();
         for (int direction = 0; direction < 4; direction++) {
@@ -254,7 +265,7 @@
                         "x", new float[] { from[direction][0], to[direction][0] },
                         "y", new float[] { from[direction][1], to[direction][1] },
                         "alpha", new float[] {1.0f, 0.0f},
-                        "onUpdate", this));
+                        "onUpdate", mUpdateListener));
             }
         }
     }
@@ -308,70 +319,109 @@
     }
 
     private void doFinish() {
-        // Inform listener of any active targets.  Typically only one will be active.
         final int activeTarget = mActiveTarget;
         boolean targetHit =  activeTarget != -1;
-        if (targetHit) {
-            Log.v(TAG, "Finish with target hit = " + targetHit);
-            dispatchTriggerEvent(mActiveTarget);
-        }
-
-        setGrabbedState(OnTriggerListener.NO_HANDLE);
-
-        // Animate finger outline back to home position
-        mHandleDrawable.setAlpha(targetHit ? 0.0f : 1.0f);
-        mHandleAnimation = Tweener.to(mHandleDrawable, RETURN_TO_HOME_DURATION,
-                "ease", Ease.Quart.easeOut,
-                "delay", targetHit ? HIDE_ANIMATION_DELAY : 0,
-                "alpha", 1.0f,
-                "x", mWaveCenterX,
-                "y", mWaveCenterY,
-                "onUpdate", this,
-                "onComplete", mResetListener);
 
         // Hide unselected targets
         hideTargets(true);
 
         // Highlight the selected one
+        mHandleDrawable.setAlpha(targetHit ? 0.0f : 1.0f);
         if (targetHit) {
             mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
+
+            hideUnselected(activeTarget);
+
+            // Inform listener of any active targets.  Typically only one will be active.
+            if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);
+            dispatchTriggerEvent(mActiveTarget);
+            mHandleAnimation = Tweener.to(mHandleDrawable, 0,
+                    "ease", Ease.Quart.easeOut,
+                    "delay", RETURN_TO_HOME_DELAY,
+                    "alpha", 1.0f,
+                    "x", mWaveCenterX,
+                    "y", mWaveCenterY,
+                    "onUpdate", mUpdateListener,
+                    "onComplete", mResetListener);
+        } else {
+            // Animate finger outline back to home position
+            mHandleAnimation = Tweener.to(mHandleDrawable, RETURN_TO_HOME_DURATION,
+                    "ease", Ease.Quart.easeOut,
+                    "delay", 0,
+                    "alpha", 1.0f,
+                    "x", mWaveCenterX,
+                    "y", mWaveCenterY,
+                    "onUpdate", mUpdateListener,
+                    "onComplete", mResetListener);
         }
+
+        setGrabbedState(OnTriggerListener.NO_HANDLE);
+    }
+
+    private void hideUnselected(int active) {
+        for (int i = 0; i < mTargetDrawables.size(); i++) {
+            if (i != active) {
+                mTargetDrawables.get(i).setAlpha(0.0f);
+            }
+        }
+        mOuterRing.setAlpha(0.0f);
     }
 
     private void hideTargets(boolean animate) {
         if (mTargetAnimations.size() > 0) {
             stopTargetAnimation();
         }
-        for (TargetDrawable target : mTargetDrawables) {
-            target.setState(TargetDrawable.STATE_INACTIVE);
-            mTargetAnimations.add(Tweener.to(target,
-                    animate ? HIDE_ANIMATION_DURACTION : 0,
+        // Note: these animations should complete at the same time so that we can swap out
+        // the target assets asynchronously from the setTargetResources() call.
+        mAnimatingTargets = animate;
+        if (animate) {
+            final int duration = animate ? HIDE_ANIMATION_DURATION : 0;
+            for (TargetDrawable target : mTargetDrawables) {
+                target.setState(TargetDrawable.STATE_INACTIVE);
+                mTargetAnimations.add(Tweener.to(target, duration,
+                        "alpha", 0.0f,
+                        "delay", HIDE_ANIMATION_DELAY,
+                        "onUpdate", mUpdateListener));
+            }
+            mTargetAnimations.add(Tweener.to(mOuterRing, duration,
                     "alpha", 0.0f,
                     "delay", HIDE_ANIMATION_DELAY,
-                    "onUpdate", this));
+                    "onUpdate", mUpdateListener,
+                    "onComplete", mTargetUpdateListener));
+        } else {
+            for (TargetDrawable target : mTargetDrawables) {
+                target.setState(TargetDrawable.STATE_INACTIVE);
+                target.setAlpha(0.0f);
+            }
+            mOuterRing.setAlpha(0.0f);
         }
-        mTargetAnimations.add(Tweener.to(mOuterRing,
-                animate ? HIDE_ANIMATION_DURACTION : 0,
-                "alpha", 0.0f,
-                "delay", HIDE_ANIMATION_DELAY,
-                "onUpdate", this));
     }
 
-    private void showTargets() {
+    private void showTargets(boolean animate) {
         if (mTargetAnimations.size() > 0) {
             stopTargetAnimation();
         }
-        for (TargetDrawable target : mTargetDrawables) {
-            target.setState(TargetDrawable.STATE_INACTIVE);
-            mTargetAnimations.add(Tweener.to(target, SHOW_ANIMATION_DURATION,
+        mAnimatingTargets = animate;
+        if (animate) {
+            for (TargetDrawable target : mTargetDrawables) {
+                target.setState(TargetDrawable.STATE_INACTIVE);
+                mTargetAnimations.add(Tweener.to(target, SHOW_ANIMATION_DURATION,
+                        "alpha", 1.0f,
+                        "delay", SHOW_ANIMATION_DELAY,
+                        "onUpdate", mUpdateListener));
+            }
+            mTargetAnimations.add(Tweener.to(mOuterRing, SHOW_ANIMATION_DURATION,
                     "alpha", 1.0f,
                     "delay", SHOW_ANIMATION_DELAY,
-                    "onUpdate", this));
+                    "onUpdate", mUpdateListener,
+                    "onComplete", mTargetUpdateListener));
+        } else {
+            for (TargetDrawable target : mTargetDrawables) {
+                target.setState(TargetDrawable.STATE_INACTIVE);
+                target.setAlpha(1.0f);
+            }
+            mOuterRing.setAlpha(1.0f);
         }
-        mTargetAnimations.add(Tweener.to(mOuterRing, SHOW_ANIMATION_DURATION,
-                "alpha", 1.0f,
-                "delay", SHOW_ANIMATION_DELAY,
-                "onUpdate", this));
     }
 
     private void stopTargetAnimation() {
@@ -387,12 +437,7 @@
         }
     }
 
-    /**
-     * Loads an array of drawables from the given resourceId.
-     *
-     * @param resourceId
-     */
-    public void setTargetResources(int resourceId) {
+    private void internalSetTargetResources(int resourceId) {
         Resources res = getContext().getResources();
         TypedArray array = res.obtainTypedArray(resourceId);
         int count = array.length();
@@ -402,6 +447,21 @@
             targetDrawables.add(new TargetDrawable(res, drawable));
         }
         mTargetDrawables = targetDrawables;
+        updateTargetPositions();
+    }
+
+    /**
+     * Loads an array of drawables from the given resourceId.
+     *
+     * @param resourceId
+     */
+    public void setTargetResources(int resourceId) {
+        if (mAnimatingTargets) {
+            // postpone this change until we return to the initial state
+            mNewTargetResources = resourceId;
+        } else {
+            internalSetTargetResources(resourceId);
+        }
     }
 
     /**
@@ -442,6 +502,7 @@
         mHandleDrawable.setX(mWaveCenterX);
         mHandleDrawable.setY(mWaveCenterY);
         mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
+        Tweener.reset();
     }
 
     @Override
@@ -589,20 +650,9 @@
         }
     }
 
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        final int width = right - left;
-        final int height = bottom - top;
-
-        mWaveCenterX = mHorizontalOffset + Math.max(width, mOuterRing.getWidth() ) / 2;
-        mWaveCenterY = mVerticalOffset + Math.max(height, mOuterRing.getHeight()) / 2;
-        moveHandleTo(mWaveCenterX, mWaveCenterY, false);
-        mOuterRing.setX(mWaveCenterX);
-        mOuterRing.setY(Math.max(mWaveCenterY, mWaveCenterY));
-        mOuterRing.setAlpha(0.0f);
+    private void performInitialLayout(float centerX, float centerY) {
         if (mOuterRadius == 0.0f) {
-            mOuterRadius = 0.5f*(float) Math.sqrt(dist2(mWaveCenterX, mWaveCenterY));
+            mOuterRadius = 0.5f*(float) Math.sqrt(dist2(centerX, centerY));
         }
         if (mHitRadius == 0.0f) {
             // Use the radius of inscribed circle of the first target.
@@ -612,6 +662,35 @@
             mSnapMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                     SNAP_MARGIN_DEFAULT, getContext().getResources().getDisplayMetrics());
         }
+        hideChevrons();
+        hideTargets(false);
+        moveHandleTo(centerX, centerY, false);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        final int width = right - left;
+        final int height = bottom - top;
+        float newWaveCenterX = mHorizontalOffset + Math.max(width, mOuterRing.getWidth() ) / 2;
+        float newWaveCenterY = mVerticalOffset + Math.max(height, mOuterRing.getHeight()) / 2;
+        if (newWaveCenterX != mWaveCenterX || newWaveCenterY != mWaveCenterY) {
+            if (mWaveCenterX == 0 && mWaveCenterY == 0) {
+                performInitialLayout(newWaveCenterX, newWaveCenterY);
+            }
+            mWaveCenterX = newWaveCenterX;
+            mWaveCenterY = newWaveCenterY;
+
+            mOuterRing.setX(mWaveCenterX);
+            mOuterRing.setY(Math.max(mWaveCenterY, mWaveCenterY));
+
+            updateTargetPositions();
+        }
+        if (DEBUG) dump();
+    }
+
+    private void updateTargetPositions() {
+        // Reposition the target drawables if the view changed.
         for (int i = 0; i < mTargetDrawables.size(); i++) {
             final TargetDrawable targetIcon = mTargetDrawables.get(i);
             double angle = -2.0f * Math.PI * i / mTargetDrawables.size();
@@ -619,11 +698,7 @@
             float yPosition = mWaveCenterY + mOuterRadius * (float) Math.sin(angle);
             targetIcon.setX(xPosition);
             targetIcon.setY(yPosition);
-            targetIcon.setAlpha(0.0f);
         }
-        hideChevrons();
-        hideTargets(false);
-        if (DEBUG) dump();
     }
 
     private void hideChevrons() {
@@ -654,11 +729,6 @@
         mOnTriggerListener = listener;
     }
 
-    public void onAnimationUpdate(ValueAnimator animation) {
-        invalidateGlobalRegion(mHandleDrawable);
-        invalidate();
-    }
-
     private float square(float d) {
         return d * d;
     }
diff --git a/core/java/com/android/internal/widget/multiwaveview/Tweener.java b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
index 0cff00a..bc8a62f 100644
--- a/core/java/com/android/internal/widget/multiwaveview/Tweener.java
+++ b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
@@ -18,25 +18,42 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map.Entry;
 
 import android.animation.Animator.AnimatorListener;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.util.Log;
 
 class Tweener {
     private static final String TAG = "Tweener";
+    private static final boolean DEBUG = false;
 
-    private Object object;
     ObjectAnimator animator;
     private static HashMap<Object, Tweener> sTweens = new HashMap<Object, Tweener>();
 
-    public Tweener(Object obj, ObjectAnimator anim) {
-        object = obj;
+    public Tweener(ObjectAnimator anim) {
         animator = anim;
     }
 
+    private static void remove(Animator animator) {
+        Iterator<Entry<Object, Tweener>> iter = sTweens.entrySet().iterator();
+        while (iter.hasNext()) {
+            Entry<Object, Tweener> entry = iter.next();
+            if (entry.getValue().animator == animator) {
+                if (DEBUG) Log.v(TAG, "Removing tweener " + sTweens.get(entry.getKey())
+                        + " sTweens.size() = " + sTweens.size());
+                iter.remove();
+                break; // an animator can only be attached to one object
+            }
+        }
+    }
+
     public static Tweener to(Object object, long duration, Object... vars) {
         long delay = 0;
         AnimatorUpdateListener updateListener = null;
@@ -77,32 +94,35 @@
 
         // Re-use existing tween, if present
         Tweener tween = sTweens.get(object);
+        ObjectAnimator anim = null;
         if (tween == null) {
-            ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(object,
+            anim = ObjectAnimator.ofPropertyValuesHolder(object,
                     props.toArray(new PropertyValuesHolder[props.size()]));
-            tween = new Tweener(object, anim);
+            tween = new Tweener(anim);
             sTweens.put(object, tween);
+            if (DEBUG) Log.v(TAG, "Added new Tweener " + tween);
         } else {
-            tween.animator.cancel();
-            replace(props, object);
+            anim = sTweens.get(object).animator;
+            replace(props, object); // Cancel all animators for given object
         }
 
         if (interpolator != null) {
-            tween.animator.setInterpolator(interpolator);
+            anim.setInterpolator(interpolator);
         }
 
         // Update animation with properties discovered in loop above
-        tween.animator.setStartDelay(delay);
-        tween.animator.setDuration(duration);
+        anim.setStartDelay(delay);
+        anim.setDuration(duration);
         if (updateListener != null) {
-            tween.animator.removeAllUpdateListeners(); // There should be only one
-            tween.animator.addUpdateListener(updateListener);
+            anim.removeAllUpdateListeners(); // There should be only one
+            anim.addUpdateListener(updateListener);
         }
         if (listener != null) {
-            tween.animator.removeAllListeners(); // There should be only one.
-            tween.animator.addListener(listener);
+            anim.removeAllListeners(); // There should be only one.
+            anim.addListener(listener);
         }
-        tween.animator.start();
+        anim.addListener(mCleanupListener);
+        anim.start();
 
         return tween;
     }
@@ -114,18 +134,40 @@
         return Tweener.to(object, duration, vars);
     }
 
-    static void replace(ArrayList<PropertyValuesHolder> props, Object... args) {
+    // Listener to watch for completed animations and remove them.
+    private static AnimatorListener mCleanupListener = new AnimatorListenerAdapter() {
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            remove(animation);
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            remove(animation);
+        }
+    };
+
+    public static void reset() {
+        if (DEBUG) {
+            Log.v(TAG, "Reset()");
+            if (sTweens.size() > 0) {
+                Log.v(TAG, "Cleaning up " + sTweens.size() + " animations");
+            }
+        }
+        sTweens.clear();
+    }
+
+    private static void replace(ArrayList<PropertyValuesHolder> props, Object... args) {
         for (final Object killobject : args) {
             Tweener tween = sTweens.get(killobject);
             if (tween != null) {
-                if (killobject == tween.object) {
-                    tween.animator.cancel();
-                    if (props != null) {
-                        tween.animator.setValues(
-                                props.toArray(new PropertyValuesHolder[props.size()]));
-                    } else {
-                        sTweens.remove(tween);
-                    }
+                tween.animator.cancel();
+                if (props != null) {
+                    tween.animator.setValues(
+                            props.toArray(new PropertyValuesHolder[props.size()]));
+                } else {
+                    sTweens.remove(tween);
                 }
             }
         }
diff --git a/core/java/com/android/server/NetworkManagementSocketTagger.java b/core/java/com/android/server/NetworkManagementSocketTagger.java
new file mode 100644
index 0000000..2871073
--- /dev/null
+++ b/core/java/com/android/server/NetworkManagementSocketTagger.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import dalvik.system.SocketTagger;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.SocketException;
+import java.nio.charset.Charsets;
+
+/**
+ * Assigns tags to sockets for traffic stats.
+ */
+public final class NetworkManagementSocketTagger extends SocketTagger {
+
+    private static final boolean LOGI = false;
+    private static final boolean ENABLE_TAGGING = false;
+
+    private static ThreadLocal<SocketTags> threadSocketTags = new ThreadLocal<SocketTags>() {
+        @Override protected SocketTags initialValue() {
+            return new SocketTags();
+        }
+    };
+
+    public static void install() {
+        SocketTagger.set(new NetworkManagementSocketTagger());
+    }
+
+    public static void setThreadSocketStatsTag(int tag) {
+        threadSocketTags.get().statsTag = tag;
+    }
+
+    public static void setThreadSocketStatsUid(int uid) {
+        threadSocketTags.get().statsUid = uid;
+    }
+
+    @Override public void tag(FileDescriptor fd) throws SocketException {
+        final SocketTags options = threadSocketTags.get();
+        if (LOGI) {
+            System.logI("tagSocket(" + fd.getInt$() + ") with statsTag="
+                    + options.statsTag + ", statsUid=" + options.statsUid);
+        }
+        try {
+            // TODO: skip tagging when options would be no-op
+            tagSocketFd(fd, options.statsTag, options.statsUid);
+        } catch (IOException e) {
+            throw new SocketException("Problem tagging socket", e);
+        }
+    }
+
+    private void tagSocketFd(FileDescriptor fd, int tag, int uid) throws IOException {
+        final int fdNum = fd.getInt$();
+        if (fdNum == -1 || (tag == -1 && uid == -1)) return;
+
+        String cmd = "t " + fdNum;
+        if (tag == -1) {
+            // Case where just the uid needs adjusting. But probably the caller
+            // will want to track his own name here, just in case.
+            cmd += " 0";
+        } else {
+            cmd += " " + tagToKernel(tag);
+        }
+        if (uid != -1) {
+            cmd += " " + uid;
+        }
+        internalModuleCtrl(cmd);
+    }
+
+    @Override public void untag(FileDescriptor fd) throws SocketException {
+        if (LOGI) {
+            System.logI("untagSocket(" + fd.getInt$() + ")");
+        }
+        try {
+            unTagSocketFd(fd);
+        } catch (IOException e) {
+            throw new SocketException("Problem untagging socket", e);
+        }
+    }
+
+    private void unTagSocketFd(FileDescriptor fd) throws IOException {
+        int fdNum = fd.getInt$();
+        if (fdNum == -1) return;
+        String cmd = "u " + fdNum;
+        internalModuleCtrl(cmd);
+    }
+
+    public static class SocketTags {
+        public int statsTag = -1;
+        public int statsUid = -1;
+    }
+
+    /**
+     * Sends commands to the kernel netfilter module.
+     *
+     * @param cmd command string for the qtaguid netfilter module. May not be null.
+     *   <p>Supports:
+     *     <ul><li>tag a socket:<br>
+     *        <code>t <i>sock_fd</i> <i>acct_tag</i> [<i>uid_in_case_caller_is_acting_on_behalf_of</i>]</code><br>
+     *     <code>*_tag</code> defaults to default_policy_tag_from_uid(uid_of_caller)<br>
+     *     <code>acct_tag</code> is either 0 or greater that 2^32.<br>
+     *     <code>uid_*</code> is only settable by privileged UIDs (DownloadManager,...)
+     *     </li>
+     *     <li>untag a socket, preserving counters:<br>
+     *       <code>u <i>sock_fd</i></code>
+     *     </li></ul>
+     *   <p>Notes:<br>
+     *   <ul><li><i>sock_fd</i> is withing the callers process space.</li>
+     *   <li><i>*_tag</i> are 64bit values</li></ul>
+     *
+     */
+    private void internalModuleCtrl(String cmd) throws IOException {
+        if (!ENABLE_TAGGING) return;
+
+        final FileOutputStream procOut;
+        // TODO: Use something like
+        //  android.os.SystemProperties.getInt("persist.bandwidth.enable", 0)
+        // to see if tagging should happen or not.
+        try {
+            procOut = new FileOutputStream("/proc/net/xt_qtaguid/ctrl");
+        } catch (FileNotFoundException e) {
+            if (LOGI) {
+                System.logI("Can't talk to kernel module:" + e);
+            }
+            return;
+        }
+        try {
+            procOut.write(cmd.getBytes(Charsets.US_ASCII));
+        } finally {
+            procOut.close();
+        }
+    }
+
+    /**
+     * Convert {@link Integer} tag to {@code /proc/} format. Assumes unsigned
+     * base-10 format like {@code 2147483647}. Currently strips signed bit to
+     * avoid using {@link java.math.BigInteger}.
+     */
+    public static String tagToKernel(int tag) {
+        // TODO: eventually write in hex, since that's what proc exports
+        // TODO: migrate to direct integer instead of odd shifting
+        return Long.toString((((long) tag) << 32) & 0x7FFFFFFF00000000L);
+    }
+
+    /**
+     * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
+     * format like {@code 0x7fffffff00000000}.
+     */
+    public static int kernelToTag(String string) {
+        // TODO: migrate to direct integer instead of odd shifting
+        return (int) (Long.decode(string) >> 32);
+    }
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 7b0882f..63fa504 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -75,7 +75,6 @@
 	android_nio_utils.cpp \
 	android_nfc_NdefMessage.cpp \
 	android_nfc_NdefRecord.cpp \
-	android_pim_EventRecurrence.cpp \
 	android_text_format_Time.cpp \
 	android_util_AssetManager.cpp \
 	android_util_Binder.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 21b0a42..a61217a 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -131,7 +131,6 @@
 extern int register_android_nio_utils(JNIEnv* env);
 extern int register_android_nfc_NdefMessage(JNIEnv *env);
 extern int register_android_nfc_NdefRecord(JNIEnv *env);
-extern int register_android_pim_EventRecurrence(JNIEnv* env);
 extern int register_android_text_format_Time(JNIEnv* env);
 extern int register_android_os_Debug(JNIEnv* env);
 extern int register_android_os_MessageQueue(JNIEnv* env);
@@ -1103,7 +1102,6 @@
     REG_JNI(register_android_util_Log),
     REG_JNI(register_android_util_FloatMath),
     REG_JNI(register_android_text_format_Time),
-    REG_JNI(register_android_pim_EventRecurrence),
     REG_JNI(register_android_content_AssetManager),
     REG_JNI(register_android_content_StringBlock),
     REG_JNI(register_android_content_XmlBlock),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 1b22e2d..18bd754 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -273,7 +273,8 @@
 // These must match the int values in Bitmap.java

 enum JavaEncodeFormat {

     kJPEG_JavaEncodeFormat = 0,

-    kPNG_JavaEncodeFormat = 1

+    kPNG_JavaEncodeFormat = 1,

+    kWEBP_JavaEncodeFormat = 2

 };

 

 static bool Bitmap_compress(JNIEnv* env, jobject clazz, SkBitmap* bitmap,

@@ -288,6 +289,9 @@
     case kPNG_JavaEncodeFormat:

         fm = SkImageEncoder::kPNG_Type;

         break;

+    case kWEBP_JavaEncodeFormat:

+        fm = SkImageEncoder::kWEBP_Type;

+        break;

     default:

         return false;

     }

diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 30ef8df..2de0932 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -91,7 +91,8 @@
     virtual void onFrameAvailable();
 
 private:
-    static JNIEnv* getJNIEnv();
+    static JNIEnv* getJNIEnv(bool* needsDetach);
+    static void detachJNI();
 
     jobject mWeakThiz;
     jclass mClazz;
@@ -103,37 +104,57 @@
     mClazz((jclass)env->NewGlobalRef(clazz))
 {}
 
-JNIEnv* JNISurfaceTextureContext::getJNIEnv() {
-    JNIEnv* env;
-    JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
-    JavaVM* vm = AndroidRuntime::getJavaVM();
-    int result = vm->AttachCurrentThread(&env, (void*) &args);
-    if (result != JNI_OK) {
-        LOGE("thread attach failed: %#x", result);
-        return NULL;
+JNIEnv* JNISurfaceTextureContext::getJNIEnv(bool* needsDetach) {
+    *needsDetach = false;
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (env == NULL) {
+        JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
+        JavaVM* vm = AndroidRuntime::getJavaVM();
+        int result = vm->AttachCurrentThread(&env, (void*) &args);
+        if (result != JNI_OK) {
+            LOGE("thread attach failed: %#x", result);
+            return NULL;
+        }
+        *needsDetach = true;
     }
     return env;
 }
 
+void JNISurfaceTextureContext::detachJNI() {
+    JavaVM* vm = AndroidRuntime::getJavaVM();
+    int result = vm->DetachCurrentThread();
+    if (result != JNI_OK) {
+        LOGE("thread detach failed: %#x", result);
+    }
+}
+
 JNISurfaceTextureContext::~JNISurfaceTextureContext()
 {
-    JNIEnv* env = getJNIEnv();
+    bool needsDetach = false;
+    JNIEnv* env = getJNIEnv(&needsDetach);
     if (env != NULL) {
         env->DeleteGlobalRef(mWeakThiz);
         env->DeleteGlobalRef(mClazz);
     } else {
         LOGW("leaking JNI object references");
     }
+    if (needsDetach) {
+        detachJNI();
+    }
 }
 
 void JNISurfaceTextureContext::onFrameAvailable()
 {
-    JNIEnv *env = getJNIEnv();
+    bool needsDetach = false;
+    JNIEnv* env = getJNIEnv(&needsDetach);
     if (env != NULL) {
         env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
     } else {
         LOGW("onFrameAvailable event will not posted");
     }
+    if (needsDetach) {
+        detachJNI();
+    }
 }
 
 // ----------------------------------------------------------------------------
@@ -212,12 +233,6 @@
     return surfaceTexture->getTimestamp();
 }
 
-static jint SurfaceTexture_getQueuedCount(JNIEnv* env, jobject thiz)
-{
-    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
-    return surfaceTexture->getQueuedCount();
-}
-
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gSurfaceTextureMethods[] = {
@@ -228,7 +243,6 @@
     {"nativeUpdateTexImage",     "()V",   (void*)SurfaceTexture_updateTexImage },
     {"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix },
     {"nativeGetTimestamp",       "()J",   (void*)SurfaceTexture_getTimestamp },
-    {"nativeGetQueuedCount",     "()I",   (void*)SurfaceTexture_getQueuedCount }
 };
 
 int register_android_graphics_SurfaceTexture(JNIEnv* env)
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index ddae505..d9bd50e 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -26,7 +26,7 @@
 extern "C" {
 int ifc_enable(const char *ifname);
 int ifc_disable(const char *ifname);
-int ifc_reset_connections(const char *ifname);
+int ifc_reset_connections(const char *ifname, int reset_mask);
 
 int dhcp_do_request(const char *ifname,
                     const char *ipaddr,
@@ -90,12 +90,17 @@
     return (jint)result;
 }
 
-static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz, jstring ifname)
+static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz,
+      jstring ifname, jint mask)
 {
     int result;
 
     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
-    result = ::ifc_reset_connections(nameStr);
+
+    LOGD("android_net_utils_resetConnections in env=%p clazz=%p iface=%s mask=0x%x\n",
+          env, clazz, nameStr, mask);
+
+    result = ::ifc_reset_connections(nameStr, mask);
     env->ReleaseStringUTFChars(ifname, nameStr);
     return (jint)result;
 }
@@ -206,7 +211,7 @@
 
     { "enableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_enableInterface },
     { "disableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_disableInterface },
-    { "resetConnections", "(Ljava/lang/String;)I",  (void *)android_net_utils_resetConnections },
+    { "resetConnections", "(Ljava/lang/String;I)I",  (void *)android_net_utils_resetConnections },
     { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcp },
     { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcpRenew },
     { "stopDhcp", "(Ljava/lang/String;)Z",  (void *)android_net_utils_stopDhcp },
diff --git a/core/jni/android_pim_EventRecurrence.cpp b/core/jni/android_pim_EventRecurrence.cpp
deleted file mode 100644
index 3e11569..0000000
--- a/core/jni/android_pim_EventRecurrence.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/* //device/libs/android_runtime/android_pim_EventRecurrence.cpp

-**

-** Copyright 2006, The Android Open Source Project

-**

-** Licensed under the Apache License, Version 2.0 (the "License");

-** you may not use this file except in compliance with the License.

-** You may obtain a copy of the License at

-**

-**     http://www.apache.org/licenses/LICENSE-2.0

-**

-** Unless required by applicable law or agreed to in writing, software

-** distributed under the License is distributed on an "AS IS" BASIS,

-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

-** See the License for the specific language governing permissions and

-** limitations under the License.

-*/

-

-#include <pim/EventRecurrence.h>

-#include "jni.h"

-#include "nativehelper/JNIHelp.h"

-#include <utils/String8.h>

-

-namespace android {

-

-struct cached_array_fields_t

-{

-    jfieldID array;

-    jfieldID count;

-};

-

-static jfieldID freq_field;

-static jfieldID until_field;

-static jfieldID count_field;

-static jfieldID interval_field;

-static jfieldID wkst_field;

-static cached_array_fields_t bysecond_fields;

-static cached_array_fields_t byminute_fields;

-static cached_array_fields_t byhour_fields;

-static cached_array_fields_t byday_fields;

-static cached_array_fields_t bydayNum_fields;

-static cached_array_fields_t bymonthday_fields;

-static cached_array_fields_t byyearday_fields;

-static cached_array_fields_t byweekno_fields;

-static cached_array_fields_t bymonth_fields;

-static cached_array_fields_t bysetpos_fields;

-

-static status_t

-set_array(JNIEnv* env, int inCount, int* inArray,

-            jobject This, const cached_array_fields_t& fields)

-{

-    if (inCount > 0) {

-        jintArray array = (jintArray) env->GetObjectField(This, fields.array);

-        if (array == NULL || env->GetArrayLength(array) < inCount) {

-            // +4 because it's cheap to allocate a little extra here, and

-            // that reduces the chance that we'll come back here again

-            array = env->NewIntArray(inCount+4);

-            env->SetObjectField(This, fields.array, array);

-        }

-        if (array == NULL) {

-            return NO_MEMORY;

-        }

-        env->SetIntArrayRegion(array, 0, inCount, inArray);

-

-    }

-    env->SetIntField(This, fields.count, inCount);

-    return NO_ERROR;

-}

-

-/*

- * In class android.pim.EventRecurrence

- *  public native int parse(String str);

- */

-#define SET_ARRAY_AND_CHECK(name) \

-    /*printf("setting " #name " to %d elements\n", er.name##Count);*/ \

-    if (set_array(env, er.name##Count, er.name, This, name##_fields) \

-            != NO_ERROR) { \

-        jniThrowException(env, "java/lang/RuntimeException", \

-                "EventRecurrence.parse error setting field " #name " or " \

-                #name "Count."); \

-        return ; \

-    }

-static void

-EventRecurrence_parse(JNIEnv* env, jobject This, jstring jstr)

-{

-    if (jstr == NULL) {

-        jniThrowNullPointerException(env, "EventRecurrence.parse str parameter null");

-        return ;

-    }

-    const jchar* jchars = env->GetStringChars(jstr, NULL);

-    jsize len = env->GetStringLength(jstr);

-    String16 str(jchars, len);

-    env->ReleaseStringChars(jstr, jchars);

-

-    //printf("the string was '%s'\n", String8(str).string());

-

-    EventRecurrence er;

-    if (NO_ERROR != er.parse(str)) {

-        String8 msg("Error parsing recurrence: '");

-        msg.append(String8(str));

-        msg.append("'");

-

-        jniThrowException(env,

-                "android/pim/EventRecurrence$InvalidFormatException",

-                msg.string());

-        return ;

-    }

-

-    jstring untilStr;

-    if (er.until.size() > 0) {

-        untilStr = env->NewString(er.until.string(), er.until.size());

-        if (untilStr == NULL) {

-            jniThrowException(env, "java/lang/RuntimeException",

-                    "EventRecurrence.parse error setting field 'until'");

-            return ;

-        }

-    } else {

-        untilStr = NULL;

-    }

-    env->SetObjectField(This, until_field, untilStr);

-

-    env->SetIntField(This, freq_field, er.freq);

-    env->SetIntField(This, count_field, er.count);

-    env->SetIntField(This, interval_field, er.interval);

-    env->SetIntField(This, wkst_field, er.wkst);

-

-    SET_ARRAY_AND_CHECK(bysecond)

-    SET_ARRAY_AND_CHECK(byminute)

-    SET_ARRAY_AND_CHECK(byhour)

-    SET_ARRAY_AND_CHECK(byday)

-    // we'll just set the bydayCount field twice, it'll be less code total

-    if (set_array(env, er.bydayCount, er.bydayNum, This, bydayNum_fields)

-            != NO_ERROR) {

-        jniThrowException(env, "java/lang/RuntimeException",

-                "EventRecurrence.parse error setting field bydayNum or "

-                "bydayCount.");

-        return ;

-    }

-    SET_ARRAY_AND_CHECK(bymonthday)

-    SET_ARRAY_AND_CHECK(byyearday)

-    SET_ARRAY_AND_CHECK(byweekno)

-    SET_ARRAY_AND_CHECK(bymonth)

-    SET_ARRAY_AND_CHECK(bysetpos)

-}

-

-/*

- * JNI registration.

- */

-static JNINativeMethod METHODS[] = {

-    /* name, signature, funcPtr */

-    { "parseNative", "(Ljava/lang/String;)V", (void*)EventRecurrence_parse }

-};

-

-static const char*const CLASS_NAME = "android/pim/EventRecurrence";

-

-int register_android_pim_EventRecurrence(JNIEnv* env)

-{

-    jclass clazz = env->FindClass(CLASS_NAME);

-    if (clazz == NULL) {

-        LOGE("Field lookup unable to find class '%s'\n", CLASS_NAME);

-        return -1;

-    }

-

-    freq_field = env->GetFieldID(clazz, "freq", "I");

-    count_field = env->GetFieldID(clazz, "count", "I");

-    interval_field = env->GetFieldID(clazz, "interval", "I");

-    wkst_field = env->GetFieldID(clazz, "wkst", "I");

-

-    until_field = env->GetFieldID(clazz, "until", "Ljava/lang/String;");

-

-    bysecond_fields.array = env->GetFieldID(clazz, "bysecond", "[I");

-    bysecond_fields.count = env->GetFieldID(clazz, "bysecondCount", "I");

-    byminute_fields.array = env->GetFieldID(clazz, "byminute", "[I");

-    byminute_fields.count = env->GetFieldID(clazz, "byminuteCount", "I");

-    byhour_fields.array = env->GetFieldID(clazz, "byhour", "[I");

-    byhour_fields.count = env->GetFieldID(clazz, "byhourCount", "I");

-    byday_fields.array = env->GetFieldID(clazz, "byday", "[I");

-    byday_fields.count = env->GetFieldID(clazz, "bydayCount", "I");

-    bydayNum_fields.array = env->GetFieldID(clazz, "bydayNum", "[I");

-    bydayNum_fields.count = byday_fields.count;

-    bymonthday_fields.array = env->GetFieldID(clazz, "bymonthday", "[I");

-    bymonthday_fields.count = env->GetFieldID(clazz, "bymonthdayCount", "I");

-    byyearday_fields.array = env->GetFieldID(clazz, "byyearday", "[I");

-    byyearday_fields.count = env->GetFieldID(clazz, "byyeardayCount", "I");

-    byweekno_fields.array = env->GetFieldID(clazz, "byweekno", "[I");

-    byweekno_fields.count = env->GetFieldID(clazz, "byweeknoCount", "I");

-    bymonth_fields.array = env->GetFieldID(clazz, "bymonth", "[I");

-    bymonth_fields.count = env->GetFieldID(clazz, "bymonthCount", "I");

-    bysetpos_fields.array = env->GetFieldID(clazz, "bysetpos", "[I");

-    bysetpos_fields.count = env->GetFieldID(clazz, "bysetposCount", "I");

-

-    return jniRegisterNativeMethods(env, CLASS_NAME,

-        METHODS, sizeof(METHODS)/sizeof(METHODS[0]));

-}

-

-}; // namespace android

diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index fb25486..2b09442 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -119,7 +119,7 @@
                                                          "(Ljava/lang/String;Z)V");
 
     method_onAgentAuthorize = env->GetMethodID(clazz, "onAgentAuthorize",
-                                               "(Ljava/lang/String;Ljava/lang/String;)Z");
+                                               "(Ljava/lang/String;Ljava/lang/String;I)V");
     method_onAgentOutOfBandDataAvailable = env->GetMethodID(clazz, "onAgentOutOfBandDataAvailable",
                                                "(Ljava/lang/String;)Z");
     method_onAgentCancel = env->GetMethodID(clazz, "onAgentCancel", "()V");
@@ -1114,29 +1114,11 @@
         LOGV("... object_path = %s", object_path);
         LOGV("... uuid = %s", uuid);
 
-        bool auth_granted =
-            env->CallBooleanMethod(nat->me, method_onAgentAuthorize,
-                env->NewStringUTF(object_path), env->NewStringUTF(uuid));
+        dbus_message_ref(msg);  // increment refcount because we pass to java
+        env->CallBooleanMethod(nat->me, method_onAgentAuthorize,
+                env->NewStringUTF(object_path), env->NewStringUTF(uuid),
+                int(msg));
 
-        // reply
-        if (auth_granted) {
-            DBusMessage *reply = dbus_message_new_method_return(msg);
-            if (!reply) {
-                LOGE("%s: Cannot create message reply\n", __FUNCTION__);
-                goto failure;
-            }
-            dbus_connection_send(nat->conn, reply, NULL);
-            dbus_message_unref(reply);
-        } else {
-            DBusMessage *reply = dbus_message_new_error(msg,
-                    "org.bluez.Error.Rejected", "Authorization rejected");
-            if (!reply) {
-                LOGE("%s: Cannot create message reply\n", __FUNCTION__);
-                goto failure;
-            }
-            dbus_connection_send(nat->conn, reply, NULL);
-            dbus_message_unref(reply);
-        }
         goto success;
     } else if (dbus_message_is_method_call(msg,
             "org.bluez.Agent", "OutOfBandAvailable")) {
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index 5f9a96f..86e7cc0 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -255,7 +255,7 @@
 }
 
 static jboolean stopDiscoveryNative(JNIEnv *env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     DBusMessage *msg = NULL;
     DBusMessage *reply = NULL;
@@ -616,6 +616,35 @@
     return JNI_FALSE;
 }
 
+static jboolean setAuthorizationNative(JNIEnv *env, jobject object, jstring address,
+                         jboolean val, int nativeData) {
+#ifdef HAVE_BLUETOOTH
+  LOGV("%s", __FUNCTION__);
+    native_data_t *nat = get_native_data(env, object);
+    if (nat) {
+        DBusMessage *msg = (DBusMessage *)nativeData;
+        DBusMessage *reply;
+        if (val) {
+            reply = dbus_message_new_method_return(msg);
+        } else {
+            reply = dbus_message_new_error(msg,
+                    "org.bluez.Error.Rejected", "Authorization rejected");
+        }
+        if (!reply) {
+            LOGE("%s: Cannot create message reply D-Bus\n", __FUNCTION__);
+            dbus_message_unref(msg);
+            return JNI_FALSE;
+        }
+
+        dbus_connection_send(nat->conn, reply, NULL);
+        dbus_message_unref(msg);
+        dbus_message_unref(reply);
+        return JNI_TRUE;
+    }
+#endif
+    return JNI_FALSE;
+}
+
 static jboolean setPinNative(JNIEnv *env, jobject object, jstring address,
                          jstring pin, int nativeData) {
 #ifdef HAVE_BLUETOOTH
@@ -1683,6 +1712,7 @@
             (void *)setPairingConfirmationNative},
     {"setPasskeyNative", "(Ljava/lang/String;II)Z", (void *)setPasskeyNative},
     {"setRemoteOutOfBandDataNative", "(Ljava/lang/String;[B[BI)Z", (void *)setRemoteOutOfBandDataNative},
+    {"setAuthorizationNative", "(Ljava/lang/String;ZI)Z", (void *)setAuthorizationNative},
     {"setPinNative", "(Ljava/lang/String;Ljava/lang/String;I)Z", (void *)setPinNative},
     {"cancelPairingUserInputNative", "(Ljava/lang/String;I)Z",
             (void *)cancelPairingUserInputNative},
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 0960b25..d1ba2d1 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -318,17 +318,15 @@
                                       jint pid, jint adj)
 {
 #ifdef HAVE_OOM_ADJ
-    if (ProcessState::self()->supportsProcesses()) {
-        char text[64];
-        sprintf(text, "/proc/%d/oom_adj", pid);
-        int fd = open(text, O_WRONLY);
-        if (fd >= 0) {
-            sprintf(text, "%d", adj);
-            write(fd, text, strlen(text));
-            close(fd);
-        }
-        return true;
+    char text[64];
+    sprintf(text, "/proc/%d/oom_adj", pid);
+    int fd = open(text, O_WRONLY);
+    if (fd >= 0) {
+        sprintf(text, "%d", adj);
+        write(fd, text, strlen(text));
+        close(fd);
     }
+    return true;
 #endif
     return false;
 }
@@ -370,11 +368,6 @@
     #endif
 }
 
-jboolean android_os_Process_supportsProcesses(JNIEnv* env, jobject clazz)
-{
-    return ProcessState::self()->supportsProcesses();
-}
-
 static int pid_compare(const void* v1, const void* v2)
 {
     //LOGI("Compare %d vs %d\n", *((const jint*)v1), *((const jint*)v2));
@@ -878,7 +871,6 @@
     {"setGid", "(I)I", (void*)android_os_Process_setGid},
     {"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
     {"sendSignalQuiet", "(II)V", (void*)android_os_Process_sendSignalQuiet},
-    {"supportsProcesses", "()Z", (void*)android_os_Process_supportsProcesses},
     {"getFreeMemory", "()J", (void*)android_os_Process_getFreeMemory},
     {"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V", (void*)android_os_Process_readProcLines},
     {"getPids", "(Ljava/lang/String;[I)[I", (void*)android_os_Process_getPids},
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 537aae6..681f43f 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -115,6 +115,18 @@
     return error == EGL_SUCCESS && value == EGL_BUFFER_PRESERVED;
 }
 
+static void android_view_GLES20Canvas_disableVsync(JNIEnv* env, jobject clazz) {
+    EGLDisplay display = eglGetCurrentDisplay();
+
+    eglGetError();
+    eglSwapInterval(display, 0);
+
+    EGLint error = eglGetError();
+    if (error != EGL_SUCCESS) {
+        RENDERER_LOGD("Could not disable v-sync (%x)", error);
+    }
+}
+
 // ----------------------------------------------------------------------------
 // Constructors
 // ----------------------------------------------------------------------------
@@ -161,6 +173,14 @@
     return renderer->callDrawGLFunction(functor, dirty);
 }
 
+static jint android_view_GLES20Canvas_getMaxTextureWidth(JNIEnv* env, jobject clazz) {
+    return Caches::getInstance().maxTextureSize;
+}
+
+static jint android_view_GLES20Canvas_getMaxTextureHeight(JNIEnv* env, jobject clazz) {
+    return Caches::getInstance().maxTextureSize;
+}
+
 // ----------------------------------------------------------------------------
 // State
 // ----------------------------------------------------------------------------
@@ -613,7 +633,7 @@
 
     if (layer) {
         jint* storage = env->GetIntArrayElements(layerInfo, NULL);
-        storage[0] = layer->texture;
+        storage[0] = layer->getTexture();
         env->ReleaseIntArrayElements(layerInfo, storage, 0);
     }
 
@@ -626,8 +646,8 @@
 
     if (layer) {
         jint* storage = env->GetIntArrayElements(layerInfo, NULL);
-        storage[0] = layer->width;
-        storage[1] = layer->height;
+        storage[0] = layer->getWidth();
+        storage[1] = layer->getHeight();
         env->ReleaseIntArrayElements(layerInfo, storage, 0);
     }
 
@@ -639,8 +659,8 @@
     LayerRenderer::resizeLayer(layer, width, height);
 
     jint* storage = env->GetIntArrayElements(layerInfo, NULL);
-    storage[0] = layer->width;
-    storage[1] = layer->height;
+    storage[0] = layer->getWidth();
+    storage[1] = layer->getHeight();
     env->ReleaseIntArrayElements(layerInfo, storage, 0);
 }
 
@@ -714,6 +734,7 @@
 #ifdef USE_OPENGL_RENDERER
     { "nIsBackBufferPreserved", "()Z",         (void*) android_view_GLES20Canvas_isBackBufferPreserved },
     { "nPreserveBackBuffer",    "()Z",         (void*) android_view_GLES20Canvas_preserveBackBuffer },
+    { "nDisableVsync",          "()V",         (void*) android_view_GLES20Canvas_disableVsync },
 
     { "nCreateRenderer",    "()I",             (void*) android_view_GLES20Canvas_createRenderer },
     { "nDestroyRenderer",   "(I)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
@@ -803,6 +824,9 @@
     { "nDrawLayer",              "(IIFFI)V",   (void*) android_view_GLES20Canvas_drawLayer },
     { "nCopyLayer",              "(II)Z",      (void*) android_view_GLES20Canvas_copyLayer },
 
+    { "nGetMaximumTextureWidth",  "()I",       (void*) android_view_GLES20Canvas_getMaxTextureWidth },
+    { "nGetMaximumTextureHeight", "()I",       (void*) android_view_GLES20Canvas_getMaxTextureHeight },
+
 #endif
 };
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 47902a8..49eaf19 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1384,7 +1384,7 @@
     <permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY"
         android:label="@string/permlab_readNetworkUsageHistory"
         android:description="@string/permdesc_readNetworkUsageHistory"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signatureOrSystem" />
 
     <!-- Allows an application to manage network policies (such as warning and disable
          limits) and to define application-specific rules. @hide -->
@@ -1393,6 +1393,14 @@
         android:description="@string/permdesc_manageNetworkPolicy"
         android:protectionLevel="signature" />
 
+    <!-- Allows an application to account its network traffic against other UIDs. Used
+         by system services like download manager and media server. Not for use by
+         third party apps. @hide -->
+    <permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING"
+        android:label="@string/permlab_modifyNetworkAccounting"
+        android:description="@string/permdesc_modifyNetworkAccounting"
+        android:protectionLevel="signatureOrSystem" />
+
     <!-- C2DM permission. 
          @hide Used internally.
      -->
@@ -1410,7 +1418,6 @@
                  android:label="@string/android_system_label"
                  android:allowClearUserData="false"
                  android:backupAgent="com.android.server.SystemBackupAgent"
-                 android:fullBackupAgent="com.android.server.SystemBackupAgent"
                  android:killAfterRestore="false"
                  android:icon="@drawable/ic_launcher_android">
         <activity android:name="com.android.internal.app.ChooserActivity"
diff --git a/core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.png
new file mode 100644
index 0000000..3ea6c44
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.png
new file mode 100644
index 0000000..6c6fcd2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.png
new file mode 100644
index 0000000..854631e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.png
new file mode 100644
index 0000000..aef6142d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.png
new file mode 100644
index 0000000..d8b5edc
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_solid_dark_holo.9.png
new file mode 100644
index 0000000..660a234
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_light_holo.9.png b/core/res/res/drawable-hdpi/ab_solid_light_holo.9.png
new file mode 100644
index 0000000..9756cf5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.png b/core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.png
new file mode 100644
index 0000000..80213d5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.png
new file mode 100644
index 0000000..6de2bf2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.png
new file mode 100644
index 0000000..c23e473
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.png
new file mode 100644
index 0000000..343d7c6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.png
new file mode 100644
index 0000000..3de1174
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.png
new file mode 100644
index 0000000..da8b042
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.png
new file mode 100644
index 0000000..1957c32
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_transparent_light_holo.9.png b/core/res/res/drawable-hdpi/ab_transparent_light_holo.9.png
new file mode 100644
index 0000000..0f1ce73
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png
deleted file mode 100644
index 1f7aeee..0000000
--- a/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_holo.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_holo.9.png
deleted file mode 100755
index 4c1d89d..0000000
--- a/core/res/res/drawable-hdpi/btn_toggle_on_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_pressed_holo_light.9.png
deleted file mode 100644
index 6963a0e..0000000
--- a/core/res/res/drawable-hdpi/btn_toggle_pressed_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_holo_dark.9.png b/core/res/res/drawable-hdpi/cab_holo_dark.9.png
deleted file mode 100755
index 64e2052..0000000
--- a/core/res/res/drawable-hdpi/cab_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo.9.png
deleted file mode 100644
index 3a84de9..0000000
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
index 5225a81..acbbb38 100644
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
index 2e7e973..6009528 100644
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
index 4591627..30727d7 100644
--- a/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
index 9cf1826..7cea5e1 100644
--- a/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
index a47ef40..ba0d612 100644
--- a/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
index 9b50c73..e8646b9 100644
--- a/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
index a0d36de..14cb4c9 100644
--- a/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
index 805b956..80fd218 100644
--- a/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png
index 7855cda..897a1c1 100644
--- a/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png
index c062773..0c89f71 100644
--- a/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_back.png b/core/res/res/drawable-hdpi/ic_btn_back.png
deleted file mode 100644
index f8b3285..0000000
--- a/core/res/res/drawable-hdpi/ic_btn_back.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_next.png b/core/res/res/drawable-hdpi/ic_btn_next.png
deleted file mode 100644
index b2c6e1b..0000000
--- a/core/res/res/drawable-hdpi/ic_btn_next.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
index e21a87c..0f4bfe6 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
index 3283f99..995705d 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_copy.png b/core/res/res/drawable-hdpi/ic_menu_copy.png
new file mode 100644
index 0000000..5dcc3a3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_copy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png
index 852f146..d1e1337 100644
--- a/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png
index ad09b37..5d02660 100644
--- a/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_cut.png b/core/res/res/drawable-hdpi/ic_menu_cut.png
new file mode 100644
index 0000000..03fac98
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_cut.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png
index 7716a94..bd28a85 100644
--- a/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png
index bea6db1..037c362 100644
--- a/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_find_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_find_holo_dark.png
index b888202..b981a4d 100644
--- a/core/res/res/drawable-hdpi/ic_menu_find_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_find_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_find_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_find_holo_light.png
index b888202..efee6df 100644
--- a/core/res/res/drawable-hdpi/ic_menu_find_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_find_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow.png
new file mode 100644
index 0000000..33bb5e76
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png
index 8563c1a..1e69eac 100644
--- a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png
index 1cd2384..2f6accc 100644
--- a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_paste.png b/core/res/res/drawable-hdpi/ic_menu_paste.png
new file mode 100644
index 0000000..c24fd86
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_paste.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png
index 5579443..e9514b8 100644
--- a/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png
index 6674914..b02aa09 100644
--- a/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_share_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_share_holo_dark.png
index 2837615..db011be 100644
--- a/core/res/res/drawable-hdpi/ic_menu_share_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_share_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_share_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_share_holo_light.png
index 2837615..d9a9a73 100644
--- a/core/res/res/drawable-hdpi/ic_menu_share_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_share_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
index b0fba52..1014d8a 100644
--- a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
index 3ef8935..18cd171 100644
--- a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_16.png b/core/res/res/drawable-hdpi/spinner_black_16.png
index eb34867..ef5ca35 100644
--- a/core/res/res/drawable-hdpi/spinner_black_16.png
+++ b/core/res/res/drawable-hdpi/spinner_black_16.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_20.png b/core/res/res/drawable-hdpi/spinner_black_20.png
index dac06d7..d938931 100644
--- a/core/res/res/drawable-hdpi/spinner_black_20.png
+++ b/core/res/res/drawable-hdpi/spinner_black_20.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_48.png b/core/res/res/drawable-hdpi/spinner_black_48.png
index 337f72a..9d1efb7 100644
--- a/core/res/res/drawable-hdpi/spinner_black_48.png
+++ b/core/res/res/drawable-hdpi/spinner_black_48.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_76.png b/core/res/res/drawable-hdpi/spinner_black_76.png
index 2edc3e7..0d90881 100644
--- a/core/res/res/drawable-hdpi/spinner_black_76.png
+++ b/core/res/res/drawable-hdpi/spinner_black_76.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_white_16.png b/core/res/res/drawable-hdpi/spinner_white_16.png
index 7914a68..32fa447 100644
--- a/core/res/res/drawable-hdpi/spinner_white_16.png
+++ b/core/res/res/drawable-hdpi/spinner_white_16.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_white_48.png b/core/res/res/drawable-hdpi/spinner_white_48.png
index faee8ca..31fa267 100644
--- a/core/res/res/drawable-hdpi/spinner_white_48.png
+++ b/core/res/res/drawable-hdpi/spinner_white_48.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_white_76.png b/core/res/res/drawable-hdpi/spinner_white_76.png
index cd26379..9f63292 100644
--- a/core/res/res/drawable-hdpi/spinner_white_76.png
+++ b/core/res/res/drawable-hdpi/spinner_white_76.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_default.9.png b/core/res/res/drawable-hdpi/textfield_default.9.png
old mode 100644
new mode 100755
index 4c20179..f7b6e99
--- a/core/res/res/drawable-hdpi/textfield_default.9.png
+++ b/core/res/res/drawable-hdpi/textfield_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled.9.png b/core/res/res/drawable-hdpi/textfield_disabled.9.png
old mode 100644
new mode 100755
index 81569d1..3011502
--- a/core/res/res/drawable-hdpi/textfield_disabled.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_selected.9.png b/core/res/res/drawable-hdpi/textfield_disabled_selected.9.png
old mode 100644
new mode 100755
index 2591490..e0f82eb
--- a/core/res/res/drawable-hdpi/textfield_disabled_selected.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_selected.9.png b/core/res/res/drawable-hdpi/textfield_selected.9.png
old mode 100644
new mode 100755
index a36ed72..cf2cae3
--- a/core/res/res/drawable-hdpi/textfield_selected.9.png
+++ b/core/res/res/drawable-hdpi/textfield_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/toast_frame.9.png b/core/res/res/drawable-hdpi/toast_frame.9.png
index 9769bbb..ad2cb5a 100644
--- a/core/res/res/drawable-hdpi/toast_frame.9.png
+++ b/core/res/res/drawable-hdpi/toast_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/toast_frame_holo.9.png b/core/res/res/drawable-hdpi/toast_frame_holo.9.png
index 9769bbb..ad2cb5a 100644
--- a/core/res/res/drawable-hdpi/toast_frame_holo.9.png
+++ b/core/res/res/drawable-hdpi/toast_frame_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.png
new file mode 100644
index 0000000..3807a48
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.png
new file mode 100644
index 0000000..9994438
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.png
new file mode 100644
index 0000000..5648403
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.png
new file mode 100644
index 0000000..261365d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.png
new file mode 100644
index 0000000..95df5fc
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_solid_dark_holo.9.png
new file mode 100644
index 0000000..4a6c3bc
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_light_holo.9.png b/core/res/res/drawable-mdpi/ab_solid_light_holo.9.png
new file mode 100644
index 0000000..93a0c3e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.png b/core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.png
new file mode 100644
index 0000000..f3abd07
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.png
new file mode 100644
index 0000000..e1d8f67
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.png
new file mode 100644
index 0000000..9d7e953
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.png
new file mode 100644
index 0000000..711e0fd
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.png
new file mode 100644
index 0000000..9649a2d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.png
new file mode 100644
index 0000000..376e4ef
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.png
new file mode 100644
index 0000000..99c8fd3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_transparent_light_holo.9.png b/core/res/res/drawable-mdpi/ab_transparent_light_holo.9.png
new file mode 100644
index 0000000..a86ec34
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png
deleted file mode 100644
index 48cc017..0000000
--- a/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_holo.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_holo.9.png
deleted file mode 100755
index 66cbe48..0000000
--- a/core/res/res/drawable-mdpi/btn_toggle_on_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_pressed_holo_light.9.png
deleted file mode 100644
index b6508fc..0000000
--- a/core/res/res/drawable-mdpi/btn_toggle_pressed_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_holo_dark.9.png b/core/res/res/drawable-mdpi/cab_holo_dark.9.png
deleted file mode 100755
index 7daae1f..0000000
--- a/core/res/res/drawable-mdpi/cab_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo.9.png
deleted file mode 100644
index cb3d0f2..0000000
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
index a0bd4e3..4836da1 100644
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
index 12abcd2..c299931 100644
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
index adb8104..86edad7 100644
--- a/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
index d7c6bbf..53ee68b 100644
--- a/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
index 42cfc52..606adaf 100644
--- a/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
index 9a08e15..14d2e5e 100644
--- a/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
index 5d86b2a..2646332 100644
--- a/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
index ad22f5b..48ec0a4 100644
--- a/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png
index ae3e6bf..df2d3d1 100644
--- a/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png
index c61e3fa..b2aa9c2 100644
--- a/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_back.png b/core/res/res/drawable-mdpi/ic_btn_back.png
deleted file mode 100644
index c9bff4c..0000000
--- a/core/res/res/drawable-mdpi/ic_btn_back.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_next.png b/core/res/res/drawable-mdpi/ic_btn_next.png
deleted file mode 100755
index c6cf436..0000000
--- a/core/res/res/drawable-mdpi/ic_btn_next.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
index c10344f..754d7bc 100644
--- a/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
index 08c6cfe..0187a02 100644
--- a/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_copy.png b/core/res/res/drawable-mdpi/ic_menu_copy.png
new file mode 100644
index 0000000..eee5540
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_menu_copy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png
index 35c3318..cb19fea 100644
--- a/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png
index 3b179d8..e353d46 100644
--- a/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_cut.png b/core/res/res/drawable-mdpi/ic_menu_cut.png
new file mode 100644
index 0000000..865d1e0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_menu_cut.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png
index dfe8b4a..66a750d 100644
--- a/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png
index 748dc9b..e7e8c54 100644
--- a/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_find_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_find_holo_dark.png
index 82dcba7..45f8fd3 100644
--- a/core/res/res/drawable-mdpi/ic_menu_find_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_find_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_find_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_find_holo_light.png
index 82dcba7..9033f1e 100644
--- a/core/res/res/drawable-mdpi/ic_menu_find_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_find_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow.png
new file mode 100644
index 0000000..e478922
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_dark.png
index c369e6f..48d6c78 100644
--- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_light.png
index a4df2bf..50ff8fc 100644
--- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png
index a7389c9..135ca6e 100644
--- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png
index 87e41ac..ccbf143 100644
--- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_paste.png b/core/res/res/drawable-mdpi/ic_menu_paste.png
new file mode 100644
index 0000000..8c9916c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_menu_paste.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png
index caec299..23f3a32 100644
--- a/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png
index 434f5d1..c9d571c 100644
--- a/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_share_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_share_holo_dark.png
old mode 100755
new mode 100644
index d89ca5f..306cac8
--- a/core/res/res/drawable-mdpi/ic_menu_share_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_share_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_share_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_share_holo_light.png
old mode 100755
new mode 100644
index d89ca5f..cc081ad
--- a/core/res/res/drawable-mdpi/ic_menu_share_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_share_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
index 923f92d..dd5dd39 100644
--- a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
index afada39..12d65be 100644
--- a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_16.png b/core/res/res/drawable-mdpi/spinner_black_16.png
index 5ee33ce..4b7fdfe 100644
--- a/core/res/res/drawable-mdpi/spinner_black_16.png
+++ b/core/res/res/drawable-mdpi/spinner_black_16.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_20.png b/core/res/res/drawable-mdpi/spinner_black_20.png
index e55b60d..86d7a20 100755
--- a/core/res/res/drawable-mdpi/spinner_black_20.png
+++ b/core/res/res/drawable-mdpi/spinner_black_20.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_48.png b/core/res/res/drawable-mdpi/spinner_black_48.png
index 3a68192..f1571f9 100644
--- a/core/res/res/drawable-mdpi/spinner_black_48.png
+++ b/core/res/res/drawable-mdpi/spinner_black_48.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_76.png b/core/res/res/drawable-mdpi/spinner_black_76.png
index ec57460..e9f6e8f 100644
--- a/core/res/res/drawable-mdpi/spinner_black_76.png
+++ b/core/res/res/drawable-mdpi/spinner_black_76.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_white_16.png b/core/res/res/drawable-mdpi/spinner_white_16.png
index dd2e1fd..650e315 100644
--- a/core/res/res/drawable-mdpi/spinner_white_16.png
+++ b/core/res/res/drawable-mdpi/spinner_white_16.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_white_48.png b/core/res/res/drawable-mdpi/spinner_white_48.png
index d25a33e..11eacf8 100644
--- a/core/res/res/drawable-mdpi/spinner_white_48.png
+++ b/core/res/res/drawable-mdpi/spinner_white_48.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_white_76.png b/core/res/res/drawable-mdpi/spinner_white_76.png
index f53e8ff..6c31bc3 100644
--- a/core/res/res/drawable-mdpi/spinner_white_76.png
+++ b/core/res/res/drawable-mdpi/spinner_white_76.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_default.9.png b/core/res/res/drawable-mdpi/textfield_default.9.png
index cc78e6c..1a59bb2 100644
--- a/core/res/res/drawable-mdpi/textfield_default.9.png
+++ b/core/res/res/drawable-mdpi/textfield_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled.9.png b/core/res/res/drawable-mdpi/textfield_disabled.9.png
index 9c77149..800205a 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_selected.9.png b/core/res/res/drawable-mdpi/textfield_disabled_selected.9.png
index 6d47708..59e1536 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_selected.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_selected.9.png b/core/res/res/drawable-mdpi/textfield_selected.9.png
index 0c1b446..faadace 100644
--- a/core/res/res/drawable-mdpi/textfield_selected.9.png
+++ b/core/res/res/drawable-mdpi/textfield_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/toast_frame.9.png b/core/res/res/drawable-mdpi/toast_frame.9.png
index 06cfc70..b9105de 100755
--- a/core/res/res/drawable-mdpi/toast_frame.9.png
+++ b/core/res/res/drawable-mdpi/toast_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/toast_frame_holo.9.png b/core/res/res/drawable-mdpi/toast_frame_holo.9.png
index 06cfc70..b9105de 100755
--- a/core/res/res/drawable-mdpi/toast_frame_holo.9.png
+++ b/core/res/res/drawable-mdpi/toast_frame_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.png
new file mode 100644
index 0000000..462e0e0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.png
new file mode 100644
index 0000000..939ff4e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.png
new file mode 100644
index 0000000..8f89040
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.png
new file mode 100644
index 0000000..ccd53a3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.png
new file mode 100644
index 0000000..0b1ae2d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.png
new file mode 100644
index 0000000..c8e5efc4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_solid_light_holo.9.png
new file mode 100644
index 0000000..6cb8a0e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.png b/core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.png
new file mode 100644
index 0000000..49b2669
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.png
new file mode 100644
index 0000000..201e21d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.png
new file mode 100644
index 0000000..ac96200
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.png
new file mode 100644
index 0000000..d605d96
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.png
new file mode 100644
index 0000000..8ece2a9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png
new file mode 100644
index 0000000..ae0b6b7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.png
new file mode 100644
index 0000000..d3a3809
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.png
new file mode 100644
index 0000000..7e6e24d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
index b33e117..077e4d3 100644
--- a/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
index d84d427..357c17f 100644
--- a/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
index 9c0ff47..5b51072 100644
--- a/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
index 331a4f2..2705a39 100644
--- a/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
index cdc887d..101876f 100644
--- a/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
index bdb6824..0df1503 100644
--- a/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
index 600efb3..344a4e2 100644
--- a/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
index aa8401d..249848f 100644
--- a/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-xhdpi/ic_ab_back_holo_dark.png
new file mode 100644
index 0000000..8ded62f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_ab_back_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-xhdpi/ic_ab_back_holo_light.png
new file mode 100644
index 0000000..517e9f7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_ab_back_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png
new file mode 100644
index 0000000..544924e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png
new file mode 100644
index 0000000..2d28009
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_account_list.png b/core/res/res/drawable-xhdpi/ic_menu_account_list.png
new file mode 100644
index 0000000..ebe29b9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_account_list.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_add.png b/core/res/res/drawable-xhdpi/ic_menu_add.png
new file mode 100644
index 0000000..7d498a9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_add.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_agenda.png b/core/res/res/drawable-xhdpi/ic_menu_agenda.png
new file mode 100644
index 0000000..25e9f11
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_agenda.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_allfriends.png b/core/res/res/drawable-xhdpi/ic_menu_allfriends.png
new file mode 100644
index 0000000..20994ed
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_allfriends.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_always_landscape_portrait.png b/core/res/res/drawable-xhdpi/ic_menu_always_landscape_portrait.png
new file mode 100644
index 0000000..96606de
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_always_landscape_portrait.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_archive.png b/core/res/res/drawable-xhdpi/ic_menu_archive.png
new file mode 100644
index 0000000..b1be9d5
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_archive.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_attachment.png b/core/res/res/drawable-xhdpi/ic_menu_attachment.png
new file mode 100644
index 0000000..aa41bd6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_attachment.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_back.png b/core/res/res/drawable-xhdpi/ic_menu_back.png
new file mode 100644
index 0000000..8ac4f64
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_back.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_block.png b/core/res/res/drawable-xhdpi/ic_menu_block.png
new file mode 100644
index 0000000..e672395
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_block.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_blocked_user.png b/core/res/res/drawable-xhdpi/ic_menu_blocked_user.png
new file mode 100644
index 0000000..53a279e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_blocked_user.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_btn_add.png b/core/res/res/drawable-xhdpi/ic_menu_btn_add.png
new file mode 100644
index 0000000..7d498a9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_btn_add.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_call.png b/core/res/res/drawable-xhdpi/ic_menu_call.png
new file mode 100644
index 0000000..703a76b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_call.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_camera.png b/core/res/res/drawable-xhdpi/ic_menu_camera.png
new file mode 100644
index 0000000..7875aa3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_camera.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_cc.png b/core/res/res/drawable-xhdpi/ic_menu_cc.png
new file mode 100644
index 0000000..50d686a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_cc.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_chat_dashboard.png b/core/res/res/drawable-xhdpi/ic_menu_chat_dashboard.png
new file mode 100644
index 0000000..c0b238c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_chat_dashboard.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_clear_playlist.png b/core/res/res/drawable-xhdpi/ic_menu_clear_playlist.png
new file mode 100644
index 0000000..8981d6f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_clear_playlist.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_close_clear_cancel.png b/core/res/res/drawable-xhdpi/ic_menu_close_clear_cancel.png
new file mode 100644
index 0000000..d743d75
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_close_clear_cancel.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_compass.png b/core/res/res/drawable-xhdpi/ic_menu_compass.png
new file mode 100644
index 0000000..1c2ad89
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_compass.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_compose.png b/core/res/res/drawable-xhdpi/ic_menu_compose.png
new file mode 100644
index 0000000..bef190e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_compose.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_copy.png b/core/res/res/drawable-xhdpi/ic_menu_copy.png
new file mode 100644
index 0000000..22761fc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_copy.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_copy_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_dark.png
new file mode 100644
index 0000000..8014345
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_copy_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_light.png
new file mode 100644
index 0000000..b5359a1
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_crop.png b/core/res/res/drawable-xhdpi/ic_menu_crop.png
new file mode 100644
index 0000000..d32daae
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_crop.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_cut.png b/core/res/res/drawable-xhdpi/ic_menu_cut.png
new file mode 100644
index 0000000..efefcde
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_cut.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png
new file mode 100644
index 0000000..180365f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png
new file mode 100644
index 0000000..a31a06f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_day.png b/core/res/res/drawable-xhdpi/ic_menu_day.png
new file mode 100644
index 0000000..9eed1b2
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_day.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_delete.png b/core/res/res/drawable-xhdpi/ic_menu_delete.png
new file mode 100644
index 0000000..65b9cae
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_delete.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_directions.png b/core/res/res/drawable-xhdpi/ic_menu_directions.png
new file mode 100644
index 0000000..bdc0088
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_directions.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_edit.png b/core/res/res/drawable-xhdpi/ic_menu_edit.png
new file mode 100644
index 0000000..fcdd71e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_edit.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_emoticons.png b/core/res/res/drawable-xhdpi/ic_menu_emoticons.png
new file mode 100644
index 0000000..af730fa
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_emoticons.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_end_conversation.png b/core/res/res/drawable-xhdpi/ic_menu_end_conversation.png
new file mode 100644
index 0000000..ac76f3b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_end_conversation.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_find.png b/core/res/res/drawable-xhdpi/ic_menu_find.png
new file mode 100644
index 0000000..ccf2aab
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_find.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_find_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_find_holo_dark.png
new file mode 100644
index 0000000..3ede9e2
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_find_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_find_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_find_holo_light.png
new file mode 100644
index 0000000..de20fa0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_find_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_forward.png b/core/res/res/drawable-xhdpi/ic_menu_forward.png
new file mode 100644
index 0000000..6463e7a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_forward.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_friendslist.png b/core/res/res/drawable-xhdpi/ic_menu_friendslist.png
new file mode 100644
index 0000000..9200f87
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_friendslist.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_gallery.png b/core/res/res/drawable-xhdpi/ic_menu_gallery.png
new file mode 100644
index 0000000..6b21e22
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_gallery.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_goto.png b/core/res/res/drawable-xhdpi/ic_menu_goto.png
new file mode 100644
index 0000000..b925e69
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_goto.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_help.png b/core/res/res/drawable-xhdpi/ic_menu_help.png
new file mode 100644
index 0000000..128c7e8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_help_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_help_holo_light.png
new file mode 100644
index 0000000..b961de9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_help_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_home.png b/core/res/res/drawable-xhdpi/ic_menu_home.png
new file mode 100644
index 0000000..689f372
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_home.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_info_details.png b/core/res/res/drawable-xhdpi/ic_menu_info_details.png
new file mode 100644
index 0000000..24ea543
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_info_details.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_invite.png b/core/res/res/drawable-xhdpi/ic_menu_invite.png
new file mode 100644
index 0000000..d594607
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_invite.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_login.png b/core/res/res/drawable-xhdpi/ic_menu_login.png
new file mode 100644
index 0000000..5095ed9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_login.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_manage.png b/core/res/res/drawable-xhdpi/ic_menu_manage.png
new file mode 100644
index 0000000..d743624
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_manage.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_mapmode.png b/core/res/res/drawable-xhdpi/ic_menu_mapmode.png
new file mode 100644
index 0000000..0b62d08
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_mapmode.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_mark.png b/core/res/res/drawable-xhdpi/ic_menu_mark.png
new file mode 100644
index 0000000..a5de6fb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_mark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_month.png b/core/res/res/drawable-xhdpi/ic_menu_month.png
new file mode 100644
index 0000000..099263b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_month.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_more.png b/core/res/res/drawable-xhdpi/ic_menu_more.png
new file mode 100644
index 0000000..c7a6538
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_more.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow.png
new file mode 100644
index 0000000..2998d65
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_dark.png
new file mode 100644
index 0000000..62659fa
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_light.png
new file mode 100644
index 0000000..341edaf
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png
new file mode 100644
index 0000000..81306ca
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png
new file mode 100644
index 0000000..1f46e7a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_my_calendar.png b/core/res/res/drawable-xhdpi/ic_menu_my_calendar.png
new file mode 100644
index 0000000..ca95b92
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_my_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_mylocation.png b/core/res/res/drawable-xhdpi/ic_menu_mylocation.png
new file mode 100644
index 0000000..b0a76a2
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_mylocation.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_myplaces.png b/core/res/res/drawable-xhdpi/ic_menu_myplaces.png
new file mode 100644
index 0000000..205848e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_myplaces.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_notifications.png b/core/res/res/drawable-xhdpi/ic_menu_notifications.png
new file mode 100644
index 0000000..db80b57
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_notifications.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_paste.png b/core/res/res/drawable-xhdpi/ic_menu_paste.png
new file mode 100644
index 0000000..a69f0eb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_paste.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_paste_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_dark.png
new file mode 100644
index 0000000..6e7273f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_paste_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_light.png
new file mode 100644
index 0000000..b7eedd9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_play_clip.png b/core/res/res/drawable-xhdpi/ic_menu_play_clip.png
new file mode 100644
index 0000000..f680fce
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_play_clip.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_preferences.png b/core/res/res/drawable-xhdpi/ic_menu_preferences.png
new file mode 100644
index 0000000..02cfbad
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_preferences.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_recent_history.png b/core/res/res/drawable-xhdpi/ic_menu_recent_history.png
new file mode 100644
index 0000000..fc5e1fc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_recent_history.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_refresh.png b/core/res/res/drawable-xhdpi/ic_menu_refresh.png
new file mode 100644
index 0000000..9e9f10e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_refresh.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_report_image.png b/core/res/res/drawable-xhdpi/ic_menu_report_image.png
new file mode 100644
index 0000000..26f7ff4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_report_image.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_revert.png b/core/res/res/drawable-xhdpi/ic_menu_revert.png
new file mode 100644
index 0000000..19c580f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_revert.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_rotate.png b/core/res/res/drawable-xhdpi/ic_menu_rotate.png
new file mode 100644
index 0000000..98e19fe
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_rotate.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_save.png b/core/res/res/drawable-xhdpi/ic_menu_save.png
new file mode 100644
index 0000000..62a66d8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_save.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_search.png b/core/res/res/drawable-xhdpi/ic_menu_search.png
new file mode 100644
index 0000000..5c18f9e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_search.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_search_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_search_holo_dark.png
new file mode 100644
index 0000000..d49c7e2
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_search_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_search_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_search_holo_light.png
new file mode 100644
index 0000000..578cb24
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_search_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_dark.png
new file mode 100644
index 0000000..7125557
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_light.png
new file mode 100644
index 0000000..c7728d4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_send.png b/core/res/res/drawable-xhdpi/ic_menu_send.png
new file mode 100644
index 0000000..6e5ec78
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_send.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_set_as.png b/core/res/res/drawable-xhdpi/ic_menu_set_as.png
new file mode 100644
index 0000000..8689766
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_set_as.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_settings_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_settings_holo_light.png
new file mode 100644
index 0000000..aa33c38
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_settings_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_share.png b/core/res/res/drawable-xhdpi/ic_menu_share.png
new file mode 100644
index 0000000..fce1d35
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_share.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_share_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_share_holo_dark.png
new file mode 100644
index 0000000..af72732
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_share_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_share_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_share_holo_light.png
new file mode 100644
index 0000000..79c162f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_share_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_slideshow.png b/core/res/res/drawable-xhdpi/ic_menu_slideshow.png
new file mode 100644
index 0000000..8740f37
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_slideshow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_sort_alphabetically.png b/core/res/res/drawable-xhdpi/ic_menu_sort_alphabetically.png
new file mode 100644
index 0000000..5736ff8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_sort_alphabetically.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_sort_by_size.png b/core/res/res/drawable-xhdpi/ic_menu_sort_by_size.png
new file mode 100644
index 0000000..fe3836c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_sort_by_size.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_star.png b/core/res/res/drawable-xhdpi/ic_menu_star.png
new file mode 100644
index 0000000..c051020
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_star.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_start_conversation.png b/core/res/res/drawable-xhdpi/ic_menu_start_conversation.png
new file mode 100644
index 0000000..d71ed17
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_start_conversation.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_stop.png b/core/res/res/drawable-xhdpi/ic_menu_stop.png
new file mode 100644
index 0000000..855af11
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_stop.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_today.png b/core/res/res/drawable-xhdpi/ic_menu_today.png
new file mode 100644
index 0000000..e9ebc5e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_today.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_upload.png b/core/res/res/drawable-xhdpi/ic_menu_upload.png
new file mode 100644
index 0000000..94d1478
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_upload.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_upload_you_tube.png b/core/res/res/drawable-xhdpi/ic_menu_upload_you_tube.png
new file mode 100644
index 0000000..508c354
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_upload_you_tube.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_view.png b/core/res/res/drawable-xhdpi/ic_menu_view.png
new file mode 100644
index 0000000..e97c30df
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_view.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_week.png b/core/res/res/drawable-xhdpi/ic_menu_week.png
new file mode 100644
index 0000000..2c3e761
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_week.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_zoom.png b/core/res/res/drawable-xhdpi/ic_menu_zoom.png
new file mode 100644
index 0000000..858aef5
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_zoom.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png
new file mode 100644
index 0000000..92acc47
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png
new file mode 100644
index 0000000..4e54b4b6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_bottom_bright.9.png b/core/res/res/drawable-xhdpi/popup_bottom_bright.9.png
new file mode 100644
index 0000000..cdc0afb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_bottom_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_bottom_dark.9.png b/core/res/res/drawable-xhdpi/popup_bottom_dark.9.png
new file mode 100644
index 0000000..36b0448
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_bottom_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_bottom_medium.9.png b/core/res/res/drawable-xhdpi/popup_bottom_medium.9.png
new file mode 100644
index 0000000..3a7a8b3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_bottom_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_center_bright.9.png b/core/res/res/drawable-xhdpi/popup_center_bright.9.png
new file mode 100644
index 0000000..b1a8e3e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_center_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_center_dark.9.png b/core/res/res/drawable-xhdpi/popup_center_dark.9.png
new file mode 100644
index 0000000..87378e1
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_center_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_center_medium.9.png b/core/res/res/drawable-xhdpi/popup_center_medium.9.png
new file mode 100644
index 0000000..ea29ed4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_center_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_full_bright.9.png b/core/res/res/drawable-xhdpi/popup_full_bright.9.png
new file mode 100644
index 0000000..114faa0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_full_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_full_dark.9.png b/core/res/res/drawable-xhdpi/popup_full_dark.9.png
new file mode 100644
index 0000000..996beaa
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_full_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_top_bright.9.png b/core/res/res/drawable-xhdpi/popup_top_bright.9.png
new file mode 100644
index 0000000..64e4139
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_top_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_top_dark.9.png b/core/res/res/drawable-xhdpi/popup_top_dark.9.png
new file mode 100644
index 0000000..902bc29
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_top_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_black_16.png b/core/res/res/drawable-xhdpi/spinner_black_16.png
new file mode 100644
index 0000000..5b1422c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_black_16.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_black_20.png b/core/res/res/drawable-xhdpi/spinner_black_20.png
new file mode 100644
index 0000000..5f53e38
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_black_20.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_black_48.png b/core/res/res/drawable-xhdpi/spinner_black_48.png
new file mode 100644
index 0000000..3aab620
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_black_48.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_black_76.png b/core/res/res/drawable-xhdpi/spinner_black_76.png
new file mode 100644
index 0000000..2968d8c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_black_76.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_white_16.png b/core/res/res/drawable-xhdpi/spinner_white_16.png
new file mode 100644
index 0000000..69be752
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_white_16.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_white_48.png b/core/res/res/drawable-xhdpi/spinner_white_48.png
new file mode 100644
index 0000000..7b196bc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_white_48.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_white_76.png b/core/res/res/drawable-xhdpi/spinner_white_76.png
new file mode 100644
index 0000000..ba47005
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_white_76.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/toast_frame.9.png b/core/res/res/drawable-xhdpi/toast_frame.9.png
index f7debee..9f39a77 100644
--- a/core/res/res/drawable-xhdpi/toast_frame.9.png
+++ b/core/res/res/drawable-xhdpi/toast_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/toast_frame_holo.9.png b/core/res/res/drawable-xhdpi/toast_frame_holo.9.png
index f7debee..9f39a77 100644
--- a/core/res/res/drawable-xhdpi/toast_frame_holo.9.png
+++ b/core/res/res/drawable-xhdpi/toast_frame_holo.9.png
Binary files differ
diff --git a/core/res/res/layout-land/ssl_certificate.xml b/core/res/res/layout-land/ssl_certificate.xml
new file mode 100644
index 0000000..4f8bd8e
--- /dev/null
+++ b/core/res/res/layout-land/ssl_certificate.xml
@@ -0,0 +1,280 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<ScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" >
+
+    <LinearLayout
+        android:id="@+id/body"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="left"
+        android:orientation="vertical" >
+
+        <!-- Placeholder for the success message or one or more warnings -->
+        <LinearLayout
+            android:id="@+id/placeholder"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginTop="12dip"
+            android:orientation="vertical" />
+
+        <!-- Dialog-title line separator -->
+        <ImageView
+            android:id="@+id/title_separator"
+            android:src="@android:drawable/divider_horizontal_dark"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:scaleType="fitXY"
+            android:layout_weight="1"
+            android:gravity="fill_horizontal"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"/>
+
+        <TableLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:shrinkColumns="1"
+            android:orientation="vertical">
+
+            <!-- Issued to: -->
+            <TextView
+                android:id="@+id/issued_to_header"
+                android:text="@string/issued_to"
+                android:textStyle="bold"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent"
+                android:layout_marginTop="12dip"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="7dip" />
+
+            <!-- Common name: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/to_common_header"
+                    android:text="@string/common_name"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/to_common"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+            </TableRow>
+
+            <!-- Organization: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/to_org_header"
+                    android:text="@string/org_name"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/to_org"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+            </TableRow>
+
+            <!-- Organizational unit: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/to_org_unit_header"
+                    android:text="@string/org_unit"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/to_org_unit"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+            </TableRow>
+
+            <!-- Serial number: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/serial_number_header"
+                    android:text="@string/serial_number"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/serial_number"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+            </TableRow>
+
+            <!-- Issued by: -->
+            <TextView
+                android:id="@+id/issued_to_header"
+                android:text="@string/issued_by"
+                android:textStyle="bold"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent"
+                android:layout_marginTop="12dip"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="7dip" />
+
+            <!-- Common name: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/by_common_header"
+                    android:text="@string/common_name"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/by_common"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+            </TableRow>
+
+            <!-- Organization: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/by_org_header"
+                    android:text="@string/org_name"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/by_org"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+            </TableRow>
+
+            <!-- Organizational unit: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/by_org_unit_header"
+                    android:text="@string/org_unit"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/by_org_unit"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+            </TableRow>
+
+            <!-- Validity Dates: -->
+            <TextView
+                android:id="@+id/validity_header"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent"
+                android:text="@string/validity_period"
+                android:textStyle="bold"
+                android:layout_marginTop="12dip"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="7dip" />
+
+            <!-- Issued On: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/issued_on_header"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/issued_on"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/issued_on"
+                    android:layout_height="wrap_content"
+                    android:layout_width="match_parent"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+
+            </TableRow>
+
+            <!-- Expires On: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/expires_on_header"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/expires_on"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/expires_on"
+                    android:layout_height="wrap_content"
+                    android:layout_width="match_parent"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+            </TableRow>
+
+            <!-- Fingerprints: -->
+            <TextView
+                android:id="@+id/fingerprints"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent"
+                android:text="@string/fingerprints"
+                android:textStyle="bold"
+                android:layout_marginTop="12dip"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:layout_marginBottom="7dip" />
+
+            <!-- SHA-256 fingerprint: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/sha256_fingerprint_header"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/sha256_fingerprint"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/sha256_fingerprint"
+                    android:layout_height="wrap_content"
+                    android:layout_width="match_parent"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+
+            </TableRow>
+
+            <!-- SHA-1 fingerprint: -->
+            <TableRow>
+                <TextView
+                    android:id="@+id/sha1_fingerprint_header"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/sha1_fingerprint"
+                    android:layout_marginLeft="20dip" />
+
+                <TextView
+                    android:id="@+id/sha1_fingerprint"
+                    android:layout_height="wrap_content"
+                    android:layout_width="match_parent"
+                    android:layout_marginLeft="10dip"
+                    android:layout_marginRight="20dip"
+                    android:layout_marginBottom="7dip" />
+
+            </TableRow>
+
+        </TableLayout>
+
+    </LinearLayout>
+
+</ScrollView>
diff --git a/core/res/res/layout-sw600dp/date_picker_dialog.xml b/core/res/res/layout-sw600dp/date_picker_dialog.xml
new file mode 100644
index 0000000..004d52a
--- /dev/null
+++ b/core/res/res/layout-sw600dp/date_picker_dialog.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/datePicker"
+    android:layout_gravity="center_horizontal"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    />
diff --git a/core/res/res/layout-sw600dp/number_picker.xml b/core/res/res/layout-sw600dp/number_picker.xml
new file mode 100644
index 0000000..807daf2
--- /dev/null
+++ b/core/res/res/layout-sw600dp/number_picker.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2008, 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.
+*/
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <ImageButton android:id="@+id/increment"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        style="?android:attr/numberPickerUpButtonStyle"
+        android:contentDescription="@string/number_picker_increment_button" />
+
+    <EditText android:id="@+id/numberpicker_input"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        style="?android:attr/numberPickerInputTextStyle" />
+
+    <ImageButton android:id="@+id/decrement"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        style="?android:attr/numberPickerDownButtonStyle"
+        android:contentDescription="@string/number_picker_decrement_button" />
+
+</merge>
diff --git a/core/res/res/layout-sw600dp/preference_list_content.xml b/core/res/res/layout-sw600dp/preference_list_content.xml
index 5a345c6..a5320a7 100644
--- a/core/res/res/layout-sw600dp/preference_list_content.xml
+++ b/core/res/res/layout-sw600dp/preference_list_content.xml
@@ -87,7 +87,6 @@
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
         android:layout_weight="0"
-        android:background="@android:drawable/bottom_bar"
         android:visibility="gone">
 
         <Button android:id="@+id/back_button"
@@ -95,8 +94,6 @@
             android:layout_height="wrap_content"
             android:layout_margin="5dip"
             android:layout_alignParentLeft="true"
-            android:drawableLeft="@drawable/ic_btn_back"
-            android:drawablePadding="3dip"
             android:text="@string/back_button_label"
         />
         <LinearLayout
@@ -117,8 +114,6 @@
                 android:layout_width="150dip"
                 android:layout_height="wrap_content"
                 android:layout_margin="5dip"
-                android:drawableRight="@drawable/ic_btn_next"
-                android:drawablePadding="3dip"
                 android:text="@string/next_button_label"
             />
         </LinearLayout>
diff --git a/core/res/res/layout-w600dp/preference_list_content_single.xml b/core/res/res/layout-w600dp/preference_list_content_single.xml
index 6725996..bbad296 100644
--- a/core/res/res/layout-w600dp/preference_list_content_single.xml
+++ b/core/res/res/layout-w600dp/preference_list_content_single.xml
@@ -61,7 +61,6 @@
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
         android:layout_weight="0"
-        android:background="@android:drawable/bottom_bar"
         android:visibility="gone">
 
         <Button android:id="@+id/back_button"
@@ -69,8 +68,6 @@
             android:layout_height="wrap_content"
             android:layout_margin="5dip"
             android:layout_alignParentLeft="true"
-            android:drawableLeft="@drawable/ic_btn_back"
-            android:drawablePadding="3dip"
             android:text="@string/back_button_label"
         />
         <LinearLayout
@@ -91,8 +88,6 @@
                 android:layout_width="150dip"
                 android:layout_height="wrap_content"
                 android:layout_margin="5dip"
-                android:drawableRight="@drawable/ic_btn_next"
-                android:drawablePadding="3dip"
                 android:text="@string/next_button_label"
             />
         </LinearLayout>
diff --git a/core/res/res/layout-xlarge/activity_list.xml b/core/res/res/layout-xlarge/activity_list.xml
index ad485c1..5093a5e 100644
--- a/core/res/res/layout-xlarge/activity_list.xml
+++ b/core/res/res/layout-xlarge/activity_list.xml
@@ -54,21 +54,15 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content" />
         </LinearLayout>
-        <ImageView android:id="@+id/titleDivider"
+        <View android:id="@+id/titleDivider"
             android:layout_width="match_parent"
-            android:layout_height="4dip"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
-            android:scaleType="fitXY"
-            android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_strong_holo" />
+            android:layout_height="2dip"
+            android:background="@android:color/holo_blue_light" />
         <!-- If the client uses a customTitle, it will be added here. -->
     </LinearLayout>
 
     <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
-        android:layout_marginLeft="32dip"
-        android:layout_marginRight="32dip"
         android:layout_height="0dip"
         android:layout_weight="1">
 
@@ -95,15 +89,12 @@
         android:minHeight="54dip"
         android:orientation="vertical"
         android:divider="?android:attr/dividerHorizontal"
-        android:showDividers="beginning"
-        android:dividerPadding="16dip">
+        android:showDividers="beginning">
         <LinearLayout
             style="?android:attr/buttonBarStyle"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:paddingLeft="2dip"
-            android:paddingRight="2dip"
             android:measureWithLargestChild="true">
             <LinearLayout android:id="@+id/leftSpacer"
                 android:layout_weight="0.25"
diff --git a/core/res/res/layout/action_menu_item_layout.xml b/core/res/res/layout/action_menu_item_layout.xml
index a8f0c22..dca6c52 100644
--- a/core/res/res/layout/action_menu_item_layout.xml
+++ b/core/res/res/layout/action_menu_item_layout.xml
@@ -21,8 +21,8 @@
     android:addStatesFromChildren="true"
     android:gravity="center"
     android:focusable="true"
-    android:paddingLeft="12dip"
-    android:paddingRight="12dip"
+    android:paddingLeft="4dip"
+    android:paddingRight="4dip"
     style="?android:attr/actionButtonStyle">
     <ImageButton android:id="@+id/imageButton"
                  android:layout_width="wrap_content"
@@ -45,6 +45,8 @@
             android:textAppearance="?attr/actionMenuTextAppearance"
             style="?attr/buttonStyleSmall"
             android:textColor="?attr/actionMenuTextColor"
+            android:singleLine="true"
+            android:ellipsize="none"
             android:background="@null"
             android:paddingTop="4dip"
             android:paddingBottom="4dip"
diff --git a/core/res/res/layout/activity_chooser_list_footer.xml b/core/res/res/layout/activity_chooser_list_footer.xml
new file mode 100644
index 0000000..c05ba1a
--- /dev/null
+++ b/core/res/res/layout/activity_chooser_list_footer.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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/list_footer"
+    android:paddingLeft="16dip"
+    android:paddingRight="16dip"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    android:orientation="vertical">
+
+    <View
+        android:id="@+id/divider"
+        android:layout_width="match_parent"
+        android:layout_height="2dip"
+        android:background="@android:color/holo_blue_light" />
+
+    <TextView
+        android:id="@+id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="48dip"
+        android:gravity="center"
+        android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
+        android:duplicateParentState="true"
+        android:singleLine="true"
+        android:text="@string/activity_chooser_view_see_all" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/activity_chooser_list_header.xml b/core/res/res/layout/activity_chooser_list_header.xml
new file mode 100644
index 0000000..0fb256f
--- /dev/null
+++ b/core/res/res/layout/activity_chooser_list_header.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/list_header"
+    android:paddingLeft="16dip"
+    android:paddingRight="16dip"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:gravity="center"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="?android:attr/dropdownListPreferredItemHeight"
+        android:gravity="center"
+        android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
+        android:duplicateParentState="true"
+        android:singleLine="true" />
+
+    <View
+        android:id="@+id/divider"
+        android:layout_width="match_parent"
+        android:layout_height="2dip"
+        android:src="@drawable/divider_strong_holo" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/activity_chooser_view.xml b/core/res/res/layout/activity_chooser_view.xml
new file mode 100644
index 0000000..ccf49fc
--- /dev/null
+++ b/core/res/res/layout/activity_chooser_view.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/activity_chooser_view_content"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    style="?android:attr/actionButtonStyle">
+
+    <ImageButton android:id="@+id/default_activity_button"
+        android:layout_width="32dip"
+        android:layout_height="32dip"
+        android:layout_marginLeft="16dip" />
+
+    <ImageButton android:id="@+id/expand_activities_button"
+        android:layout_width="32dip"
+        android:layout_height="32dip"
+        android:layout_marginLeft="16dip" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/activity_chooser_view_list_item.xml b/core/res/res/layout/activity_chooser_view_list_item.xml
new file mode 100644
index 0000000..61b7e70
--- /dev/null
+++ b/core/res/res/layout/activity_chooser_view_list_item.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/list_item"
+    android:layout_width="match_parent"
+    android:layout_height="?android:attr/dropdownListPreferredItemHeight"
+    android:gravity="center_vertical"
+    android:paddingLeft="16dip"
+    android:paddingRight="16dip">
+
+    <ImageView
+        android:id="@+id/icon"
+        android:layout_width="32dip"
+        android:layout_height="32dip"
+        android:layout_gravity="center_vertical"
+        android:layout_marginRight="8dip"
+        android:duplicateParentState="true" />
+
+    <TextView
+        android:id="@+id/title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
+        android:singleLine="true"
+        android:duplicateParentState="true"
+        android:ellipsize="marquee"
+        android:fadingEdge="horizontal" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/alert_dialog_holo.xml b/core/res/res/layout/alert_dialog_holo.xml
index 2185467..2b686bd 100644
--- a/core/res/res/layout/alert_dialog_holo.xml
+++ b/core/res/res/layout/alert_dialog_holo.xml
@@ -30,13 +30,11 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical">
-        <ImageView android:id="@+id/titleDividerTop"
+        <View android:id="@+id/titleDividerTop"
             android:layout_width="match_parent"
-            android:layout_height="1dip"
+            android:layout_height="2dip"
             android:visibility="gone"
-            android:scaleType="fitXY"
-            android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_strong_holo" />
+            android:background="@android:color/holo_blue_light" />
         <LinearLayout android:id="@+id/title_template"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -51,20 +49,17 @@
                 android:paddingRight="8dip"
                 android:src="@null" />
             <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
-                style="?android:attr/textAppearanceLarge"
-                android:textColor="@android:color/holo_blue"
+                style="?android:attr/windowTitleStyle"
                 android:singleLine="true"
                 android:ellipsize="end"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content" />
         </LinearLayout>
-        <ImageView android:id="@+id/titleDivider"
+        <View android:id="@+id/titleDivider"
             android:layout_width="match_parent"
-            android:layout_height="1dip"
+            android:layout_height="2dip"
             android:visibility="gone"
-            android:scaleType="fitXY"
-            android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_strong_holo" />
+            android:background="@android:color/holo_blue_light" />
         <!-- If the client uses a customTitle, it will be added here. -->
     </LinearLayout>
 
diff --git a/core/res/res/layout/date_picker_dialog.xml b/core/res/res/layout/date_picker_dialog.xml
index 004d52a..db8f311 100644
--- a/core/res/res/layout/date_picker_dialog.xml
+++ b/core/res/res/layout/date_picker_dialog.xml
@@ -22,4 +22,6 @@
     android:layout_gravity="center_horizontal"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
+    android:spinnersShown="true"
+    android:calendarViewShown="false"
     />
diff --git a/core/res/res/layout/date_picker_holo.xml b/core/res/res/layout/date_picker_holo.xml
index 026cbfb..8627637 100644
--- a/core/res/res/layout/date_picker_holo.xml
+++ b/core/res/res/layout/date_picker_holo.xml
@@ -77,7 +77,8 @@
         android:id="@+id/calendar_view"
         android:layout_width="245dip"
         android:layout_height="280dip"
-        android:layout_marginLeft="22dip"
+        android:layout_marginLeft="16dip"
+        android:layout_marginRight="16dip"
         android:layout_weight="1"
         android:focusable="true"
         android:focusableInTouchMode="true"
diff --git a/core/res/res/layout/dialog_custom_title_holo.xml b/core/res/res/layout/dialog_custom_title_holo.xml
index 5261553..e2335a7 100644
--- a/core/res/res/layout/dialog_custom_title_holo.xml
+++ b/core/res/res/layout/dialog_custom_title_holo.xml
@@ -28,12 +28,10 @@
         android:gravity="center_vertical|left"
         style="?android:attr/windowTitleBackgroundStyle">
     </FrameLayout>
-    <ImageView android:id="@+id/titleDivider"
+    <View android:id="@+id/titleDivider"
             android:layout_width="match_parent"
-            android:layout_height="1dip"
-            android:scaleType="fitXY"
-            android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_strong_holo" />
+            android:layout_height="2dip"
+            android:background="@android:color/holo_blue_light" />
     <FrameLayout
         android:layout_width="match_parent" android:layout_height="wrap_content"
         android:layout_weight="1"
diff --git a/core/res/res/layout/dialog_title_holo.xml b/core/res/res/layout/dialog_title_holo.xml
index 400ef60..50bb0ba 100644
--- a/core/res/res/layout/dialog_title_holo.xml
+++ b/core/res/res/layout/dialog_title_holo.xml
@@ -30,12 +30,10 @@
         android:paddingLeft="16dip"
         android:paddingRight="16dip"
         android:gravity="center_vertical|left" />
-    <ImageView android:id="@+id/titleDivider"
+    <View android:id="@+id/titleDivider"
             android:layout_width="match_parent"
-            android:layout_height="1dip"
-            android:scaleType="fitXY"
-            android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_strong_holo" />
+            android:layout_height="2dip"
+            android:background="@android:color/holo_blue_light" />
     <FrameLayout
         android:layout_width="match_parent" android:layout_height="wrap_content"
         android:layout_weight="1"
diff --git a/core/res/res/layout/dialog_title_icons_holo.xml b/core/res/res/layout/dialog_title_icons_holo.xml
index f780ab0..7d7959f 100644
--- a/core/res/res/layout/dialog_title_icons_holo.xml
+++ b/core/res/res/layout/dialog_title_icons_holo.xml
@@ -48,12 +48,10 @@
             android:layout_marginLeft="8dip" />
     </LinearLayout>
 
-    <ImageView android:id="@+id/titleDivider"
+    <View android:id="@+id/titleDivider"
             android:layout_width="match_parent"
             android:layout_height="1dip"
-            android:scaleType="fitXY"
-            android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_strong_holo" />
+            android:background="@android:color/holo_blue_light" />
 
     <FrameLayout
         android:layout_width="match_parent" android:layout_height="wrap_content"
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index 937d5dc..e867fe0 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -29,11 +29,10 @@
     android:clipChildren="false">
 
     <!-- Column 0 -->
-    <Space android:height="20dip"/>
-
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
-        android:layout_marginTop="16dip"
-        android:layout_marginBottom="8dip">
+        android:layout_marginTop="8dip"
+        android:layout_marginBottom="8dip"
+        android:layout_gravity="right">
 
        <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
         top of the other. Hence the redundant layout... -->
@@ -67,120 +66,130 @@
         android:id="@+id/date"
         android:layout_below="@id/time"
         android:layout_marginTop="6dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
-        android:layout_gravity="left"
+        android:layout_gravity="right"
         />
 
     <TextView
         android:id="@+id/alarm_status"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
         android:layout_marginTop="4dip"
-        android:layout_gravity="left"
+        android:layout_gravity="right"
         />
 
     <TextView
         android:id="@+id/status1"
         android:layout_marginTop="4dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
-        android:layout_gravity="left"
+        android:layout_gravity="right"
         />
 
     <TextView
         android:id="@+id/status2"
         android:layout_marginTop="4dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
-        android:layout_gravity="left"
+        android:layout_gravity="right"
         />
 
     <TextView
         android:id="@+id/screenLocked"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:gravity="center"
         android:layout_marginTop="4dip"
         android:drawablePadding="4dip"
-        android:layout_gravity="left"
+        android:layout_gravity="right"
         />
 
-    <Space android:height="20dip"/>
-
-    <LinearLayout android:orientation="vertical" >
-
-         <TextView
-            android:id="@+id/carrier"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentTop="true"
-            android:singleLine="true"
-            android:ellipsize="marquee"
-            android:layout_gravity="bottom|left"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
-            android:textColor="?android:attr/textColorSecondary"
+    <Space
+        android:layout_rowFlexibility="canStretch"
+        android:layout_columnFlexibility="canStretch"
         />
 
-        <!-- "emergency calls only" shown when sim is missing or PUKd -->
-        <TextView
-            android:id="@+id/emergencyCallText"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentTop="true"
-            android:layout_marginTop="20dip"
-            android:singleLine="true"
-            android:ellipsize="marquee"
-            android:text="@string/emergency_calls_only"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
-            android:textColor="?android:attr/textColorSecondary"
-        />
-
-        <Button
-            android:id="@+id/emergencyCallButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:drawableLeft="@drawable/ic_emergency"
-            android:text="@string/lockscreen_emergency_call"
-            style="@style/Widget.Button.Transparent"
-            android:drawablePadding="8dip"
-            android:layout_marginRight="80dip"
-            android:visibility="visible"
-        />
-    </LinearLayout>
-
-    <Space android:height="20dip"/>
-
-    <!-- Column 1 -->
-    <Space android:width="20dip" android:layout_columnWeight="1" android:layout_rowSpan="10" />
-
-    <!-- Column 2 - password entry field and PIN keyboard -->
-    <EditText android:id="@+id/passwordEntry"
-        android:layout_height="wrap_content"
-        android:layout_width="match_parent"
+    <TextView
+        android:id="@+id/carrier"
         android:singleLine="true"
-        android:textStyle="normal"
-        android:inputType="textPassword"
-        android:gravity="center"
-        android:textSize="24sp"
+        android:ellipsize="marquee"
+        android:layout_gravity="right"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:background="@drawable/lockscreen_password_field_dark"
-        android:textColor="?android:attr/textColorPrimary"
-        />
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:textColor="?android:attr/textColorSecondary"
+    />
 
-    <!-- Numeric keyboard -->
-    <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
-        android:layout_width="300dip"
-        android:layout_height="300dip"
-        android:background="#40000000"
-        android:layout_marginTop="5dip"
-        android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
+    <!-- "emergency calls only" shown when sim is missing or PUKd -->
+    <TextView
+        android:id="@+id/emergencyCallText"
+        android:layout_marginTop="20dip"
+        android:layout_gravity="right"
+        android:singleLine="true"
+        android:ellipsize="marquee"
+        android:text="@string/emergency_calls_only"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:textColor="?android:attr/textColorSecondary"
+    />
+
+    <Button
+        android:id="@+id/emergencyCallButton"
+        android:layout_gravity="right"
+        android:drawableLeft="@drawable/lockscreen_emergency_button"
+        android:text="@string/lockscreen_emergency_call"
+        style="?android:attr/buttonBarButtonStyle"
+        android:drawablePadding="8dip"
         android:visibility="visible"
     />
 
+    <!-- Column 1 -->
+    <Space android:layout_width="32dip" android:layout_rowSpan="10" />
+
+    <!-- Column 2 - password entry field and PIN keyboard -->
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_gravity="center|fill"
+        android:layout_rowSpan="10">
+
+        <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"
+            />
+
+        <!-- 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="visible"
+        />
+
+    </LinearLayout>
+
 </GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index 30747bc..6953ac8 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -41,10 +41,10 @@
         android:layout_marginTop="4dip"
         android:layout_marginRight="16dip"
         android:layout_gravity="right"
-        android:drawableLeft="@drawable/ic_emergency"
+        android:drawableLeft="@drawable/lockscreen_emergency_button"
         android:drawablePadding="8dip"
         android:text="@string/lockscreen_emergency_call"
-        style="@style/Widget.Button.Transparent"
+        style="?android:attr/buttonBarButtonStyle"
     />
 
     <!-- bottom: password -->
diff --git a/core/res/res/layout/keyguard_screen_status_land.xml b/core/res/res/layout/keyguard_screen_status_land.xml
index 60dd9ff..021faa3 100644
--- a/core/res/res/layout/keyguard_screen_status_land.xml
+++ b/core/res/res/layout/keyguard_screen_status_land.xml
@@ -73,6 +73,8 @@
             android:id="@+id/date"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"/>
 
@@ -81,6 +83,8 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginLeft="30dip"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"/>
 
@@ -92,6 +96,8 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:layout_marginTop="10dip"
@@ -106,6 +112,8 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="10dip"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         />
 
diff --git a/core/res/res/layout/keyguard_screen_status_port.xml b/core/res/res/layout/keyguard_screen_status_port.xml
index e72df5b..f84e61c 100644
--- a/core/res/res/layout/keyguard_screen_status_port.xml
+++ b/core/res/res/layout/keyguard_screen_status_port.xml
@@ -70,6 +70,8 @@
             android:id="@+id/date"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"/>
 
@@ -78,6 +80,8 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginLeft="16dip"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
             android:drawablePadding="4dip"/>
@@ -90,6 +94,8 @@
         android:layout_height="wrap_content"
         android:layout_gravity="right"
         android:layout_marginTop="4dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:textAppearance="?android:attr/textAppearanceMedium"
         />
@@ -101,6 +107,8 @@
         android:layout_height="wrap_content"
         android:layout_gravity="right"
         android:layout_alignParentTop="true"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:layout_marginTop="4dip"
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 020bb27..1e2abf9 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -80,6 +80,8 @@
             android:id="@+id/date"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
             />
@@ -88,6 +90,8 @@
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
             android:drawablePadding="4dip"
@@ -105,6 +109,8 @@
         android:layout_marginLeft="16dip"
         android:layout_marginRight="16dip"
         android:layout_alignParentRight="true"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
@@ -119,6 +125,8 @@
         android:layout_marginLeft="16dip"
         android:layout_marginRight="16dip"
         android:layout_alignParentRight="true"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
@@ -133,6 +141,8 @@
         android:layout_marginLeft="16dip"
         android:layout_marginRight="16dip"
         android:layout_alignParentRight="true"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:layout_marginTop="12dip"
@@ -147,14 +157,13 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="4dip"
         android:layout_marginRight="16dip"
-        android:drawableLeft="@drawable/ic_emergency"
+        android:drawableLeft="@drawable/lockscreen_emergency_button"
         android:layout_alignParentRight="true"
         android:layout_below="@id/screenLocked"
-        style="@style/Widget.Button.Transparent"
+        style="?android:attr/buttonBarButtonStyle"
         android:drawablePadding="4dip"
         android:text="@string/lockscreen_emergency_call"
         android:visibility="visible"
-        android:background="@null"
         />
 
     <RelativeLayout
@@ -207,6 +216,8 @@
             android:layout_marginTop="0dip"
             android:layout_marginRight="8dip"
             android:text="@string/emergency_calls_only"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
             android:textColor="?android:attr/textColorSecondary"
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 930ac33..7aab04e 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -24,15 +24,13 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:rowCount="10"
+    android:rowCount="8"
     android:id="@+id/root"
     android:clipChildren="false">
 
     <!-- Column 0 -->
-    <Space android:height="20dip"/>
-
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
-        android:layout_marginTop="16dip"
+        android:layout_marginTop="8dip"
         android:layout_marginBottom="8dip"
         android:layout_gravity="right">
 
@@ -68,6 +66,8 @@
         android:id="@+id/date"
         android:layout_below="@id/time"
         android:layout_marginTop="6dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:layout_gravity="right"
@@ -75,6 +75,8 @@
 
     <TextView
         android:id="@+id/alarm_status"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
@@ -85,6 +87,8 @@
     <TextView
         android:id="@+id/status1"
         android:layout_marginTop="4dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
@@ -94,6 +98,8 @@
     <TextView
         android:id="@+id/status2"
         android:layout_marginTop="4dip"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
@@ -102,6 +108,8 @@
 
     <TextView
         android:id="@+id/screenLocked"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:gravity="center"
@@ -110,10 +118,14 @@
         android:layout_gravity="right"
         />
 
-    <Space android:height="20dip"/>
+    <Space
+        android:layout_rowFlexibility="canStretch"
+        android:layout_columnFlexibility="canStretch"
+        />
 
     <LinearLayout android:orientation="vertical"
-        android:gravity="fill">
+        android:layout_gravity="right"
+        android:gravity="fill_horizontal">
 
          <TextView
             android:id="@+id/carrier"
@@ -148,25 +160,24 @@
             android:id="@+id/emergencyCallButton"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:drawableLeft="@drawable/ic_emergency"
+            android:drawableLeft="@drawable/lockscreen_emergency_button"
             android:text="@string/lockscreen_emergency_call"
-            style="@style/Widget.Button.Transparent"
+            style="?android:attr/buttonBarButtonStyle"
             android:drawablePadding="8dip"
-            android:layout_marginRight="80dip"
             android:visibility="visible"
             android:layout_gravity="right"
         />
     </LinearLayout>
 
     <!-- Column 1 -->
-    <Space android:width="20dip" android:layout_columnWeight="1" android:layout_rowSpan="10" />
+    <Space android:layout_width="32dip" android:layout_rowSpan="8" />
 
     <!-- Column 2 -->
     <com.android.internal.widget.multiwaveview.MultiWaveView
         android:id="@+id/unlock_widget"
-        android:layout_width="300dip"
+        android:layout_width="200dip"
         android:layout_height="match_parent"
-        android:layout_rowSpan="10"
+        android:layout_rowSpan="8"
 
         android:targetDrawables="@array/lockscreen_targets_when_silent"
         android:handleDrawable="@drawable/ic_lockscreen_handle"
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index 8319b8a..8f083a0 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -26,12 +26,10 @@
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:rowCount="8">
+    android:rowCount="7">
 
     <!-- Column 0: Time, date and status -->
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
         android:layout_marginTop="8dip"
         android:layout_marginBottom="12dip"
         android:layout_gravity="right">
@@ -66,8 +64,8 @@
 
     <TextView
         android:id="@+id/date"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:layout_gravity="right"
@@ -75,8 +73,8 @@
 
     <TextView
         android:id="@+id/alarm_status"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:layout_gravity="right"
@@ -85,8 +83,8 @@
 
     <TextView
         android:id="@+id/status1"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:layout_gravity="right"
@@ -94,37 +92,47 @@
 
     <!-- TODO: remove hard coded height since layout_rowWeight doesn't seem to be working -->
     <Space
-    android:layout_height="43dip"
-    android:layout_gravity="fill"
-    android:layout_rowWeight="1" android:layout_columnWeight="1" />
+        android:layout_rowFlexibility="canStretch"
+        android:layout_columnFlexibility="canStretch"
+        />
 
     <TextView android:id="@+id/carrier"
         android:layout_gravity="right"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:singleLine="true"
         android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         />
 
-    <Button android:id="@+id/emergencyCallButton"
-        android:layout_gravity="right"
-        style="@style/Widget.Button.Transparent"
-        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
-        android:text="@string/lockscreen_emergency_call"
-        android:drawableLeft="@drawable/lockscreen_emergency_button"
-        android:drawablePadding="0dip"
-        android:background="@null"
-    />
+    <LinearLayout
+        style="?android:attr/buttonBarStyle"
+        android:orientation="vertical"
+        android:layout_gravity="right">
 
-    <Button android:id="@+id/forgotPatternButton"
-        android:layout_gravity="right"
-        style="@style/Widget.Button.Transparent"
-        android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
-        android:text="@string/lockscreen_forgot_pattern_button_text"
-        android:drawableLeft="@drawable/lockscreen_forgot_password_button"
-        android:drawablePadding="0dip"
-        android:background="@null"
-    />
+        <Button android:id="@+id/emergencyCallButton"
+            style="?android:attr/buttonBarButtonStyle"
+            android:layout_gravity="right"
+            android:layout_width="wrap_content"
+            android:layout_height="0dip"
+            android:layout_weight="1"
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+            android:text="@string/lockscreen_emergency_call"
+            android:drawableLeft="@drawable/lockscreen_emergency_button"
+            android:drawablePadding="0dip"
+        />
+
+        <Button android:id="@+id/forgotPatternButton"
+            style="?android:attr/buttonBarButtonStyle"
+            android:layout_gravity="right"
+            android:layout_width="wrap_content"
+            android:layout_height="0dip"
+            android:layout_weight="1"
+            android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+            android:text="@string/lockscreen_forgot_pattern_button_text"
+            android:drawableLeft="@drawable/lockscreen_forgot_password_button"
+            android:drawablePadding="0dip"
+        />
+    </LinearLayout>
 
     <!-- Column 1: lock pattern -->
     <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
@@ -134,6 +142,6 @@
          android:layout_marginRight="8dip"
          android:layout_marginBottom="8dip"
          android:layout_marginLeft="8dip"
-         android:layout_rowSpan="8"/>
+         android:layout_rowSpan="7"/>
 
 </GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index bbe2006..35fd473 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -68,6 +68,8 @@
             android:id="@+id/date"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
             />
@@ -77,6 +79,8 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginLeft="16dip"
+            android:singleLine="true"
+            android:ellipsize="marquee"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
             android:drawablePadding="4dip"
@@ -89,22 +93,22 @@
         android:id="@+id/status1"
         android:layout_gravity="right"
         android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
-        android:singleLine="true"
-        android:ellipsize="marquee"
         />
 
     <TextView
         android:id="@+id/status2"
         android:layout_gravity="right"
         android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+        android:singleLine="true"
+        android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
-        android:singleLine="true"
-        android:ellipsize="marquee"
         android:visibility="gone"
         />
 
@@ -121,7 +125,7 @@
         android:layout_marginBottom="4dip"
         android:layout_marginLeft="8dip"
         android:layout_gravity="center|bottom"
-        android:layout_rowWeight="1"
+        android:layout_rowFlexibility="canStretch"
      />
 
     <TextView
@@ -136,30 +140,33 @@
     <!-- Footer: an emergency call button and an initially hidden "Forgot pattern" button -->
     <LinearLayout
         android:orientation="horizontal"
-        android:layout_gravity="fill_horizontal">
+        android:layout_width="match_parent"
+        style="?android:attr/buttonBarStyle"
+        android:gravity="center"
+        android:weightSum="2">
 
         <Button android:id="@+id/emergencyCallButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal"
-            style="@style/Widget.Button.Transparent"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            style="?android:attr/buttonBarButtonStyle"
             android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
             android:text="@string/lockscreen_emergency_call"
             android:drawableLeft="@drawable/lockscreen_emergency_button"
             android:drawablePadding="0dip"
-            android:background="@null"
         />
 
         <Button android:id="@+id/forgotPatternButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal"
-            style="@style/Widget.Button.Transparent"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            style="?android:attr/buttonBarButtonStyle"
             android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
             android:text="@string/lockscreen_forgot_pattern_button_text"
             android:drawableLeft="@drawable/lockscreen_forgot_password_button"
             android:drawablePadding="0dip"
-            android:background="@null"
         />
 
     </LinearLayout>
diff --git a/core/res/res/layout/number_picker.xml b/core/res/res/layout/number_picker.xml
index 807daf2..f2f524c 100644
--- a/core/res/res/layout/number_picker.xml
+++ b/core/res/res/layout/number_picker.xml
@@ -23,6 +23,8 @@
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         style="?android:attr/numberPickerUpButtonStyle"
+        android:paddingTop="22dip"
+        android:paddingBottom="22dip"
         android:contentDescription="@string/number_picker_increment_button" />
 
     <EditText android:id="@+id/numberpicker_input"
@@ -34,6 +36,8 @@
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         style="?android:attr/numberPickerDownButtonStyle"
+        android:paddingTop="22dip"
+        android:paddingBottom="22dip"
         android:contentDescription="@string/number_picker_decrement_button" />
 
 </merge>
diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml
index 82b3a4c..fb898ee 100644
--- a/core/res/res/layout/preference_list_content.xml
+++ b/core/res/res/layout/preference_list_content.xml
@@ -85,7 +85,6 @@
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
         android:layout_weight="0"
-        android:background="@android:drawable/bottom_bar"
         android:visibility="gone">
 
         <Button android:id="@+id/back_button"
@@ -93,8 +92,6 @@
             android:layout_height="wrap_content"
             android:layout_margin="5dip"
             android:layout_alignParentLeft="true"
-            android:drawableLeft="@drawable/ic_btn_back"
-            android:drawablePadding="3dip"
             android:text="@string/back_button_label"
         />
         <LinearLayout
@@ -115,8 +112,6 @@
                 android:layout_width="150dip"
                 android:layout_height="wrap_content"
                 android:layout_margin="5dip"
-                android:drawableRight="@drawable/ic_btn_next"
-                android:drawablePadding="3dip"
                 android:text="@string/next_button_label"
             />
         </LinearLayout>
diff --git a/core/res/res/layout/preference_list_content_single.xml b/core/res/res/layout/preference_list_content_single.xml
index a015761..6902ffd 100644
--- a/core/res/res/layout/preference_list_content_single.xml
+++ b/core/res/res/layout/preference_list_content_single.xml
@@ -56,7 +56,6 @@
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
         android:layout_weight="0"
-        android:background="@android:drawable/bottom_bar"
         android:visibility="gone">
 
         <Button android:id="@+id/back_button"
@@ -64,8 +63,6 @@
             android:layout_height="wrap_content"
             android:layout_margin="5dip"
             android:layout_alignParentLeft="true"
-            android:drawableLeft="@drawable/ic_btn_back"
-            android:drawablePadding="3dip"
             android:text="@string/back_button_label"
         />
         <LinearLayout
@@ -86,8 +83,6 @@
                 android:layout_width="150dip"
                 android:layout_height="wrap_content"
                 android:layout_margin="5dip"
-                android:drawableRight="@drawable/ic_btn_next"
-                android:drawablePadding="3dip"
                 android:text="@string/next_button_label"
             />
         </LinearLayout>
diff --git a/core/res/res/layout/preference_list_fragment.xml b/core/res/res/layout/preference_list_fragment.xml
index 986536e..315f708 100644
--- a/core/res/res/layout/preference_list_fragment.xml
+++ b/core/res/res/layout/preference_list_fragment.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/* 
+/*
 ** Copyright 2010, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -41,7 +41,6 @@
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
         android:layout_weight="0"
-        android:background="@android:drawable/bottom_bar"
         android:visibility="gone">
 
         <Button android:id="@+id/back_button"
@@ -49,8 +48,6 @@
             android:layout_height="wrap_content"
             android:layout_margin="5dip"
             android:layout_alignParentLeft="true"
-            android:drawableLeft="@drawable/ic_btn_back"
-            android:drawablePadding="3dip"
             android:text="@string/back_button_label"
         />
         <LinearLayout
@@ -71,8 +68,6 @@
                 android:layout_width="150dip"
                 android:layout_height="wrap_content"
                 android:layout_margin="5dip"
-                android:drawableRight="@drawable/ic_btn_next"
-                android:drawablePadding="3dip"
                 android:text="@string/next_button_label"
             />
         </LinearLayout>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index 9742b94..2392618 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -46,7 +46,7 @@
     <com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar"
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
-                  style="?android:attr/actionBarStyle"
+                  style="?android:attr/actionBarSplitStyle"
                   android:visibility="gone"
                   android:gravity="center"/>
 </LinearLayout>
diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml
index 086acdd..19b861c 100644
--- a/core/res/res/layout/screen_action_bar_overlay.xml
+++ b/core/res/res/layout/screen_action_bar_overlay.xml
@@ -50,7 +50,7 @@
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:layout_alignParentBottom="true"
-                  style="?android:attr/actionBarStyle"
+                  style="?android:attr/actionBarSplitStyle"
                   android:visibility="gone"
                   android:gravity="center"/>
 </RelativeLayout>
diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml
index 475aa59..fee27eb 100644
--- a/core/res/res/layout/search_view.xml
+++ b/core/res/res/layout/search_view.xml
@@ -54,8 +54,8 @@
         android:layout_height="wrap_content"
         android:layout_weight="1"
         android:layout_gravity="center_vertical"
-        android:layout_marginLeft="16dip"
-        android:layout_marginRight="16dip"
+        android:layout_marginLeft="8dip"
+        android:layout_marginRight="8dip"
         android:layout_marginTop="4dip"
         android:layout_marginBottom="4dip"
         android:orientation="horizontal">
@@ -87,7 +87,6 @@
                 android:layout_gravity="bottom"
                 android:paddingLeft="8dip"
                 android:paddingRight="6dip"
-                android:drawablePadding="2dip"
                 android:singleLine="true"
                 android:ellipsize="end"
                 android:background="@null"
diff --git a/core/res/res/layout/ssl_certificate.xml b/core/res/res/layout/ssl_certificate.xml
new file mode 100644
index 0000000..dd89a2d
--- /dev/null
+++ b/core/res/res/layout/ssl_certificate.xml
@@ -0,0 +1,286 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<ScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" >
+
+    <LinearLayout
+        android:id="@+id/body"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="left"
+        android:orientation="vertical" >
+
+        <!-- Placeholder for the success message or one or more warnings -->
+        <LinearLayout
+            android:id="@+id/placeholder"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginTop="12dip"
+            android:orientation="vertical" />
+
+        <!-- Dialog-title line separator -->
+        <ImageView
+            android:id="@+id/title_separator"
+            android:src="@android:drawable/divider_horizontal_dark"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:scaleType="fitXY"
+            android:layout_weight="1"
+            android:gravity="fill_horizontal"
+            android:layout_marginRight="20dip"
+            android:layout_marginLeft="20dip"/>
+
+        <!-- Issued to: -->
+        <TextView
+            android:id="@+id/issued_to_header"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:text="@string/issued_to"
+            android:textStyle="bold"
+            android:layout_marginTop="12dip"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+        <!-- Common name: -->
+        <TextView
+            android:id="@+id/to_common_header"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:text="@string/common_name"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip" />
+
+        <TextView
+            android:id="@+id/to_common"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+        <!-- Organization: -->
+        <TextView
+            android:id="@+id/to_org_header"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:text="@string/org_name"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip" />
+
+        <TextView
+            android:id="@+id/to_org"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+        <!-- Organizational unit: -->
+        <TextView
+            android:id="@+id/to_org_unit_header"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:text="@string/org_unit"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip" />
+
+        <TextView
+            android:id="@+id/to_org_unit"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+        <!-- Serial number: -->
+        <TextView
+            android:id="@+id/serial_number_header"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:text="@string/serial_number"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip" />
+
+        <TextView
+            android:id="@+id/serial_number"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+        <!-- Issued by: -->
+        <TextView
+            android:id="@+id/issued_to_header"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:text="@string/issued_by"
+            android:textStyle="bold"
+            android:layout_marginTop="12dip"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+        <!-- Common name: -->
+        <TextView
+            android:id="@+id/by_common_header"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/common_name"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip" />
+
+        <TextView
+            android:id="@+id/by_common"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+        <!-- Organization: -->
+        <TextView
+            android:id="@+id/by_org_header"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:text="@string/org_name"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip" />
+
+        <TextView
+            android:id="@+id/by_org"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+        <!-- Organizational unit: -->
+        <TextView
+            android:id="@+id/by_org_unit_header"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:text="@string/org_unit"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip" />
+
+        <TextView
+            android:id="@+id/by_org_unit"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+        <!-- Validity Dates: -->
+        <TextView
+            android:id="@+id/validity_header"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:text="@string/validity_period"
+            android:textStyle="bold"
+            android:layout_marginTop="12dip"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+        <!-- Issued On: -->
+        <TextView
+            android:id="@+id/issued_on_header"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/issued_on"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip" />
+
+        <TextView
+            android:id="@+id/issued_on"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+        <!-- Expires On: -->
+        <TextView
+            android:id="@+id/expires_on_header"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/expires_on"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip" />
+
+        <TextView
+            android:id="@+id/expires_on"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+        <!-- Fingerprints: -->
+        <TextView
+            android:id="@+id/fingerprints"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:text="@string/fingerprints"
+            android:textStyle="bold"
+            android:layout_marginTop="12dip"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+        <!-- SHA-256 fingerprint: -->
+        <TextView
+            android:id="@+id/sha256_fingerprint_header"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/sha256_fingerprint"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip" />
+
+        <TextView
+            android:id="@+id/sha256_fingerprint"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+        <!-- SHA-1 fingerprint: -->
+        <TextView
+            android:id="@+id/sha1_fingerprint_header"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/sha1_fingerprint"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip" />
+
+        <TextView
+            android:id="@+id/sha1_fingerprint"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_marginBottom="7dip" />
+
+    </LinearLayout>
+
+</ScrollView>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 78381a3..8a75bd0 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -685,6 +685,10 @@
     <skip />
     <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
     <skip />
+    <!-- no translation found for permlab_modifyNetworkAccounting (5088217309088729650) -->
+    <skip />
+    <!-- no translation found for permdesc_modifyNetworkAccounting (8702285686629184404) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Stel wagwoordreëls"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Beheer die lengte van en watter karakters in skermontsluit-wagwoorde gebruik kan word"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitor pogings om skerm te ontsluit"</string>
@@ -1243,9 +1247,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"As jy USB-berging aanskakel, sal sekere programme wat jy gebruik, stop en dalk nie beskikbaar wees nie tot jy USB-berging afskakel."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-bewerking het misluk"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formateer USB-berging"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formateer SD-kaart"</string>
@@ -1311,13 +1319,9 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Toeganklikheid"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Muurpapier"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Verander muurpapier"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Punt-tot-punt-tonnelprotokol"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Laag 2-tonnelprotokol"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Voorafgedeelde sleutel gebaseer op L2TP/IPSec-VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sertifikaat gebaseer op L2TP/IPSec-VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
     <!-- no translation found for vpn_text (1610714069627824309) -->
     <skip />
@@ -1371,12 +1375,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Vee die items uit."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Ontdoen die uitvee."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Doen vir eers niks."</string>
-    <!-- no translation found for vpn_notification_title_connected (3197819122581348515) -->
-    <skip />
-    <!-- no translation found for vpn_notification_title_disconnected (4614192702448522822) -->
-    <skip />
-    <!-- no translation found for vpn_notification_hint_disconnected (4689796928510104200) -->
-    <skip />
     <!-- no translation found for choose_account_label (4191313562041125787) -->
     <skip />
     <!-- no translation found for number_picker_increment_button (4830170763103463443) -->
@@ -1409,4 +1407,38 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <!-- no translation found for ssl_certificate (6510040486049237639) -->
+    <skip />
+    <!-- no translation found for ssl_certificate_is_valid (6825263250774569373) -->
+    <skip />
+    <!-- no translation found for issued_to (454239480274921032) -->
+    <skip />
+    <!-- no translation found for common_name (2233209299434172646) -->
+    <skip />
+    <!-- no translation found for org_name (6973561190762085236) -->
+    <skip />
+    <!-- no translation found for org_unit (7265981890422070383) -->
+    <skip />
+    <!-- no translation found for issued_by (2647584988057481566) -->
+    <skip />
+    <!-- no translation found for validity_period (8818886137545983110) -->
+    <skip />
+    <!-- no translation found for issued_on (5895017404361397232) -->
+    <skip />
+    <!-- no translation found for expires_on (3676242949915959821) -->
+    <skip />
+    <!-- no translation found for serial_number (758814067660862493) -->
+    <skip />
+    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <skip />
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
+    <skip />
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 7a0441d..52745b9 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -685,6 +685,10 @@
     <skip />
     <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
     <skip />
+    <!-- no translation found for permlab_modifyNetworkAccounting (5088217309088729650) -->
+    <skip />
+    <!-- no translation found for permdesc_modifyNetworkAccounting (8702285686629184404) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"የይለፍ ቃል ድንቦች አዘጋጅ"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"በማያ-መክፈት የተፈቀዱ የይለፍ ቃል ርዝመት እና  ቁምፊዎች ተቆጣጠር።"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"የማሳያ-ክፈት ሙከራዎችን አሳይ"</string>
@@ -1243,9 +1247,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"የUSB ማከማቻዎን ካበሩ፣ እየተጠቀሙባቸው ያሉ አንዳንድ ትግበራዎች ይቆማሉ እና የUSB ማከማቻ እስኪያጠፉ ድረስ ላይገኝ ይችላል።"</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB ክንውን አልተሳካም"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"እሺ"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"የUSB ማከማቻ ቅረፅ"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"የSD ካርድ ቅርፀት"</string>
@@ -1311,13 +1319,9 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"ተደራሽነት"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ልጣፍ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ልጣፍ ለውጥ"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"ከጫፍ እስከ ጫፍ ማስተላለፊያ ፕሮቶኮል"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"ንብርብር 2 ማስተላለፊያ ፕሮቶኮል"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"በቅድመ- አጋሪ ቁልፍL2TP/IPSec VPN የተመሰረተ"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"በL2TP/IPSec VPN ምስክርላይ የተመሰረተ"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
     <!-- no translation found for vpn_text (1610714069627824309) -->
     <skip />
@@ -1371,12 +1375,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"አይነቶቹን ሰርዝ"</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"ስርዞቹን ቀልብስ።"</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"ለአሁን ምንም አታድርግ።"</string>
-    <!-- no translation found for vpn_notification_title_connected (3197819122581348515) -->
-    <skip />
-    <!-- no translation found for vpn_notification_title_disconnected (4614192702448522822) -->
-    <skip />
-    <!-- no translation found for vpn_notification_hint_disconnected (4689796928510104200) -->
-    <skip />
     <!-- no translation found for choose_account_label (4191313562041125787) -->
     <skip />
     <!-- no translation found for number_picker_increment_button (4830170763103463443) -->
@@ -1409,4 +1407,38 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <!-- no translation found for ssl_certificate (6510040486049237639) -->
+    <skip />
+    <!-- no translation found for ssl_certificate_is_valid (6825263250774569373) -->
+    <skip />
+    <!-- no translation found for issued_to (454239480274921032) -->
+    <skip />
+    <!-- no translation found for common_name (2233209299434172646) -->
+    <skip />
+    <!-- no translation found for org_name (6973561190762085236) -->
+    <skip />
+    <!-- no translation found for org_unit (7265981890422070383) -->
+    <skip />
+    <!-- no translation found for issued_by (2647584988057481566) -->
+    <skip />
+    <!-- no translation found for validity_period (8818886137545983110) -->
+    <skip />
+    <!-- no translation found for issued_on (5895017404361397232) -->
+    <skip />
+    <!-- no translation found for expires_on (3676242949915959821) -->
+    <skip />
+    <!-- no translation found for serial_number (758814067660862493) -->
+    <skip />
+    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <skip />
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
+    <skip />
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index a326712..f37410b 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"وضع الطائرة"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"وضع الطائرة قيد التشغيل"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"وضع الطائرة متوقف"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"+100"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"الوضع الآمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"نظام Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"الخدمات التي تكلفك المال"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"كتابة بيانات جهة الاتصال"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"للسماح للتطبيق بتعديل بيانات جهة الاتصال (العنوان) المخزنة على الجهاز اللوحي. يمكن أن تستخدم التطبيقات الضارة ذلك لمحو بيانات جهة الاتصال أو تعديلها."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"للسماح لتطبيق ما بتعديل بيانات (عنوان) جهة الاتصال المخزّنة في هاتفك. يمكن أن تستخدم التطبيقات الضارة ذلك لمسح بيانات جهة الاتصال أو تعديلها."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"قراءة بيانات الملف الشخصي"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"للسماح لتطبيق بقراءة جميع معلوماتك الشخصية في الملف الشخصي. ويمكن أن تستخدم التطبيقات الضارة هذه الإمكانية للتعرف على هويتك وإرسال معلوماتك الشخصية إلى أشخاص آخرين."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"كتابة بيانات الملف الشخصي"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"للسماح لتطبيق بتعديل معلوماتك الشخصية في الملف الشخصي. يمكن للتطبيقات الضارة استخدام هذه الإمكانية لمسح أو تعديل بيانات ملفك الشخصي."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"قراءة أحداث التقويم"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"للسماح لتطبيق ما بقراءة كل أحداث التقويم المخزنة على الجهاز اللوحي. ويمكن للتطبيقات الضارة استخدام ذلك لإرسال أحداث التقويم إلى أشخاص آخرين."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"للسماح لتطبيق ما بقراءة جميع أحداث التقويم المخزّنة في هاتفك. يمكن أن تستخدم التطبيقات الضارة هذا لإرسال أحداث تقويمك إلى أشخاص آخرين."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"للسماح لتطبيق ما بقراءة نظام ملفات ذاكرة التخزين المؤقت والكتابة به."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"إجراء/تلقي مكالمات عبر الإنترنت"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"للسماح لتطبيق ما باستخدام خدمة SIP لإجراء/تلقي مكالمات عبر الإنترنت."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"قراءة بيانات الاستخدام السابقة للشبكة"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"للسماح لتطبيق بقراءة معلومات سابقة عن استخدام الشبكة لشبكات وتطبيقات معينة."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"إدارة سياسة الشبكة"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"للسماح لتطبيق بإدارة سياسات الشبكة وتحديد قواعد متعلقة بالتطبيق."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"تعديل حساب استخدام الشبكة"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"للسماح بتعديل كيفية حساب استخدام الشبكة مع التطبيقات. ليس للاستخدام بواسطة التطبيقات العادية."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تعيين قواعد كلمة المرور"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"التحكم في الطول والأحرف المسموح بها في كلمات مرور إلغاء قفل الشاشة"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"مراقبة محاولات إلغاء قفل الشاشة"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"التحكم في عدد مرات تغيير كلمة مرور تأمين الشاشة"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"تعيين تشفير التخزين"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"طلب تشفير بيانات التطبيق المخزنة"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"تعطيل الكاميرات"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"منح استخدام جميع كاميرات الجهاز"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"الرئيسية"</item>
     <item msgid="869923650527136615">"الجوال"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ليس هناك بطاقة SIM في الجهاز اللوحي."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ليس هناك بطاقة SIM في الهاتف."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"الرجاء إدخال بطاقة SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"بطاقة SIM مفقودة أو غير قابلة للقراءة. الرجاء إدراج بطاقة SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"بطاقة SIM معطلة دومًا."\n" يرجى الاتصال بمقدم الخدمة اللاسلكية للحصول على بطاقة SIM أخرى."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"مكالمات الطوارئ فقط"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"الشبكة مؤمّنة"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"بطاقة SIM مؤمّنة بكود PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"إذا شغّلت سعة تخزين USB، فستتوقف بعض التطبيقات التي تستخدمها وربما تصبح غير متاحة لحين إيقاف تشغيل سعة تخزين USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"أخفقت عملية USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"موافق"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"تهيئة وحدة تخزين USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"تنسيق بطاقة SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"إمكانية الدخول"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"الخلفية"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"تغيير الخلفية"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"بروتوكول الاتصال النفقي من نقطة إلى نقطة"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"بروتوكول الاتصال النفقي ثنائي الطبقة"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"بروتوكول L2TP/IPSec VPN المستند إلى المفتاح المشترك مسبقًا"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"بروتوكول L2TP/IPSec VPN المستند إلى الشهادة"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"انقر لإدارة الشبكة."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"تم الاتصال بـ <xliff:g id="SESSION">%s</xliff:g>. انقر لإدارة الشبكة."</string>
     <string name="upload_file" msgid="2897957172366730416">"اختيار ملف"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"لم يتم اختيار أي ملف"</string>
     <string name="reset" msgid="2448168080964209908">"إعادة تعيين"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"حذف هذه العناصر"</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"التراجع عن عمليات الحذف"</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"عدم تنفيذ أي شيء الآن"</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"تم توصيل الشبكة الظاهرية الخاصة (VPN) لـ <xliff:g id="PROFILENAME">%s</xliff:g>"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"تم فصل الشبكة الظاهرية الخاصة (VPN) لـ <xliff:g id="PROFILENAME">%s</xliff:g>"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"يمكنك اللمس لإعادة الاتصال بالشبكة الظاهرية الخاصة (VPN)."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"حدد حسابًا."</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"زيادة"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"تناقص"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"بطاقة SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"وحدة تخزين USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"تعديل..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"تحذير استخدام البيانات"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"يتجاوز الاستخدام <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"تم تعطيل بيانات شبكات الجيل الثاني والجيل الثالث"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"تم تعطيل بيانات شبكة الجيل الرابع"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"تم تعطيل بيانات الجوال"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"انقر للتمكين."</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"شهادة الأمان"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"هذه الشهادة صالحة."</string>
+    <string name="issued_to" msgid="454239480274921032">"إصدار لـ:"</string>
+    <string name="common_name" msgid="2233209299434172646">"الاسم الشائع:"</string>
+    <string name="org_name" msgid="6973561190762085236">"المؤسسة:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"الوحدة التنظيمية:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"جهة الإصدار:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"الصلاحية:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"تاريخ الإصدار:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"تنتهي الصلاحية في:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 5633807..9147fb5 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Самолетен режим"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Самолетният режим е ВКЛЮЧЕН"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Самолетният режим е ИЗКЛЮЧЕН"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Системно от Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Услуги, които ви струват пари"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"запис на данни за контактите"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Разрешава на приложението да променя данните за контактите (за адрес), съхранени в таблета ви. Злонамерените приложения може да използват това, за да изтрият или променят тези данни."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Разрешава на приложението да променя данните за контактите (за адрес), съхранени в телефона ви. Злонамерените приложения могат да използват това, за да изтрият или променят тези данни."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"четене на данните"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Разрешава на приложението да чете цялата информацията от личния ви потребителски профил. Злонамерените приложения могат да използват това, за да ви идентифицират и да изпращат тази информация на други хора."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"запис на данните"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Разрешава на приложението да променя информацията от личния ви потребителски профил. Злонамерените приложения могат да използват това, за да изтрият или да променят данните ви."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"четене на събития от календара"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Разрешава на приложението да чете всички съхранени в таблета събития в календара ви. Злонамерените приложения могат да използват това, за да изпращат тези събития на други хора."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Разрешава на приложението да чете всички съхранени в телефона събития в календара ви. Злонамерените приложения могат да използват това, за да изпратят тези събития на други хора."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Разрешава на приложението да чете и записва във файловата система на кеша."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"извършване/получаване на интернет обаждания"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Разрешава на приложението да използва услугата SIP за извършване/получаване на интернет обаждания."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"четене на употребата на мрежата до момента"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Разрешава на приложението да чете употребата на данни за конкретни мрежи и приложения до момента."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"управление на правилата на мрежата"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Разрешава на приложението да управлява правилата на мрежата и да определя такива за конкретно приложение."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"промяна на отчетността на употребата на мрежа"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Разрешава промяна на това как употребата на мрежа се отчита спрямо приложенията. Не е предназначено за нормални приложения."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Задаване на правила за паролата"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Контролирайте дължината и позволените знаци за паролите за отключване на екрана"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Наблюдаване на опитите за отключване на екрана"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролирайте колко често трябва да се променя паролата за заключен екран"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Шифроване за хранилището"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Изисква съхраняваните данни за приложенията да бъдат шифровани"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Деактивиране на камерите"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Предотвратява употребата на камерите на всички устройства"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Домашен"</item>
     <item msgid="869923650527136615">"Мобилен"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"В таблета няма SIM карта."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"В телефона няма SIM карта."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Моля, поставете SIM карта."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"SIM картата липсва или е нечетима. Моля, поставете SIM карта."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"SIM картата ви е деактивирана за постоянно."\n" Моля, свържете се с оператора на безжичната си връзка, за да получите друга."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Само спешни обаждания"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Мрежата е заключена"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM картата е заключена с PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ако включите работата като USB устройство за съхранение, някои използвани от вас приложения ще спрат и може да бъдат недостъпни, докато не я изключите."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Операцията през USB не бе успешна"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматиране на USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Форматиране на SD картата"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Достъпност"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Тапет"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промяна на тапета"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Тунелен протокол от точка до точка"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Тунелен протокол за слой 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Основана на предварително споделен ключ L2TP/IPSec VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Основана на сертификати L2TP/IPSec VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Докоснете за управление на мрежата."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Свързана с/ъс <xliff:g id="SESSION">%s</xliff:g>. Докоснете, за да управлявате мрежата."</string>
     <string name="upload_file" msgid="2897957172366730416">"Избор на файл"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Няма избран файл"</string>
     <string name="reset" msgid="2448168080964209908">"Повторно задаване"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Изтриване на елементите."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Отмяна на изтриванията."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Да не се прави нищо засега."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"Връзката с VPN <xliff:g id="PROFILENAME">%s</xliff:g> бе установена"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"Връзката с VPN <xliff:g id="PROFILENAME">%s</xliff:g> бе прекъсната"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Докоснете за повторно свързване с VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Избор на профил"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Увеличаване"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Намаляване"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD карта"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB хранилище"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Редактиране..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Предупрежд. за ползване на данни"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"използването надвишава <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-3G данните са деактивирани"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G данните са деактивирани"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Мобилните данни са деактивирани"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"докоснете за активиране"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Сертификат за сигурност"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Този сертификат е валиден."</string>
+    <string name="issued_to" msgid="454239480274921032">"Издаден на:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Общо име:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Организация:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Организационна единица:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Издаден от:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Валидност:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Издаден на:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Изтича на:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index e812217..b7117b9 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode d\'avió"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mode d\'avió activat"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mode d\'avió desactivat"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"+100"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"+999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode segur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serveis de pagament"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"escriure dades de contacte"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permet que una aplicació modifiqui les dades de contactes (adreces) emmagatzemades a la tauleta. Les aplicacions malicioses poden utilitzar aquesta funció per esborrar o per modificar les teves dades de contactes."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permet a una aplicació modificar les dades de contacte (adreça) emmagatzemades al telèfon. Les aplicacions malicioses poden utilitzar-ho per esborrar o modificar les dades de contacte."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"lectura de dades del perfil"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Permet que una aplicació llegeixi tota la informació del teu perfil personal. Les aplicacions malicioses poden utilitzar-ho per identificar-te i enviar la teva informació personal a altres persones."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"escriptura de dades del perfil"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Permet a una aplicació modificar la informació del teu perfil personal. Les aplicacions malicioses poden utilitzar-ho per esborrar o modificar les dades del teu perfil."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"llegir els esdeveniments del calendari"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permet que una aplicació llegeixi tots els esdeveniments del calendari emmagatzemats a la tauleta. Les aplicacions malicioses poden utilitzar aquesta funció per enviar els teus esdeveniments del calendari a altres persones."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permet a una aplicació llegir tots els esdeveniments del calendari emmagatzemats al telèfon. Les aplicacions malicioses poden utilitzar-ho per enviar els vostres esdeveniments del calendari a altres persones."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permet a una aplicació llegir el sistema de fitxers de la memòria cau i escriure-hi."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"fes/rep trucades per Internet"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Permet que una aplicació utilitzi el servei SIP per fer i rebre trucades per Internet."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"lectura de l\'ús històric de la xarxa"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Permet que una aplicació llegeixi l\'ús històric de la xarxa per a xarxes i aplicacions específiques."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"gestió de la política de xarxa"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Permet que una aplicació gestioni les polítiques de la xarxa i defineixi les regles específiques d\'aplicació."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificació del càlcul d\'ús de la xarxa"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Permet modificar la manera com es calcula l\'ús de la xarxa per part de les aplicacions. No es pot fer servir amb aplicacions normals."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Defineix les normes de contrasenya"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controla la longitud i els caràcters permesos a les contrasenyes de desbloqueig de pantalla"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa els intents de desbloqueig de la pantalla"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controla la freqüència amb què cal canviar la contrasenya de bloqueig de pantalla"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Encriptació d’emmagatzematge"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Requereix que les dades de l\'aplicació emmagatzemades estiguin encriptades"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Desactiva les càmeres"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Impedeix l\'ús de totes les càmeres del dispositiu"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Mòbil"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No hi ha cap targeta SIM a la tauleta."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No hi ha cap targeta SIM al telèfon."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Inseriu una targeta SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Falta la targeta SIM o no es pot llegir. Insereix-ne una."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"La targeta SIM està desactivada permanentment. "\n" Contacta amb el teu proveïdor de serveis sense fil per obtenir-ne una altra."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Només trucades d\'emergència"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Xarxa bloquejada"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"La targeta SIM està bloquejada pel PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si activeu l\'emmagatzematge USB, algunes de les aplicacions que utilitzeu s\'aturaran i pot ser que no estiguin disponibles fins que desactiveu l\'emmagatzematge USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Error de l\'operació d\'USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"D\'acord"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formata l\'emmag. USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formata la targeta SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibilitat"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Empaperat"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Canvi de l\'empaperat"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Protocol de tunelització punt a punt"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocol de tunelització de capa 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec basada en clau compartida prèviament"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec basada en certificats"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Pica per gestionar la xarxa."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Connectat a <xliff:g id="SESSION">%s</xliff:g>. Pica per gestionar la xarxa."</string>
     <string name="upload_file" msgid="2897957172366730416">"Trieu un fitxer"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"No s\'ha escollit cap fitxer"</string>
     <string name="reset" msgid="2448168080964209908">"Reinicia"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Suprimeix els elements."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Desfés les supressions."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"No facis res de moment."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> connectada"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> desconnectada"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Toca per tornar-te a connectar a una VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Selecciona un compte"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Incrementa"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Disminueix"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Targeta SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Emmagatzematge USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Edita..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Advertiment d\'ús de dades"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"l\'ús supera <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Dades 2G-3G desactivades"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Dades 4G desactivades"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Dades mòbils desactivades"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"pica per activar-lo"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Certificat de seguretat"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Aquest certificat és vàlid."</string>
+    <string name="issued_to" msgid="454239480274921032">"Emès per a:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Nom comú:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organització:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Unitat organitzativa:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Emès per:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Validesa:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Emès el:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Caduca el:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index d10e1b4..ecd83dd 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Režim V letadle"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Režim V letadle je ZAPNUTÝ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Režim V letadle je VYPNUTÝ"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Nouzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Zpoplatněné služby"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"zápis dat kontaktů"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Umožňuje aplikaci změnit kontaktní údaje (adresu) uložené v tabletu. Škodlivé aplikace toto oprávnění mohou zneužít a vymazat či pozměnit kontaktní údaje."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Umožňuje aplikaci změnit kontaktní údaje (adresu) uložené v telefonu. Škodlivé aplikace mohou pomocí tohoto nastavení vymazat či pozměnit kontaktní údaje."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"číst údaje o profilu"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Umožňuje aplikaci číst veškeré soukromé údaje profilu. Škodlivé aplikace vás mohou pomocí tohoto nastavení identifikovat a posílat osobní informace dalším lidem."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"zapisovat údaje o profilu"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Umožňuje aplikaci upravovat osobní údaje v profilu. Škodlivé aplikace mohou pomocí tohoto nastavení mazat nebo upravovat údaje v profilu."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"Čtení událostí v kalendáři"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Umožňuje aplikaci číst všechny události kalendáře uložené v tabletu. Škodlivé aplikace toho mohou zneužít a odeslat události z vašeho kalendáře jiným lidem."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Umožňuje aplikaci načíst všechny události kalendáře uložené ve vašem telefonu. Škodlivé aplikace poté mohou dalším lidem odeslat události z vašeho kalendáře."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Umožňuje aplikaci číst a zapisovat do souborového systému mezipaměti."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"uskutečňovat a přijímat internetové hovory"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Umožňuje aplikaci uskutečnit a přijímat internetové hovory pomocí služby SIP."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"číst využití sítě v historii"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Umožňuje aplikaci číst historii využití sítě (u určitých sítí a aplikací)."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"spravovat zásady sítě"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Umožňuje aplikaci spravovat zásady sítě a definovat pravidla pro konkrétní aplikace."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"upravit kontrolu používání sítě"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Umožňuje upravit způsob kontroly používání sítě v souvislosti s aplikacemi. Není určeno pro běžné aplikace."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavit pravidla pro heslo"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Řídit délku hesel pro odemčení obrazovky a v nich používané znaky"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Sledovat pokusy o odemčení obrazovky"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Určuje, jak často je třeba měnit heslo pro uzamčení obrazovky"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nastavit šifrování úložiště"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Požadovat šifrování ukládaných dat"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Vypnout fotoaparáty"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Zakázat používání všech fotoaparátů zařízení"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domů"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tabletu není karta SIM."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"V telefonu není žádná karta SIM."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Prosím vložte kartu SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Karta SIM chybí nebo je nečitelná. Vložte prosím kartu SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Vaše karta SIM byla natrvalo zablokována."\n" Další kartu SIM obdržíte u svého poskytovatele bezdrátových služeb."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Pouze tísňová volání"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Síť je blokována"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Karta SIM je zablokována pomocí kódu PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Pokud zapnete úložiště USB, dojde k zastavení některých používaných aplikací. Tyto aplikace pravděpodobně nebudou k dispozici až do vypnutí úložiště USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Chyba operace na rozhraní USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formátovat úložiště USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formátovat kartu SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Usnadnění"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Změnit tapetu"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Protokol PPTP (Point-to-Point Tunneling Protocol)"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protokol L2TP (Layer 2 Tunneling Protocol)"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Síť VPN L2TP/IPSec s předsdíleným klíčem"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Síť VPN L2TP/IPSec s certifikátem"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Klepnutím zobrazíte správu sítě."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Připojeno k relaci <xliff:g id="SESSION">%s</xliff:g>. Klepnutím můžete síť spravovat."</string>
     <string name="upload_file" msgid="2897957172366730416">"Zvolit soubor"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Není vybrán žádný soubor"</string>
     <string name="reset" msgid="2448168080964209908">"Resetovat"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Smazat položky."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Vrátit mazání zpět."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Neprovádět akci."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"Síť VPN <xliff:g id="PROFILENAME">%s</xliff:g> je připojena"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"Síť VPN <xliff:g id="PROFILENAME">%s</xliff:g> je odpojena"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Dotykem se znovu připojíte k síti VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Vybrat účet"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Zvýšení"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Snížení"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Karta SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Úložiště USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Upravit..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Upozornění na využití dat"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"Objem přenesených dat přesahuje <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Datové přenosy 2G a 3G zakázány"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Datové přenosy 4G jsou zakázány"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobilní data jsou zakázána"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"klepnutím povolíte"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Certifikát zabezpečení"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Tento certifikát je platný."</string>
+    <string name="issued_to" msgid="454239480274921032">"Vydáno pro:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Běžný název:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organizace:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Organizační jednotka:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Vydal:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Platnost:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Datum vydání:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Platnost vyprší:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index a7f62ec..67de2aa 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flytilstand"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flytilstand er TIL"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flytilstand er slået FRA"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Tjenester, der koster dig penge"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"skriv kontaktdata"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Tillader, at en applikation ændrer kontaktdata (adresser), der er gemt på din tabletcomputer. Ondsindede applikationer kan bruge dette til at slette eller ændre kontaktdata."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Tillader, at en applikation ændrer kontaktdata (adresser), der er gemt på din telefon. Ondsindede applikationer kan bruge dette til at slette eller ændre kontaktdata."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"læs profildata"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Tillader, at en applikation kan læse alle dine personlige profiloplysninger. Ondsindede programmer kan bruge dette til at identificere dig og sende dine personlige oplysninger til andre personer."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"skrive profildata"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Tillader, at en applikation kan ændre dine personlige profiloplysninger. Ondsindede programmer kan bruge dette til at slette eller ændre dine profildata."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"læs kalenderbegivenheder"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Tillader, at en applikation læser alle kalenderbegivenheder, der er gemt på din tabletcomputer. Ondsindede applikationer kan bruge dette til at sende dine kalenderbegivenheder til andre mennesker."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Tillader, at en applikation læser alle kalenderbegivenheder, der er gemt på din telefon. Ondsindede applikationer kan bruge dette til at sende dine kalenderbegivenheder til andre mennesker."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Tillader, at en applikation læser og skriver til cache-filsystemet."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"foretage/modtage internetopkald"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Tillader, at en applikation anvender SIP-tjenesten til at foretage/modtage internetopkald."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"læse oversigt over netværksbrug"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Tillader, at en applikation kan læse en oversigt over netværksbrug for specifikke netværk og applikationer."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"administrer netværkspolitik"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Tillader, at en applikation kan administrere netværkspolitikker og definere applikationsspecifikke regler."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"skift afregning af netværksbrug"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Tillader ændring af, hvordan netværksbrug afregnes i forhold til applikationer. Ikke til brug for almindelige applikationer."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Indstil regler for adgangskode"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontroller længden samt tilladte tegn i adgangskoder til oplåsning af skærm"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåg forsøg på oplåsning af skærm"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Administrer, hvor tit skærmlåsens adgangskode skal skiftes"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Angiv kryptering af lager"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Kræv, at gemte programdata krypteres"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Deaktiver kameraer"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Bloker brug af alle kameraer på enheden"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hjem"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Der er ikke noget SIM-kort i tabletcomputeren."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Der er ikke noget SIM-kort i telefonen."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Indsæt et SIM-kort."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"SIM-kortet mangler eller kan ikke læses. Indsæt et SIM-kort."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Dit SIM-kort er permanent deaktiveret."\n"Kontakt dit mobilselskab for at få et nyt SIM-kort."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Kun nødopkald"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Netværket er låst"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM-kortet er låst med PUK-koden."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Hvis du slår USB-lagring til, vil nogle af de applikationer, som du bruger, stoppe, og de kan være utilgængelige, indtil du slår USB-lagring til igen."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-handlingen mislykkedes"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formater USB-lager"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formater SD-kort"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Tilgængelighed"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapet"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Skift tapet"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Point-to-Point Tunneling Protocol"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunneling Protocol"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN baseret på forhåndsdelt nøglekodning"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Certifikatbaseret L2TP/IPSec VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Tryk for at administrere netværket."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Forbundet til <xliff:g id="SESSION">%s</xliff:g>. Tryk for at administrere netværket."</string>
     <string name="upload_file" msgid="2897957172366730416">"Vælg fil"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil er valgt"</string>
     <string name="reset" msgid="2448168080964209908">"Nulstil"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Slet elementerne."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Fortryd sletningerne."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Gør ikke noget lige nu."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN forbundet"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN afbrudt"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Tryk for at oprette forbindelse til et VPN igen."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Vælg en konto"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Optælling"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Nedtælling"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD-kort"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-lager"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Rediger..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Advarsel om dataforbrug"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"forbruget overstiger <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-3G-data er deaktiveret"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G-data er deaktiveret"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobildata er deaktiveret"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"tryk for at aktivere"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Sikkerhedscertifikat"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Dette certifikat er gyldigt."</string>
+    <string name="issued_to" msgid="454239480274921032">"Udstedt til:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Fællesnavn:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organisation:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Organisatorisk enhed:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Udstedt af:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Gyldighed:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Udstedt den:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Udløber den:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index afa606f..b4203b6 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flugmodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flugmodus ist AN."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flugmodus ist AUS."</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"Mehr als 100"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-System"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Kostenpflichtige Dienste"</string>
@@ -202,7 +202,7 @@
     <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Ermöglicht einer App, auf Ihrem Tablet oder Ihrer SIM-Karte gespeicherte SMS zu bearbeiten. Schädliche Anwendungen löschen möglicherweise Ihre Nachrichten."</string>
     <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Ermöglicht einer App, auf Ihrem Telefon oder Ihrer SIM-Karte gespeicherte Kurznachrichten zu bearbeiten. Schädliche Anwendungen löschen möglicherweise Ihre Nachrichten."</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"WAP-Nachrichten empfangen"</string>
-    <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Ermöglicht der App, WAP-Mitteilungen zu empfangen und zu verarbeiten. Schädliche Anwendungen können Ihre Nachrichten möglicherweise überwachen oder löschen, bevor sie angezeigt werden."</string>
+    <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Ermöglicht der App, WAP-Mitteilungen zu empfangen und zu verarbeiten. Schädliche Apps können Ihre Nachrichten möglicherweise überwachen oder löschen, bevor sie angezeigt werden."</string>
     <string name="permlab_getTasks" msgid="5005277531132573353">"laufende Anwendungen abrufen"</string>
     <string name="permdesc_getTasks" msgid="7048711358713443341">"Ermöglicht der App, Informationen zu aktuellen und kürzlich ausführten Aufgaben abzurufen. Schädliche Anwendungen können so eventuell geheime Informationen zu anderen Anwendungen entdecken."</string>
     <string name="permlab_reorderTasks" msgid="5669588525059921549">"Laufende Anwendungen neu ordnen"</string>
@@ -222,7 +222,7 @@
     <string name="permlab_forceBack" msgid="1804196839880393631">"Schließen von Anwendung erzwingen"</string>
     <string name="permdesc_forceBack" msgid="6534109744159919013">"Ermöglicht einer App, alle Aktivitäten, die im Vordergrund ablaufen, zu beenden und in den Hintergrund zu schieben. Sollte nicht für normale Anwendungen benötigt werden."</string>
     <string name="permlab_dump" msgid="1681799862438954752">"Systeminternen Status abrufen"</string>
-    <string name="permdesc_dump" msgid="2198776174276275220">"Ermöglicht einer App, den internen Status des Systems abzurufen. Schädliche Anwendungen rufen hierbei möglicherweise eine Vielzahl an privaten und geschützten Daten ab, die Sie in der Regel nicht benötigen würden."</string>
+    <string name="permdesc_dump" msgid="2198776174276275220">"Ermöglicht einer App, den internen Status des Systems abzurufen. Schädliche Apps rufen hierbei möglicherweise eine Vielzahl an privaten und geschützten Daten ab, die Sie in der Regel nicht benötigen würden."</string>
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"Bildschirminhalt abrufen"</string>
     <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Ermöglicht einer App, den Inhalt des aktiven Fensters abzurufen. Schädliche Apps können den gesamten Fensterinhalt abrufen und mit Ausnahme von Passwörtern den gesamten Text auswerten."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"partielles Herunterfahren"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"Kontaktdaten schreiben"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Ermöglicht einer App, die auf Ihrem Tablet gespeicherten Kontaktdaten (Adressen) zu ändern. Schädliche Anwendungen können so Ihre Kontaktdaten löschen oder verändern."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Ermöglicht einer App, die auf Ihrem Telefon gespeicherten Kontaktdaten (Adressen) zu ändern. Schädliche Anwendungen können so Ihre Kontaktdaten löschen oder verändern."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"Profildaten lesen"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Ermöglicht einer App, alle Ihre persönlichen Profilinformationen zu lesen. Schädliche Apps können Sie damit identifizieren und Ihre persönlichen Daten an andere Personen weitergeben."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"Profildaten schreiben"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Ermöglicht einer App, Ihre persönlichen Profilinformationen zu ändern. Schädliche Apps können so Ihre Profildaten löschen oder ändern."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"Kalendereinträge lesen"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Ermöglicht einer App, alle auf Ihrem Tablet gespeicherten Kalenderereignisse zu lesen. Schädliche Anwendungen können so Ihre Kalenderereignisse an andere Personen senden."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Ermöglicht einer App, alle auf Ihrem Telefon gespeicherten Kalenderereignisse zu lesen. Schädliche Anwendungen können so Ihre Kalenderereignisse an andere Personen senden."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Gewährt einer Anwendung Lese- und Schreibzugriff auf das Cache-Dateisystem."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"Internetanrufe tätigen/annehmen"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Ermöglicht einer App die Verwendung des SIP-Dienstes zum Tätigen/Annehmen von Internetanrufen"</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"Bisherige Netzwerkauslastung lesen"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Ermöglicht einer App, Daten zur bisherigen Netzwerkauslastung für bestimmte Netzwerke und Apps zu lesen"</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"Netzwerkrichtlinien verwalten"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Ermöglicht einer App, Netzwerkrichtlinien zu verwalten und app-spezifische Regeln festzulegen"</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"Zuordnung für Netzwerknutzung ändern"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Hiermit können Sie ändern, wie die Netzwerknutzung Apps zugeordnet wird. Kann nicht von normalen Apps genutzt werden."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Zulässige Länge und Zeichen für Passwörter zum Entsperren des Displays festlegen"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Versuche zum Entsperren des Displays überwachen"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Legen Sie fest, wie häufig das Passwort zum Sperren des Bildschirms geändert werden muss."</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Speicherverschlüsselung"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Anforderung, dass gespeicherte Anwendungsdaten verschlüsselt werden"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Kameras deaktivieren"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Nutzung sämtlicher Gerätekameras unterbinden"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Privat"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Keine SIM-Karte im Tablet"</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Keine SIM-Karte im Telefon"</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Bitte legen Sie eine SIM-Karte ein."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"SIM-Karte fehlt oder ist nicht lesbar. Bitte legen Sie eine SIM-Karte ein."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Ihre SIM-Karte wurde dauerhaft deaktiviert."\n" Bitte wenden Sie sich an Ihren Mobilfunkanbieter, um eine andere SIM-Karte zu erhalten."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Nur Notrufe"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Netzwerk gesperrt"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"PUK-Sperre auf SIM"</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Wenn Sie den USB-Speicher aktivieren, werden einige von Ihnen verwendete Anwendungen angehalten und sind möglicherweise nicht verfügbar, bis Sie den USB-Speicher wieder deaktivieren."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-Vorgang fehlgeschlagen"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB-Sp. formatieren"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD-Karte formatieren"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Eingabehilfen"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Hintergrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Hintergrund ändern"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Point-to-Point-Tunneling-Protokoll"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer-2-Tunneling-Protokoll"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec-VPN mit vorinstalliertem Schlüssel"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec-VPN mit Zertifikat"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Zum Verwalten des Netzwerks tippen"</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Verbunden mit <xliff:g id="SESSION">%s</xliff:g>. Zum Verwalten des Netzwerks tippen"</string>
     <string name="upload_file" msgid="2897957172366730416">"Datei auswählen"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Keine ausgewählt"</string>
     <string name="reset" msgid="2448168080964209908">"Zurücksetzen"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Elemente löschen"</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Löschen rückgängig machen"</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Im Moment nichts unternehmen"</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> mit VPN verbunden"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> von VPN getrennt"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Zur Wiederherstellung der Verbindung mit einem VPN berühren"</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Konto auswählen"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Erhöhen"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Verringern"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD-Karte"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-Speicher"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Bearbeiten..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Warnung zu Datennutzung"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"Datennutzung liegt über <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-/3G-Daten deaktiviert"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G-Daten deaktiviert"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobile Daten deaktiviert"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"Zum Aktivieren klicken"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Sicherheitszertifikat"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Dies ist ein gültiges Zertifikat."</string>
+    <string name="issued_to" msgid="454239480274921032">"Ausgestellt für:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Allgemeiner Name:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organisation:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Organisationseinheit:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Ausgestellt von:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Gültigkeit:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Ausgegeben am:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Läuft ab am:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 65d04b4..ae72132 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Λειτουργία πτήσης"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Η λειτουργία πτήσης είναι ενεργοποιημένη."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Η λειτουργία πτήσης είναι απενεργοποιημένη"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Ασφαλής λειτουργία"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Σύστημα Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Υπηρεσίες επί πληρωμή"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"εγγραφή δεδομένων επαφής"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Επιτρέπει σε μια εφαρμογή να τροποποιεί τα δεδομένα επαφής (διεύθυνσης) που είναι αποθηκευμένα στο tablet σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να διαγράψουν ή να τροποποιήσουν τα δεδομένα επαφών σας."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Επιτρέπει σε μια εφαρμογή να τροποποιεί τα δεδομένα επαφής (διεύθυνσης) που είναι αποθηκευμένα στο τηλέφωνό σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να διαγράψουν ή να τροποποιήσουν τα δεδομένα επαφών σας."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"ανάγνωση δεδομένων προφίλ"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Επιτρέπει σε μια εφαρμογή την ανάγνωση όλων των προσωπικών στοιχείων προφίλ. Οι κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να εξακριβώσουν την ταυτότητά σας και για να στείλουν τα προσωπικά σας στοιχεία σε άλλους χρήστες."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"εγγραφή δεδομένων προφίλ"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Επιτρέπει σε μια εφαρμογή την τροποποίηση των προσωπικών στοιχείων προφίλ. Οι κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να διαγράψουν ή να τροποποιήσουν τα προσωπικά σας δεδομένα."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"ανάγνωση συμβάντων ημερολογίου"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Επιτρέπει σε μια εφαρμογή να αναγνώσει όλα τα συμβάντα ημερολογίου που είναι αποθηκευμένα στο tablet σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να αποστείλουν συμβάντα ημερολογίου σε άλλους χρήστες."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Επιτρέπει σε μια εφαρμογή να αναγνώσει όλα τα συμβάντα ημερολογίου που είναι αποθηκευμένα στο τηλέφωνό σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να αποστείλουν συμβάντα ημερολογίου σε άλλους χρήστες."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Επιτρέπει σε μια εφαρμογή την ανάγνωση και την εγγραφή του συστήματος αρχείων προσωρινής μνήμης."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"πραγματοποίηση/λήψη κλήσεων μέσω Διαδικτύου"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Επιτρέπει σε μια εφαρμογή τη χρήση της υπηρεσίας SIP για την πραγματοποίηση/λήψη κλήσεων μέσω Διαδικτύου."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"ανάγνωση ιστορικών δεδομένων χρήσης δικτύου"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Επιτρέπει σε μια εφαρμογή την ανάγνωση ιστορικών στοιχείων χρήσης δικτύου για συγκεκριμένα δίκτυα και εφαρμογές."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"διαχείριση πολιτικής δικτύου"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Επιτρέπει σε μια εφαρμογή τη διαχείριση των πολιτικών δικτύου και τον ορισμό κανόνων για ορισμένες εφαρμογές."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"τροποποίηση υπολογισμού χρήσης δικτύου"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Επιτρέπει την τροποποίηση του τρόπου υπολογισμού χρήσης του δικτύου συγκριτικά με άλλες εφαρμογές. Δεν προορίζεται για χρήση από τις συνήθεις εφαρμογές."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Έλεγχος του μεγέθους και των χαρακτήρων που επιτρέπονται στους κωδικούς πρόσβασης ξεκλειδώματος οθόνης"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Επιλέξτε πόσο συχνά θα πρέπει να αλλάζει ο κωδικός πρόσβασης κλειδώματος οθόνης"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Ορισμός κρυπτογρ. αποθ. χώρου"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Να απαιτείται η κρυπτογράφηση των αποθηκευμένων δεδομένων εφαρμογής"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Απενεργοποίηση φωτογρ. μηχανών"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Να αποτρέπεται η χρήση των φωτογραφικών μηχανών της συσκευής"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Οικία"</item>
     <item msgid="869923650527136615">"Κινητό"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Δεν υπάρχει κάρτα SIM στο tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Δεν υπάρχει κάρτα SIM στο τηλέφωνο."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Τοποθετήστε μια κάρτα SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Η κάρτα SIM δεν υπάρχει ή δεν είναι δυνατή η ανάγνωσή της. Τοποθετήστε μια κάρτα SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Η κάρτα SIM απενεργοποιήθηκε οριστικά."\n" Επικοινωνήστε με τον παροχέα υπηρεσιών ασύρματου δικτύου για να λάβετε νέα κάρτα SIM."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Μόνο κλήσεις έκτακτης ανάγκης"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Το δίκτυο κλειδώθηκε"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Η κάρτα SIM είναι κλειδωμένη με κωδικό PUK."</string>
@@ -887,7 +877,7 @@
     <string name="new_app_action" msgid="5472756926945440706">"Εκκίνηση της εφαρμογής <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
     <string name="new_app_description" msgid="6830398339826789493">"Διακόψτε την παλιά εφαρμογή χωρίς αποθήκευση."</string>
     <string name="sendText" msgid="5132506121645618310">"Επιλέξτε μια ενέργεια για το κείμενο"</string>
-    <string name="volume_ringtone" msgid="6885421406845734650">"Ένταση ειδοποίησης ήχου"</string>
+    <string name="volume_ringtone" msgid="6885421406845734650">"Ένταση ήχου ειδοποίησης"</string>
     <string name="volume_music" msgid="5421651157138628171">"Ένταση ήχου πολυμέσων"</string>
     <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Αναπαραγωγή μέσω Bluetooth"</string>
     <string name="volume_music_hint_silent_ringtone_selected" msgid="6158339745293431194">"Επιλέχτηκε αθόρυβος ήχος κλήσης"</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Εάν ενεργοποιήσετε τον αποθηκευτικό χώρο USB, ορισμένες από τις εφαρμογές που χρησιμοποιείτε θα σταματήσουν και ενδέχεται να μην είναι διαθέσιμες μέχρι να απενεργοποιήσετε τον αποθηκευτικό χώρο USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Απέτυχε η λειτουργία USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"ΟΚ"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Διαγρ. απ. χώρου USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Διαμόρφωση κάρτας SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Προσβασιμότητα"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ταπετσαρία"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Αλλαγή ταπετσαρίας"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Πρωτόκολλο Point-to-Point Tunneling Protocol (PPTP)"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Πρωτόκολλο Layer 2 Tunneling Protocol (L2TP)"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Κλειδί pre-shared βάσει L2TP/IPSec VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Πιστοποιητικό βάσει L2TP/IPSec VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Πατήστε για να διαχειριστείτε το δίκτυο."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Συνδέθηκε με <xliff:g id="SESSION">%s</xliff:g>. Πατήστε για να διαχειριστείτε το δίκτυο."</string>
     <string name="upload_file" msgid="2897957172366730416">"Επιλογή αρχείου"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Δεν έχει επιλεγεί αρχείο"</string>
     <string name="reset" msgid="2448168080964209908">"Επαναφορά"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Διαγραφή των αντικειμένων."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Αναίρεση των διαγραφών."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Να μην γίνει καμία ενέργεια τώρα."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"Το VPN <xliff:g id="PROFILENAME">%s</xliff:g> συνδέθηκε"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"Το VPN <xliff:g id="PROFILENAME">%s</xliff:g> αποσυνδέθηκε"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Αγγίξτε για να επανασυνδεθείτε σε ένα VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Επιλογή λογαριασμού"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Αύξηση"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Μείωση"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Κάρτα SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Χώρος αποθήκευσης USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Επεξεργασία..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Προειδοποίηση χρήσης δεδομένων"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"η χρήση υπερβαίνει τα <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Τα δεδ. 2G-3G απενεργοποιήθηκαν"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Τα δεδομένα 4G απενεργοποιήθηκαν"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Τα δεδομ. κιν. τηλεφ. απενεργοπ."</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"πατήστε για ενεργοποίηση"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Πιστοποιητικό ασφαλείας"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Αυτό το πιστοποιητικό είναι έγκυρο."</string>
+    <string name="issued_to" msgid="454239480274921032">"Εκδόθηκε σε:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Κοινό όνομα:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Οργανισμός:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Μονάδα οργάνωσης:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Εκδόθηκε από:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Ισχύς:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Εκδόθηκε στις:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Λήγει στις:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 903e75f..d26628c 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -491,6 +491,8 @@
     <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Allows an application to read historical network usage for specific networks and applications."</string>
     <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"manage network policy"</string>
     <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Allows an application to manage network policies and define application-specific rules."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modify network usage accounting"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Allows modification of how network usage is accounted against applications. Not for use by normal applications."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Control the length and the characters allowed in screen-unlock passwords"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
@@ -942,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"If you turn on USB storage, some applications that you are using will stop and may be unavailable until you turn off USB storage."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB operation failed"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format USB storage"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Format SD card"</string>
@@ -1009,12 +1015,10 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibility"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Change wallpaper"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Point-to-Point Tunnelling Protocol"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunnelling Protocol"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Pre-shared key-based L2TP/IPSec VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Certificate-based L2TP/IPSec VPN"</string>
-    <string name="vpn_ticker" msgid="285642105845608311">"<xliff:g id="APP">%s</xliff:g> is activating VPN..."</string>
-    <string name="vpn_title" msgid="5434034606697234123">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
+    <!-- no translation found for vpn_title (8219003246858087489) -->
+    <skip />
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
+    <skip />
     <string name="vpn_text" msgid="1610714069627824309">"Tap to manage the network."</string>
     <string name="vpn_text_long" msgid="4907843483284977618">"Connected to <xliff:g id="SESSION">%s</xliff:g>. Tap to manage the network."</string>
     <string name="upload_file" msgid="2897957172366730416">"Choose file"</string>
@@ -1065,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Delete the items."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Undo the deletions."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Do nothing for now."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN connected"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN disconnected"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Touch to reconnect to a VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Select an account"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Increment"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Decrement"</string>
@@ -1084,4 +1085,28 @@
     <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G data disabled"</string>
     <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobile data disabled"</string>
     <string name="data_usage_limit_body" msgid="2182247539226163759">"Tap to enable"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Security certificate"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"This certificate is valid."</string>
+    <string name="issued_to" msgid="454239480274921032">"Issued to:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Common name:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organisation:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Organisational unit:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Issued by:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Validity:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Issued on:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Expires on:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
+    <skip />
+    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <skip />
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
+    <skip />
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index e28bd25..305b131 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -108,7 +108,7 @@
     <string name="fcError" msgid="3327560126588500777">"Problema de conexión o código de función no válido."</string>
     <string name="httpErrorOk" msgid="1191919378083472204">"Aceptar"</string>
     <string name="httpError" msgid="2567300624552921790">"La página web contiene un error."</string>
-    <string name="httpErrorLookup" msgid="4517085806977851374">"No se ha podido encontrar la URL."</string>
+    <string name="httpErrorLookup" msgid="4517085806977851374">"No se ha podido encontrar la dirección URL."</string>
     <string name="httpErrorUnsupportedAuthScheme" msgid="2781440683514730227">"No se admite el programa de autenticación del sitio."</string>
     <string name="httpErrorAuth" msgid="7293960746955020542">"La autenticación no se ha realizado correctamente."</string>
     <string name="httpErrorProxyAuth" msgid="1788207010559081331">"La autenticación a través del servidor proxy no se ha realizado correctamente."</string>
@@ -118,7 +118,7 @@
     <string name="httpErrorRedirectLoop" msgid="8679596090392779516">"La página contiene demasiados redireccionamientos de servidor."</string>
     <string name="httpErrorUnsupportedScheme" msgid="5257172771607996054">"No se admite el protocolo."</string>
     <string name="httpErrorFailedSslHandshake" msgid="3088290300440289771">"No se ha podido establecer una conexión segura."</string>
-    <string name="httpErrorBadUrl" msgid="6088183159988619736">"No se ha podido abrir la página debido a que la URL es incorrecta."</string>
+    <string name="httpErrorBadUrl" msgid="6088183159988619736">"No se ha podido abrir la página debido a que la dirección URL es incorrecta."</string>
     <string name="httpErrorFile" msgid="8250549644091165175">"No se ha podido acceder al archivo."</string>
     <string name="httpErrorFileNotFound" msgid="5588380756326017105">"No se ha encontrado el archivo solicitado."</string>
     <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Se están procesando demasiadas solicitudes. Vuelve a intentarlo más tarde."</string>
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avión"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"El modo avión está Encendido"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"El modo avión está Apagado"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100 +"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicios que te cuestan dinero"</string>
@@ -210,7 +210,7 @@
     <string name="permlab_removeTasks" msgid="4802740047161700683">"detener las aplicaciones en ejecución"</string>
     <string name="permdesc_removeTasks" msgid="2000332928514575461">"Permite que una aplicación elimine tareas y aplicaciones. Las aplicaciones maliciosas pueden alterar el comportamiento de otras aplicaciones."</string>
     <string name="permlab_setDebugApp" msgid="4339730312925176742">"activar la depuración de la aplicación"</string>
-    <string name="permdesc_setDebugApp" msgid="5584310661711990702">"Admite una aplicación que activa la depuración en otra aplicación. Las aplicaciones maliciosas pueden utilizarlo para suprimir otras aplicaciones."</string>
+    <string name="permdesc_setDebugApp" msgid="5584310661711990702">"Admite una aplicación que activa la depuración en otra aplicación. Las aplicaciones maliciosas pueden utilizarlo para eliminar otras aplicaciones."</string>
     <string name="permlab_changeConfiguration" msgid="8214475779521218295">"cambiar tu configuración de la interfaz de usuario"</string>
     <string name="permdesc_changeConfiguration" msgid="3465121501528064399">"Admite una aplicación para cambiar la configuración actual, como el tamaño de fuente local o general."</string>
     <string name="permlab_enableCarMode" msgid="5684504058192921098">"habilitar el modo de auto"</string>
@@ -232,7 +232,7 @@
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"verificar y controlar todos los lanzamientos de actividades"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Permite que una aplicación verifique y controle el lanzamiento de actividades por parte del sistema. Las aplicaciones maliciosas pueden comprometer totalmente el sistema. Este permiso sólo es necesario para el desarrollo, nunca para el uso normal del teléfono."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"enviar emisión de paquete eliminado"</string>
-    <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Admite una aplicación que emite una notificación acerca de que se ha eliminado un paquete de aplicación. Las aplicaciones maliciosas pueden utilizarlo para suprimir cualquier otra aplicación en ejecución."</string>
+    <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Admite una aplicación que emite una notificación acerca de que se ha eliminado un paquete de aplicación. Las aplicaciones maliciosas pueden utilizarlo para eliminar cualquier otra aplicación en ejecución."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"enviar emisiones de SMS recibidos"</string>
     <string name="permdesc_broadcastSmsReceived" msgid="9122419277306740155">"Admite una aplicación que envía una notificación acerca de que se ha recibido un mensaje SMS. Las aplicaciones maliciosas pueden utilizarlo para falsificar los mensajes SMS entrantes."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"enviar emisiones WAP-PUSH-recibido"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"escribir datos de contacto"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite que una aplicación modifique los datos de (dirección) guardados en tu tablet. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar los datos de contacto."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Admite una aplicación que modifica los datos de (dirección de) contacto guardados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar los datos de contacto."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"leer los datos del perfil"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Permite que una aplicación lea toda la información de tu perfil personal. Las aplicaciones maliciosas pueden utilizar esto para identificarte y enviar tu información personal a otras personas."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"escribir datos del perfil"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Permite que una aplicación modifique la información de tu perfil personal. Las aplicaciones maliciosas pueden utilizar esto para borrar o modificar los datos de tu perfil."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"Leer eventos del calendario"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permite que una aplicación lea todos los eventos de calendario almacenados en tu tablet. Las aplicaciones maliciosas pueden utilizarlo para enviar tus eventos de calendario a otras personas."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Admite que una aplicación lea todos los eventos de calendario almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para enviar tus eventos de calendario a otras personas."</string>
@@ -434,7 +430,7 @@
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"actuar como autenticador de cuenta"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Permite a una aplicación utilizar las capacidades del autenticador de cuentas del Administrador de la cuenta, incluida la creación de cuentas, y la obtención y configuración de sus contraseñas."</string>
     <string name="permlab_manageAccounts" msgid="4440380488312204365">"administrar la lista de cuentas"</string>
-    <string name="permdesc_manageAccounts" msgid="8804114016661104517">"Permite a una aplicación ejecutar operaciones, tales como agregar y eliminar cuentas, y suprimir sus contraseñas."</string>
+    <string name="permdesc_manageAccounts" msgid="8804114016661104517">"Permite a una aplicación ejecutar operaciones, tales como agregar y eliminar cuentas, y eliminar sus contraseñas."</string>
     <string name="permlab_useCredentials" msgid="6401886092818819856">"usar las credenciales de autenticación de una cuenta"</string>
     <string name="permdesc_useCredentials" msgid="7416570544619546974">"Permite a una aplicación solicitar tokens de autenticación."</string>
     <string name="permlab_accessNetworkState" msgid="6865575199464405769">"ver estado de la red"</string>
@@ -481,8 +477,8 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Admite una aplicación para leer palabras, nombres y frases privadas que posiblemente el usuario haya almacenado en el diccionario del usuario."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"escribir al diccionario definido por el usuario"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Admite una aplicación que escribe palabras nuevas en el diccionario del usuario."</string>
-    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modificar o suprimir el contenido del almacenamiento USB"</string>
-    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificar/suprimir el contenido de la tarjeta SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modificar o eliminar el contenido del almacenamiento USB"</string>
+    <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificar/eliminar el contenido de la tarjeta SD"</string>
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Permite que una aplicación escriba en el almacenamiento USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Admite que una aplicación escriba en la tarjeta SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"modificar/eliminar los contenidos del almacenamientos de medios internos"</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite que una aplicación lea y escriba el sistema de archivos caché."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"realizar o recibir llamadas por Internet"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Permite que una aplicación utilice el servicio SIP para realizar o recibir llamadas por Internet."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"leer uso histórico de la red"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Permite que una aplicación lea el uso histórico de la red de redes y aplicaciones específicas."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"gestionar la política de la red"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Permite que una aplicación gestione las políticas de red y defina las reglas específicas de la aplicación."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"Modificar la administración del uso de redes"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Permite modificar la manera en la que se administra el uso de redes según la aplicación, salvo en el caso de aplicaciones normales."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlar la longitud y los caracteres permitidos en las contraseñas para desbloquear la pantalla"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa los intentos para desbloquear la pantalla"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar cuán a menudo se debe cambiar la contraseña de bloqueo de pantalla"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Establecer la encriptación del almacenamiento"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Requiere que los datos almacenados de la aplicación estén encriptados"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Desactivar cámaras"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Evita el uso de todas las cámaras del dispositivo"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Celular"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No hay tarjeta SIM en el tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No hay tarjeta SIM en el teléfono."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Inserta una tarjeta SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Falta la tarjeta SIM o no es legible. Introduce una tarjeta SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Tu tarjeta SIM ha sido permanentemente desactivada."\n" Comunícate con tu proveedor de servicios inalámbricos para obtener una nueva tarjeta SIM."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Sólo llamadas de emergencia"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Red bloqueada"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"La tarjeta SIM está bloqueada con PUK."</string>
@@ -681,7 +671,7 @@
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"¿Olvidaste el patrón?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Desbloquear cuenta"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="2446246026221678244">"Demasiados intentos de patrón."</string>
-    <string name="lockscreen_glogin_instructions" msgid="1816635201812207709">"Para desbloquear, regístrate en tu cuenta de Google"</string>
+    <string name="lockscreen_glogin_instructions" msgid="1816635201812207709">"Para desbloquear, regístrate en tu Cuenta de Google"</string>
     <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Nombre de usuario (correo electrónico)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Contraseña"</string>
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Inicia sesión"</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si activas el almacenamiento USB, algunas aplicaciones que estás usando se detendrán y es posible que no estén disponibles hasta que desactives el almacenamiento USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Error en el funcionamiento del USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Aceptar"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatear almacenamiento USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatear tarjeta SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accesibilidad"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Papel tapiz"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Protocolo de túnel punto a punto"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocolo de túnel de nivel 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec basada en clave compartida previamente"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec basada en certificado"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Pulsa para gestionar la red."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Pulsa para gestionar la red."</string>
     <string name="upload_file" msgid="2897957172366730416">"Elegir archivo"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"No se seleccionó un archivo."</string>
     <string name="reset" msgid="2448168080964209908">"Restablecer"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Eliminar artículos."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Deshacer eliminaciones."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"No hagas nada por el momento."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN conectados"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN desconectada"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Tocar para volver a conectarse a una VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Seleccionar una cuenta"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Incremento"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Decremento"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Tarjeta SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Almacenamiento USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Editar..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Advertencia de uso de datos"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"el uso supera <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Datos de 2 GB - 3 GB desactivados"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Datos de 4 GB desactivados"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Datos móviles desactivados"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"pulsa para habilitarla"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Certificado de seguridad"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Este certificado es válido."</string>
+    <string name="issued_to" msgid="454239480274921032">"Emitido a:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Nombre habitual:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organización:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Unidad organizativa:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Emitido por:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Validez:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Emitido:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Expira el:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index c048b99..f3d1d66 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avión"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modo avión activado. Desactivar."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modo avión desactivado. Activar."</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"+100"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt; 999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicios por los que tienes que pagar"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"escribir datos de contacto"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite que una aplicación modifique los datos de contacto (direcciones) almacenados en el tablet. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar los datos de contacto."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permite que una aplicación modifique los datos de contacto (direcciones) almacenados en el teléfono. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar tus datos de contacto."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"leer datos de perfil"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Permite que una aplicación lea toda la información de tu perfil personal. Las aplicaciones malintencionadas pueden utilizar este permiso para identificarte y para enviar tu información personal a otros usuarios."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"escribir datos de perfil"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Permite que una aplicación modifique la información de tu perfil personal. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o para modificar los datos de tu perfil."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"leer eventos de calendario"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permite que una aplicación lea todos los eventos de calendario almacenados en el tablet. Las aplicaciones malintencionadas pueden utilizar este permiso para enviar tus eventos de calendario a otras personas."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permite que una aplicación lea todos los eventos de calendario almacenados en el teléfono. Las aplicaciones malintencionadas pueden utilizar este permiso para enviar tus eventos de calendario a otras personas."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite que una aplicación lea y escriba el sistema de archivos almacenado en caché."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"realizar/recibir llamadas por Internet"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Permite que una aplicación utilice el servicio SIP para realizar o recibir llamadas de Internet."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"leer uso de red histórico"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Permite que una aplicación lea el uso de red histórico de redes y de aplicaciones específicas."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"administrar política de red"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Permite que una aplicación administre las políticas de red y defina las reglas específicas de la aplicación."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificar cálculo de uso de red"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Permite modificar la forma de cálculo del uso de red de las aplicaciones. No se debe utilizar con aplicaciones normales."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecimiento de reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Control de la longitud y de los caracteres permitidos en las contraseñas de bloqueo de pantalla"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Control de intentos de bloqueo de pantalla"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar la frecuencia con la que se debe cambiar el bloqueo de pantalla"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Encriptación de almacenamiento"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Exige que se encripten los datos de la aplicación almacenados."</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Inhabilitar cámaras"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Evitar el uso de las cámaras del dispositivo"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Móvil"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No se ha insertado ninguna tarjeta SIM en el tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No se ha insertado ninguna tarjeta SIM en el teléfono."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Inserta una tarjeta SIM"</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Falta la tarjeta SIM o no es legible. Introduce una tarjeta SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Tu tarjeta SIM se ha inhabilitado de forma permanente."\n" Ponte en contacto con tu proveedor de servicios inalámbricos para obtener otra tarjeta SIM."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Solo llamadas de emergencia"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Bloqueada para la red"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"La tarjeta SIM está bloqueada con el código PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si activas el almacenamiento USB, se detendrán algunas aplicaciones que estás utilizando y estas no estarán disponibles hasta que lo desactives."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"No se ha podido realizar la operación USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Aceptar"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatear USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatear tarjeta SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accesibilidad"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fondo de pantalla"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Protocolo de túnel punto a punto"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocolo de túnel de nivel 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Red privada virtual L2TP/IPSec basada en clave compartida previamente"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Red privada virtual L2TP/IPSec basada en certificado"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Toca para administrar la red."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toca para administrar la red."</string>
     <string name="upload_file" msgid="2897957172366730416">"Seleccionar archivo"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Archivo no seleccionado"</string>
     <string name="reset" msgid="2448168080964209908">"Restablecer"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Eliminar los elementos"</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Deshacer las eliminaciones"</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"No hacer nada por ahora"</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> conectada"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> desconectada"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Toca para volver a conectarte a una red VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Seleccionar una cuenta"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Aumentar"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Disminuir"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Tarjeta SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Almacenamiento USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Editar..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Advertencia de uso de datos"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"uso supera <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Datos 2G-3G inhabilitados"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Datos 4G inhabilitados"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Datos móviles inhabilitados"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"tocar para habilitar"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Certificado de seguridad"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Este certificado es válido."</string>
+    <string name="issued_to" msgid="454239480274921032">"Emitido para:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Nombre común:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organización:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Departamento:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Emitido por:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Validez:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Fecha de emisión:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Fecha de caducidad:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 4ea2aa7..aae9760 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"حالت هواپیما"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"حالت هواپیما روشن است"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"حالت هواپیما خاموش است"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"بیشتر از 999"</string>
     <string name="safeMode" msgid="2788228061547930246">"حالت ایمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"سیستم Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"سرویس های غیر رایگان"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"نوشتن اطلاعات تماس"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"به یک برنامه کاربردی اجازه می دهد اطلاعات تماس (آدرس) ذخیره شده در رایانه لوحی شما را تغییر دهد. برنامه های مضر می توانند از این امکان برای حذف یا تغییر اطلاعات تماس شما استفاده کنند."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"به یک برنامه کاربردی اجازه می دهد اطلاعات تماس (آدرس) ذخیره شده در گوشی شما را تغییر دهد. برنامه های مضر می توانند از این امکان برای حذف یا تغییر اطلاعات تماس شما استفاده کنند."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"خواندن داده های نمایه"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"به برنامه امکان می دهد تا تمام اطلاعات نمایه شخصی شما را بخواند. برنامه های مضر می توانند از این حالت برای شناسایی شما و ارسال اطلاعات شخصی شما به سایر افراد استفاده کنند."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"نوشتن داده های نمایه"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"به یک برنامه امکان می دهد تا اطلاعات نمایه شخصی شما را تغییر دهد. برنامه های مضر می توانند از این حالت برای پاک کردن یا تغییر داده های نمایه شما استفاده کنند."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"خواندن رویدادهای تقویم"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"به یک برنامه کاربردی اجازه می دهد که تمام رویدادهای تقویم ذخیره شده در رایانه لوحی شما را بخواند. برنامه های مضر می توانند از این ویژگی برای ارسال رویدادهای تقویم شما به سایر افراد استفاده کنند."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"به یک برنامه کاربردی اجازه می دهد که تمام رویدادهای تقویم ذخیره شده در گوشی شما را بخواند. برنامه های کاربردی مضر می توانند از این ویژگی برای ارسال رویدادهای تقویم شما به سایر افراد استفاده کنند."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"به یک برنامه کاربردی امکان می دهد سیستم فایل حافظه پنهان را بخواند و بنویسد."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"علامتگذاری/دریافت تماس های اینترنتی"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"به یک برنامه کاربردی اجازخ می دهد از سرویس SIP جهت برقراری یا دریافت تماس های اینترنتی استفاده کند."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"خواندن سابقه استفاده از شبکه"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"به برنامه اجازه می دهد تا میزان سابقه مصرف شبکه را برای برخی از شبکه ها و برنامه های خاص بخواند."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"مدیریت خط مشی شبکه"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"به یک برنامه امکان می دهد تا خط مشی های شبکه را مدیریت کرده و قوانین خاص یک برنامه را تعیین کند."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"اصلاح محاسبه استفاده از شبکه"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"امکان اصلاح نحوه محاسبه استفاده از شبکه توسط برنامه های کاربردی را فراهم می سازد. برای استفاده توسط برنامه های کاربردی عادی نیست."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین رمز ورود"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"کنترل طول و نویسه های مجاز رمزهای ورود قفل گشایی صفحه"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"نمایش تلاش های قفل گشایی صفحه"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"کنترل تعداد دفعات تغییر رمز ورود قفل صفحه"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"تنظیم رمزگذاری حافظه"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"نیاز به رمزگذاری داده های برنامه کاربردی ذخیره شده دارد"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"غیر فعال کردن دوربین ها"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"مانع از استفاده از تمام دوربین های دستگاه می شود"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"خانه"</item>
     <item msgid="869923650527136615">"تلفن همراه"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"سیم کارت درون رایانه لوحی نیست."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"سیم کارت درون تلفن نیست."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"لطفاً سیم کارت را وارد کنید."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"سیم کارت موجود نیست یا قابل خواندن نیست. یک سیم کارت وارد کنید."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"سیم کارت شما به صورت دائمی غیرفعال شده است."\n" برای دریافت یک سیم کارت دیگر با ارائه دهنده خدمات بی سیم خود تماس بگیرید."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"فقط تماس های اضطراری"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"شبکه قفل شد"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"سیم کارت با PUK قفل شده است."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"در صورت روشن کردن دستگاه ذخیره سازی USB، برخی از برنامه هایی که از آنها استفاده می کنید متوقف می شوند و تا زمانی که دستگاه ذخیره سازی USB را خاموش نکنید امکان استفاده از آنها وجود نخواهد داشت."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"عملکرد USB انجام نشد"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"تأیید"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"فرمت کردن حافظه USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"فرمت کردن کارت SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"قابلیت دسترسی"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"تصویر زمینه"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"تغییر تصویر زمینه"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"پروتکل تونلینگ نقطه به نقطه"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"پروتکل تونلینگ لایه 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN بر پایه کلید از پیش مشترک شده"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN وابسته به گواهی"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"برای مدیریت شبکه ضربه بزنید."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"به <xliff:g id="SESSION">%s</xliff:g> متصل شد. برای مدیریت شبکه ضربه بزنید."</string>
     <string name="upload_file" msgid="2897957172366730416">"انتخاب فایل"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"هیچ فایلی انتخاب نشد"</string>
     <string name="reset" msgid="2448168080964209908">"بازنشانی"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"موارد را حذف کنید."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"واگرد موارد حذف شده."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"اکنون هیچ کاری انجام نشود."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN وصل شد"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN قطع شد"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"برای اتصال مجدد به VPN لمس کنید."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"انتخاب یک حساب"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"افزایش"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"کاهش"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"کارت SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"حافظه USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"ویرایش..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"هشدار میزان استفاده از داده"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"استفاده از <xliff:g id="SIZE">%s</xliff:g> بیشتر شده است"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"داده های 2G-3G غیرفعال شد"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"داده 4G غیر فعال شده است"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"داده های تلفن همراه غیرفعال شد"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"برای فعال کردن ضربه بزنید"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"گواهی امنیتی"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"این گواهی معتبر است."</string>
+    <string name="issued_to" msgid="454239480274921032">"صادر شده برای:"</string>
+    <string name="common_name" msgid="2233209299434172646">"نام معمولی:"</string>
+    <string name="org_name" msgid="6973561190762085236">"سازمان:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"واحد سازمانی:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"صادر شده توسط:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"اعتبار:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"تاریخ صدور:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"تاریخ انقضا:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 50c0268..962383a 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lentokonetila"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Lentokonetila on KÄYTÖSSÄ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Lentokonetila on POIS KÄYTÖSTÄ"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Maksulliset palvelut"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"kirjoita yhteystietoja"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Antaa sovelluksen muokata tablet-laitteellesi tallennettuja yhteystietoja (osoitteita). Haittasovellukset voivat käyttää tätä yhteystietojesi pyyhkimiseen tai muokkaamiseen."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Antaa sovelluksen muokata puhelimeen tallennettuja yhteystietoja (osoitteita). Haitalliset sovellukset voivat käyttää tätä yhteystietojen pyyhkimiseen tai muokkaamiseen."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"profiilitietojen lukeminen"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Sallii sovelluksen lukea yksityisiä profiilitietoja. Haittaohjelmat voivat käyttää tätä käyttäjien tunnistamiseen ja henkilötietojen levittämiseen muille."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"profiilitietojen kirjoittaminen"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Sallii sovelluksen muokata yksityisiä profiilitietoja. Haittaohjelmat voivat käyttää tätä profiilitietojen poistamiseen tai muokkaamiseen."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"lue kalenteritapahtumia"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Antaa sovelluksen tarkastella kaikkia tablet-laitteellesi tallennettuja kalenteritapahtumia. Haittasovellukset voivat käyttää tätä tietojesi lähettämiseen muille ihmisille."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Antaa sovelluksen lukea kaikki puhelimeesi tallennetut kalenteritapahtumat. Haittasovellukset voivat käyttää tätä ominaisuutta kalenteritapahtumiesi lähettämiseen muille."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Antaa sovelluksen lukea välimuistin tiedostojärjestelmää ja kirjoittaa sinne."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"soita/vastaanota internetpuheluita"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Antaa sovelluksen käyttää SIP-palvelua internetpuheluiden soittamiseen/vastaanottamiseen."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"verkonkäyttöhistorian lukeminen"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Sallii sovelluksen lukea tiettyjen verkkojen ja sovellusten verkonkäyttöhistoriaa."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"verkkokäytännön hallinnointi"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Sallii sovelluksen hallinnoida verkkokäytäntöä ja määritellä sovelluskohtaisia sääntöjä."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"verkon käytön seurannan muokkaaminen"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Mahdollistaa verkon käytön sovelluskohtaisen seurannan muokkaamisen. Ei tavallisten sovellusten käytössä."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Aseta salasanasäännöt"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Hallinnoi ruudun lukituksenpoistosalasanoissa sallittuja merkkejä ja salasanan pituutta"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Tarkkaile ruudun lukituksen poistoyrityksiä"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Määritä, miten usein ruudunlukituksen salasana tulee vaihtaa"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Aseta tallennustilan salaus"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Pakota tallennettujen sovellustietojen salaus"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Poista kamerat käytöstä"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Estä laitteen kaikkien kameroiden käyttö"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Puhelinnumero (koti)"</item>
     <item msgid="869923650527136615">"Mobiili"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tablet-laitteessa ei ole SIM-korttia."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Puhelimessa ei ole SIM-korttia."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Aseta SIM-kortti."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"SIM-korttia ei löydy tai ei voi lukea. Kytke SIM-kortti."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"SIM-kortti on poistettu pysyvästi käytöstä."\n" Ota yhteyttä operaattoriisi ja hanki uusi SIM-kortti."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Vain hätäpuhelut"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Verkko lukittu"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM-kortti on PUK-lukittu."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jos otat USB-tallennustilan käyttöön, osa käyttämistäsi sovelluksista pysähtyy eivätkä ne välttämättä ole käytössä kunnes poistat USB-tallennustilan käytöstä."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-toiminto epäonnistui"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Alusta USB-tila"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Alusta SD-kortti"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Esteettömyys"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Taustakuva"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Vaihda taustakuvaa"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Point-to-Point Tunneling Protocol"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunneling Protocol"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Esijaettuun avaimeen perustuva L2TP/IPSec-suojattu VPN-verkko"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Varmenteeseen perustuva L2TP/IPSec-suojattu VPN-verkko"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Napauta, niin voit hallinnoida verkkoa."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Yhdistetty: <xliff:g id="SESSION">%s</xliff:g>. Hallinnoi verkkoa napauttamalla."</string>
     <string name="upload_file" msgid="2897957172366730416">"Valitse tiedosto"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Ei valittua tiedostoa"</string>
     <string name="reset" msgid="2448168080964209908">"Palauta"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Poista kohteet."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Kumoa poistot."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Älä tee mitään."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g>: VPN-yhteys muodostettu"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g>: VPN-yhteys katkaistu"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Yhdistä VPN-verkkoon uudelleen koskettamalla."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Valitse tili"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Lisää"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Vähennä"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD-kortti"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-tallennustila"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Muokkaa..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Tiedonsiirtovaroitus"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"käyttö ylittää <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-3G-tiedonsiirto pois käytöstä"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G-tiedonsiirto pois käytöstä"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobiilitiedonsiirto pois käytöstä"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"ota käyttöön napauttamalla"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Suojausvarmenne"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Varmenne on voimassa."</string>
+    <string name="issued_to" msgid="454239480274921032">"Varmenteen saaja:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Yleinen nimi:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organisaatio:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Organisaatioyksikkö:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Myöntäjä:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Voimassa:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Myönnetty:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Vanhenee:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 8d95338..f9aa46e 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode Avion"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Le mode Avion est activé."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Le mode Avion est désactivé."</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100 +"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services payants"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"Édition des données d\'un contact"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permet à une application de modifier les données (adresses) associées à vos contacts et stockées sur votre tablette. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier les données de vos contacts."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permet à une application de modifier toutes les données de contact (adresses) enregistrées sur le téléphone. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier vos données de contact."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"lire les données de profil"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Permet à une application de lire toutes vos informations personnelles de profil. Des applications malveillantes peuvent l\'utiliser pour vous identifier et envoyer vos informations personnelles à d\'autres personnes."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"modifier les données de profil"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Permet à une application de modifier vos informations personnelles de profil. Des applications malveillantes peuvent utiliser cette autorisation pour effacer ou modifier les données de votre profil."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"lire des événements de l\'agenda"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permet à une application de lire tous les événements de l\'agenda enregistrés sur votre tablette. Des applications malveillantes peuvent exploiter cette fonctionnalité pour envoyer les événements de votre agenda à d\'autres personnes."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permet à une application de lire tous les événements de l\'agenda enregistrés sur votre téléphone. Des applications malveillantes peuvent exploiter cette fonctionnalité pour envoyer les événements de votre agenda à d\'autres personnes."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permet à une application de lire et d\'écrire dans le système de fichiers en cache."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"effectuer/recevoir des appels Internet"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Permet à une application d\'utiliser le service SIP pour effectuer/recevoir des appels Internet."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"lire l\'historique d\'utilisation du réseau"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Permet à une application de lire l\'historique d\'utilisation de réseaux et d\'applications spécifiques."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"gérer les règles du réseau"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Permet à une application de gérer les règles du réseau et de définir celles qui sont spécifiques à l\'application."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modifier le système de comptabilisation de l\'utilisation du réseau"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Permet de modifier la façon dont l\'utilisation du réseau est comptabilisée par rapport aux applications. Ne doit pas être utilisée par les applications standards."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Gérer le nombre et le type de caractères autorisés dans les mots de passe de déverrouillage de l\'écran"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Contrôler la fréquence de modification du mot de passe de verrouillage de l\'écran"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Définir chiffrement du stockage"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Exiger que les données d\'application stockées soient chiffrées"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Désactiver les appareils photo"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Empêcher l\'utilisation de tous les appareils photos"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domicile"</item>
     <item msgid="869923650527136615">"Mobile"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Aucune carte SIM n\'est insérée dans la tablette."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Aucune carte SIM n\'est insérée dans le téléphone."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Insérez une carte SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Aucune carte SIM ou carte SIM illisible. Veuillez insérer une carte SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Votre carte SIM est définitivement désactivée."\n" Veuillez contacter votre opérateur pour obtenir une autre carte SIM."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Appels d\'urgence uniquement"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Réseau verrouillé"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"La carte SIM est verrouillée par clé PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si vous activez la mémoire de stockage USB, certaines applications en cours d\'utilisation seront fermées. Elles risquent de rester indisponibles jusqu\'à ce que la mémoire de stockage USB soit désactivée."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Échec du fonctionnement USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formater la mémoire USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formater la carte SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibilité"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fond d\'écran"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Changer de fond d\'écran"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Protocole de tunnelisation point-à-point"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocole de tunnelisation de niveau 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec basé sur une clé pré-partagée"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec basé sur un certificat"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Appuyez ici pour gérer le réseau."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Connecté à <xliff:g id="SESSION">%s</xliff:g>. Appuyez ici pour gérer le réseau."</string>
     <string name="upload_file" msgid="2897957172366730416">"Sélectionner un fichier"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Aucun fichier sélectionné"</string>
     <string name="reset" msgid="2448168080964209908">"Réinitialiser"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Supprimer les éléments"</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Annuler les suppressions"</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Ne rien faire pour l\'instant"</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> connecté"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> déconnecté"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Appuyez ici pour vous reconnecter à un VPN"</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Sélectionner un compte"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Augmenter"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Diminuer"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Carte SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Mémoire de stockage USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Modifier..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Avertissement utilisation données"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"plus de <xliff:g id="SIZE">%s</xliff:g> utilisés"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Données 2G-3G désactivées"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Données 4G désactivées"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Données mobiles désactivées"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"appuyer pour activer"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Certificat de sécurité"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Ce certificat est valide."</string>
+    <string name="issued_to" msgid="454239480274921032">"Délivré à :"</string>
+    <string name="common_name" msgid="2233209299434172646">"Nom commun :"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organisation :"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Unité d\'organisation :"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Émis par :"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Validité :"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Date d\'émission :"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Date d\'expiration :"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 71d49cc..acb7f27 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Način rada u zrakoplovu"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Uključen je način rada u zrakoplovu"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Isključen je način rada u zrakoplovu"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sustav Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Usluge koje se plaćaju"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"pisanje kontaktnih podataka"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Aplikaciji omogućuje izmjenu kontaktnih podataka (adrese) koji su pohranjeni na vašem tabletnom uređaju. Zlonamjerne aplikacije mogu to upotrijebiti za brisanje ili izmjenu kontaktnih podataka."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Aplikaciji omogućuje izmjenu kontaktnih podataka (adrese) koji su pohranjeni na vašem telefonu. Zlonamjerne aplikacije to mogu koristiti za brisanje ili izmjenu vaših kontaktnih podataka."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"Pročitaj podatke profila"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Aplikaciji omogućuje čitanje informacija o vašem osobnom profilu. Zlonamjerne aplikacije mogu to upotrijebiti za vašu identifikaciju i slanje vaših osobnih podataka drugim ljudima."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"zapisivanje podataka profila"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Aplikaciji omogućuje izmjenu informacija o osobnom profilu. Zlonamjerne aplikacije mogu to upotrijebiti za brisanje ili izmjenu podataka o profilu."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"čitanje kalendarskih događaja"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Aplikaciji omogućuje čitanje svih događaja na kalendaru koji su pohranjeni na tabletnom uređaju. Zlonamjerne aplikacije to mogu upotrijebiti za slanje događaja na kalendaru drugim ljudima."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Aplikaciji omogućuje čitanje svih kalendarskih događaja pohranjenih na računalu. Zlonamjerne aplikacije to mogu koristiti za slanje kalendarskih događaja drugim ljudima."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Aplikaciji omogućuje čitanje i pisanje u sustav datoteka predmemorije."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"zovi/primaj internetske pozive"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Aplikaciji omogućuje upotrebu SIP usluge za nazivanje/primanje internetskih poziva."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"čitanje povijesti upotrebe mreže"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Aplikaciji omogućuje čitanje povijesti upotrebe mreže za određene mreže i aplikacije."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"Upravljanje mrežnim pravilima"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Aplikaciji omogućuje upravljanje mrežnim pravilima i određivanje pravila za aplikacije."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"izmjena evidencije mrežne upotrebe"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Omogućuje izmjenu načina upotrebe mreže u odnosu na aplikacije. Nije namijenjeno uobičajenim aplikacijama."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Postavi pravila zaporke"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Nadziri duljinu i znakove dopuštene u zaporci za otključavanje zaslona"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Nadgledaj pokušaje otključavanja zaslona"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Nadzirite koliko se često mora mijenjati zaporka za zaključavanje zaslona"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Postavi enkripciju za pohranu"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Zahtijevaj da pohranjeni podaci aplikacije budu kriptirani"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Onemogući fotoaparate"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Sprječava upotrebu svih fotoaparata uređaja"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Početna"</item>
     <item msgid="869923650527136615">"Mobilni"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"U tabletnom uređaju nema SIM kartice."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"U telefonu nema SIM kartice."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Umetnite SIM karticu."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Nedostaje SIM kartica ili nije čitljiva. Umetnite SIM karticu."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Vaša SIM kartica trajno je onemogućena."\n"Obratite se svom pružatelju bežičnih usluga za dobivanje druge SIM kartice."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Samo hitni pozivi"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Mreža je zaključana"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM kartica je zaključana PUK-om."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ako uključite USB pohranjivanje, neke aplikacije koje koristite zaustavit će se i možda neće biti dostupne sve dok ne isključite USB pohranjivanje."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Rad USB-a nije uspio"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"U redu"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format. USB memoriju"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatiraj SD karticu"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Dostupnost"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Pozadinska slika"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Promjena pozadinske slike"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Tunelni protokol od točke do točke"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Tunelni protokol sloja 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Unaprijed dijeljeni L2TP/IPSec VPN temeljen na ključu"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN temeljen na certifikatu"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Dotaknite za upravljanje mrežom."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Povezan sa sesijom <xliff:g id="SESSION">%s</xliff:g>. Dotaknite za upravljanje mrežom."</string>
     <string name="upload_file" msgid="2897957172366730416">"Odaberite datoteku"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nema odabranih datoteka"</string>
     <string name="reset" msgid="2448168080964209908">"Ponovo postavi"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Izbriši ove stavke."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Poništi brisanja."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Za sad nemoj ništa učiniti."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN priključen"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN je isključen"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Dotaknite za ponovno povezivanje s VPN-om."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Odaberite račun"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Povećaj"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Smanji"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD kartica"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB pohrana"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Uređivanje..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Upozorenje o upotrebi podataka"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"upotreba prelazi <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-3G podaci su onemogućeni"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G podaci su onemogućeni"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobilni podaci su onemogućeni"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"Dotaknite za omogućivanje"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Sigurnosni certifikat"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Ovaj je certifikat valjan."</string>
+    <string name="issued_to" msgid="454239480274921032">"Izdano za:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Zajednički naziv:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organizacija:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Organizacijska jedinica:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Izdao:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Vrijedi do:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Izdano dana:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Ističe dana:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index bbe635f..b27fb83 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Repülőgép üzemmód"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Repülőgép üzemmód bekapcsolva"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Repülőgép üzemmód kikapcsolva"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Biztonsági üzemmód"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android rendszer"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Fizetős szolgáltatások"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"névjegyadatok írása"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Lehetővé teszi az alkalmazások számára, hogy módosítsák a táblagépen tárolt névjegyadatokat (címeket). A rosszindulatú alkalmazások ezt felhasználhatják arra, hogy töröljék vagy módosítsák a névjegyadatokat."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Lehetővé teszi egy alkalmazás számára, hogy módosítsa a telefonon tárolt névjegy- (cím-) adatokat. A rosszindulatú alkalmazások felhasználhatják ezt a névjegyadatok törlésére vagy módosítására."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"profiladatok beolvasása"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Lehetővé teszi az alkalmazás számára, hogy beolvassa az összes személyes profiladatot. A rosszindulatú alkalmazások felhasználhatják ezt az Ön azonosítására, és személyes adatai elküldésére másoknak."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"profiladatok írása"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Lehetővé teszi az alkalmazás számára, hogy módosítsa az Ön személyes profiladatait. A rosszindulatú alkalmazások használhatják a profiladatok törlésére vagy módosítására."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"naptári események olvasása"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Lehetővé teszi az alkalmazások számára, hogy elolvassák a telefon naptárában lévő összes eseményt. A rosszindulatú alkalmazások ezt felhasználhatják arra, hogy elküldjék az eseményeket másoknak."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Lehetővé teszi az alkalmazás számára, hogy elolvassa a telefon naptárában lévő összes eseményt. A rosszindulatú alkalmazások ezt az események mások részére való elküldésére használhatják fel."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Lehetővé teszi egy alkalmazás számára a gyorsítótár fájlrendszerének olvasását és írását."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"internetes hívások kezdeményezése és fogadása"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Lehetővé teszi az alkalmazások számára a SIP-szolgáltatás használatát internetes hívások kezdeményezésére és fogadására."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"hálózathasználati előzmények beolvasása"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Lehetővé teszi az alkalmazás számára a hálózathasználat-előzmények beolvasását adott hálózatok és alkalmazások esetében."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"hálózati házirend kezelése"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Lehetővé teszi az alkalmazás számára, hogy kezelje a hálózati irányelveket és meghatározza az alkalmazás-specifikus szabályokat."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"hálózathasználat elszámolásának módosítása"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Lehetővé teszi a hálózathasználat elszámolásának módosítását a különböző alkalmazások esetén. Nem használható a normál alkalmazások esetén."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"A képernyőzár-feloldási jelszavakban engedélyezett karakterek és hosszúság vezérlése"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Képernyőzár-feloldási kísérletek figyelése"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Adja meg, hogy milyen gyakran kell módosítani a képernyőzár jelszavát"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Tárhelytitkosítás beállítása"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Megköveteli a tárolt alkalmazásadatok titkosítását"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Kamerák letiltása"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Az összes eszközkamera használatának megakadályozása"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Otthoni"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nincs SIM-kártya a táblagépben."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Nincs SIM-kártya a telefonban."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Kérjük, helyezzen be egy SIM-kártyát."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"A SIM-kártya hiányzik vagy nem olvasható. Helyezzen be egy SIM-kártyát."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"SIM-kártyája véglegesen letiltva."\n" Kérjük, forduljon a vezeték nélküli szolgáltatójához másik SIM-kártya beszerzése érdekében."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Csak segélyhívások"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"A hálózat lezárva"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"A SIM-kártya le van zárva a PUK-kóddal."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ha bekapcsolja az USB-tárat, egyes jelenleg használt alkalmazások leállnak és lehet, hogy nem lesznek elérhetők a tár újbóli kikapcsolásáig."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Az USB művelet sikertelen"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Az USB-tár formázása"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD-kártya formázása"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Kisegítő lehetőségek"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Háttérkép"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Háttérkép megváltoztatása"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"PPTP protokoll"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"L2TP protokoll"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Osztott kulcs (PSK) alapú L2TP/IPSec VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Tanúsítvány alapú L2TP/IPSec VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Érintse meg a hálózat irányításához."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Csatlakozva ide: <xliff:g id="SESSION">%s</xliff:g>. Érintse meg a hálózat kezeléséhez."</string>
     <string name="upload_file" msgid="2897957172366730416">"Fájl kiválasztása"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nincs fájl kiválasztva"</string>
     <string name="reset" msgid="2448168080964209908">"Alaphelyzet"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Az elemek törlése."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Törlés visszavonása."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Most nem."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"Kapcsolódva a(z) <xliff:g id="PROFILENAME">%s</xliff:g> virtuális magánhálózathoz"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"Bontotta a kapcsolatot a(z) <xliff:g id="PROFILENAME">%s</xliff:g> virtuális magánhálózattal"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Érintse meg az újracsatlakozáshoz."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Fiók kiválasztása"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Növelés"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Csökkentés"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD-kártya"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-tár"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Szerkesztés..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Adathasználati figyelmeztetés"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"Túllépte ezt a méretet: <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-3G adatforgalom letiltva"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G adatforgalom letiltva"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobil adatforgalom letiltva"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"koppintson az engedélyezéshez"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Biztonsági tanúsítvány"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"A tanúsítvány érvényes."</string>
+    <string name="issued_to" msgid="454239480274921032">"Kiállítva a következőnek:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Név:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Szervezet:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Szervezeti egység:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Kiállította:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Érvényesség:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Kiállítva:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Lejár:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 53d245a..2bfb6ce 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode pesawat"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mode pesawat HIDUP"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mode pesawat MATI"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode aman"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Layanan berbayar"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"tuliskan data kenalan"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Mengizinkan aplikasi memodifikasi data kenalan (alamat) yang disimpan pada tablet Anda. Aplikasi berbahaya dapat menggunakan ini untuk menghapus atau mengubah data kenalan."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Mengizinkan aplikasi mengubah data kenalan (alamat) yang tersimpan pada ponsel. Aplikasi hasad dapat menggunakan ini untuk menghapus atau mengubah data kenalan Anda."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"baca data profil"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Memungkinkan aplikasi membaca semua informasi profil pribadi Anda. Aplikasi berbahaya dapat menggunakannya untuk mengidentifikasi Anda dan mengirimkan informasi pribadi Anda kepada orang lain."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"tulis data profil"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Memungkinkan aplikasi mengubah informasi profil pribadi Anda. Aplikasi berbahaya dapat menggunakannya untuk menghapus atau mengubah data profil Anda."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"membaca acara kalender."</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Mengizinkan aplikasi membaca semua acara kalender yang disimpan pada tablet Anda. Aplikasi berbahaya dapat menggunakan ini untuk mengirim acara kalender ke orang lain."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Mengizinkan aplikasi membaca semua acara kalender yang tersimpan pada ponsel. Aplikasi hasad dapat menggunakan ini untuk mengirimkan acara kalender ke orang lain."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Mengizinkan aplikasi membaca dan menulis filesystem tembolok."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"lakukan//terima panggilan internet"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Mengizinkan aplikasi menggunakan layanan SIP melakukan/menerima telepon internet"</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"baca riwayat penggunaan jaringan"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Memungkinkan aplikasi membaca penggunaan jaringan historis untuk aplikasi dan jaringan tertentu."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"kelola kebijakan jaringan"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Memungkinkan aplikasi mengelola kebijakan jaringan dan menguraikan peraturan khusus aplikasi."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"mengubah penghitungan penggunaan jaringan"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Memungkinkan modifikasi cara penghitungan penggunaan jaringan yang dikenakan terhadap aplikasi. Tidak untuk digunakan oleh aplikasi normal."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setel aturan sandi"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontrol panjangnya dan karakter yang diizinkan dalam sandi pembuka layar"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Upaya pembukaan kunci layar monitor"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrol seberapa sering sandi pengunci layar harus diganti"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Setel enkripsi penyimpanan"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Mengharuskan data aplikasi yang disimpan untuk dienkripsi"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Nonaktifkan kamera"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Mencegah penggunaan semua kamera perangkat"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Rumah"</item>
     <item msgid="869923650527136615">"Seluler"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tidak ada kartu SIM dalam tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Tidak ada Kartu SIM di dalam ponsel."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Masukkan kartu SIM"</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Kartu SIM tidak ada atau tidak dapat dibaca. Masukkan kartu SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Kartu SIM Anda dinonaktifkan secara permanen."\n" Hubungi penyedia layanan nirkabel Anda untuk mendapatkan kartu SIM lainnya."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Panggilan darurat saja"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Jaringan terkunci"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Kartu SIM terkunci PUK."</string>
@@ -819,7 +809,7 @@
     <string name="year" msgid="4001118221013892076">"tahun"</string>
     <string name="years" msgid="6881577717993213522">"tahun"</string>
     <string name="VideoView_error_title" msgid="3359437293118172396">"Tidak dapat memutar video"</string>
-    <string name="VideoView_error_text_invalid_progressive_playback" msgid="897920883624437033">"Maaf, video ini tidak valid untuk streaming pada perangkat ini."</string>
+    <string name="VideoView_error_text_invalid_progressive_playback" msgid="897920883624437033">"Maaf, video ini tidak valid untuk dialirkan pada perangkat ini."</string>
     <string name="VideoView_error_text_unknown" msgid="710301040038083944">"Maaf, video ini tidak dapat diputar."</string>
     <string name="VideoView_error_button" msgid="2822238215100679592">"OK"</string>
     <string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jika Anda menghidupkan penyimpanan USB, sebagian aplikasi yang Anda gunakan akan berhenti dan mungkin tidak tersedia sampai Anda mematikan penyimpanan USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Operasi USB gagal"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format penyimpanan USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Format kartu SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Aksesibilitas"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ubah wallpaper"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Protokol Penyaluran Titik ke Titik"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protokol Penyaluran Lapis 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Kunci pra-bagi berbasis L2TP/IPSec VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sertifikat berbasis L2TP/IPSec VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Ketuk untuk mengelola jaringan."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Tersambung ke <xliff:g id="SESSION">%s</xliff:g>. Ketuk untuk mengelola jaringan."</string>
     <string name="upload_file" msgid="2897957172366730416">"Pilih berkas"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Tidak ada berkas yang dipilih"</string>
     <string name="reset" msgid="2448168080964209908">"Setel ulang"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Hapus item."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Urungkan penghapusan."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Jangan lakukan apa pun untuk saat ini."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN tersambung"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN terputus"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Sentuh untuk terhubung kembali ke VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Pilih akun"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Penambahan"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Pengurangan"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Kartu SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Penyimpanan USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Edit..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Peringatan penggunaan data"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"penggunaan melebihi <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Data 2G-3G dinonaktifkan"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Data 4G dinonaktifkan"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Data seluler dinonaktifkan"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"ketuk untuk mengaktifkan"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Sertifikat keamanan"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Sertifikat ini valid."</string>
+    <string name="issued_to" msgid="454239480274921032">"Diterbitkan ke:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Nama umum:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organisasi:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Unit organisasi:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Diterbitkan oleh:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Validitas:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Diterbitkan pada:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Kedaluwarsa pada:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 3c9d909..fcb4e3a 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modalità aereo"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modalità aereo attiva"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modalità aereo non attiva"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servizi che prevedono un costo"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"scrittura dati di contatto"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Consente a un\'applicazione di modificare i dati (gli indirizzi) di contatto memorizzati sul tablet. Le applicazioni dannose possono sfruttare questa possibilità per cancellare o modificare i dati di contatto."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Consente a un\'applicazione di modificare i dati (gli indirizzi) di contatto memorizzati sul telefono. Le applicazioni dannose possono sfruttare questa possibilità per cancellare o modificare i dati di contatto."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"lettura dati del profilo"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Consente a un\'applicazione di leggere tutte le informazioni personali del tuo profilo. Le applicazioni dannose possono sfruttare questa possibilità per identificarti e inviare le tue informazioni personali ad altre persone."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"scrittura dati profilo"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Consente a un\'applicazione di modificare le informazioni personali del tuo profilo. Le applicazioni dannose possono sfruttare questa possibilità per cancellare o modificare i dati del tuo profilo."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"leggere eventi di calendario"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Consente la lettura da parte di un\'applicazione di tutti gli eventi di calendario memorizzati sul tablet. Le applicazioni dannose possono sfruttare questa possibilità per inviare i tuoi eventi di calendario ad altre persone."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Consente la lettura da parte di un\'applicazione di tutti gli eventi di calendario memorizzati sul telefono. Le applicazioni dannose possono sfruttare questa possibilità per inviare i tuoi eventi di calendario ad altre persone."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Consente a un\'applicazione di leggere e scrivere il filesystem nella cache."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"effettuazione/ricezione chiamate Internet"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Consente a un\'applicazione di utilizzare il servizio SIP per effettuare/ricevere chiamate Internet."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"lettura dati storici di utilizzo della rete"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Consente a un\'applicazione di leggere dati storici di utilizzo della rete per reti e applicazioni specifiche."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"gestione norme rete"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Consente a un\'applicazione di gestire le norme di rete e definire le regole specifiche delle applicazioni."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modifica dell\'effetto dell\'utilizzo della rete"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Consente la modifica dell\'effetto dell\'utilizzo della rete sulle applicazioni. Da non usare per normali applicazioni."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Imposta regole password"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlla la lunghezza e i caratteri ammessi nelle password di sblocco dello schermo"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitora tentativi di sblocco dello schermo"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Stabilisci la frequenza di modifica della password di blocco dello schermo"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Imposta crittografia archivio"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Richiede la crittografia dei dati applicazione memorizzati"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Disattiva fotocamere"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Impedisci l\'utilizzo di tutte le fotocamere del dispositivo"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Cellulare"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nessuna scheda SIM presente nel tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Nessuna SIM presente nel telefono."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Inserisci una SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Scheda SIM mancante o non leggibile. Inserisci una scheda SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"La scheda SIM è stata disattivata definitivamente."\n" Contatta il fornitore del tuo servizio wireless per ricevere un\'altra scheda SIM."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Solo chiamate di emergenza"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Rete bloccata"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"La SIM è bloccata tramite PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se attivi l\'archivio USB, alcune applicazioni in uso si bloccheranno e potrebbero risultare non disponibili finché non disattiverai l\'archivio USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Operazione USB non riuscita"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatta archivio USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatta scheda SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibilità"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Sfondo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambia sfondo"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Protocollo di tunneling Point-to-Point"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocollo di tunneling livello 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec basata su chiave precondivisa"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec basata su certificato"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Tocca per gestire la rete."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Collegata a <xliff:g id="SESSION">%s</xliff:g>. Tocca per gestire la rete."</string>
     <string name="upload_file" msgid="2897957172366730416">"Scegli file"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nessun file è stato scelto"</string>
     <string name="reset" msgid="2448168080964209908">"Reimposta"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Elimina gli elementi."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Annulla le eliminazioni."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Non fare nulla per ora."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> collegata"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> scollegata"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Tocca per riconnetterti a una rete VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Seleziona un account"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Aumenta"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Diminuisci"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Scheda SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Archivio USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Modifica..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Avviso sull\'utilizzo dei dati"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"l\'utilizzo supera <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Dati 2G-3G disattivati"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Dati 4G disattivati"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Dati mobili disattivati"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"tocca per attivare"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Certificato di protezione"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Questo certificato è valido."</string>
+    <string name="issued_to" msgid="454239480274921032">"Rilasciato a:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Nome comune:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organizzazione:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Unità organizzativa:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Emesso da:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Validità:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Rilasciato il:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Scade il:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 71aa9f1..31ae61f 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"מצב טיסה"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"מצב טיסה מופעל"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"מצב טיסה כבוי"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+‎"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string>
     <string name="android_system_label" msgid="6577375335728551336">"מערכת Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"שירותים שעולים לך כסף"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"כתוב נתוני איש קשר"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"מאפשר ליישום לשנות את נתוני הקשר (כתובות) המאוחסנים בטבלט. יישומים זדוניים יכולים להשתמש ביכולת זו כדי למחוק או לשנות את נתוני אנשי הקשר."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"מאפשר ליישום לשנות את הנתונים של אנשי הקשר (כתובות) המאוחסנים בטלפון. יישומים זדוניים עלולים להשתמש ביכולת זו כדי למחוק או לשנות את הנתונים של אנשי הקשר."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"קריאת נתוני פרופיל"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"מאפשר ליישום לקרוא את כל פרטי הפרופיל האישיים שלך. יישומים זדוניים יכולים להשתמש בהרשאה זו כדי לזהות אותך ולשלוח את המידע האישי שלך לאנשים אחרים."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"כתוב נתוני פרופיל"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"מאפשר ליישום לשנות את פרטי הפרופיל האישיים שלך. יישומים זדוניים יכולים להשתמש בהרשאה זו כדי למחוק או לשנות את נתוני הפרופיל שלך."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"קרא אירועי לוח שנה"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"מאפשר ליישום לקרוא את כל נתוני לוח השנה המאוחסנים בטבלט. יישומים זדוניים יכולים להשתמש ביכולת זו כדי לשלוח את אירועי לוח השנה לאנשים אחרים."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"מאפשר ליישום לקרוא את כל אירועי לוח השנה המאוחסנים בטלפון. יישומים זדוניים עלולים להשתמש ביכולת זו כדי לשלוח את אירועי לוח השנה שלך לאנשים אחרים."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"מאפשר ליישום לקרוא ולכתוב במערכת הקבצים של הקובץ השמור."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"בצע/קבל שיחות אינטרנט"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"מאפשר ליישום להשתמש בשירות SIP כדי לבצע/לקבל שיחות אינטרנט."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"קריאת נתוני שימוש היסטוריים ברשת"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"מאפשר ליישום לקרוא נתוני שימוש היסטוריים ברשת עבור רשתות ויישומים ספציפיים."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"ניהול מדיניות רשת"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"מאפשר ליישום לנהל מדיניות רשת ולהגדיר כללים ספציפיים ליישומים."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"שינוי ניהול חשבונות של שימוש ברשת"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"מאפשר שינוי של האופן שבו מנוהלים החשבונות של שימוש ברשת מול יישומים. לא מיועד לשימוש של יישומים רגילים."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"הגדר כללי סיסמה"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"שלוט באורך ובמספר התווים המותרים בסיסמאות לביטול נעילת מסך"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"עקוב אחר ניסיונות לביטול נעילת מסך"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"שלוט בתדירות שבה הסיסמה של נעילת המסך חייבת להשתנות"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"הגדר הצפנת אחסון"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"דורש שנתוני היישום המאוחסנים יהיו מוצפנים"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"השבת מצלמות"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"מנע שימוש בכל המצלמות שבמכשיר"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"בית"</item>
     <item msgid="869923650527136615">"נייד"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"אין כרטיס SIM בטבלט."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"אין כרטיס SIM בטלפון."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"הכנס כרטיס SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"כרטיס ה-SIM חסר או לא קריא. הכנס כרטיס SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"כרטיס ה-SIM שלך מושבת לצמיתות."\n" צור קשר עם ספק השירות האלחוטי שלך כדי לקבל כרטיס SIM אחר."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"שיחות חירום בלבד"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"רשת נעולה"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"כרטיס ה-SIM נעול באמצעות PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"אם תפעיל אחסון USB, חלק מהיישומים שבהם אתה משתמש יעצרו ולא יהיו זמינים עד שתכבה את אחסון ה-USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"הפעלת ה-USB נכשלה"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"אישור"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"פרמט אמצעי אחסון מסוג USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"פרמוט כרטיס SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"נגישות"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"טפט"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"שנה טפט"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Point-to-Point Tunneling Protocol"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunneling Protocol"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN של L2TP/IPSec המבוסס על מפתח משותף מראש"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN המבוסס על אישור"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"הקש כדי לנהל את הרשת."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"מחובר אל <xliff:g id="SESSION">%s</xliff:g>. הקש כדי לנהל את הרשת."</string>
     <string name="upload_file" msgid="2897957172366730416">"בחר קובץ"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"לא נבחר קובץ"</string>
     <string name="reset" msgid="2448168080964209908">"אפס"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"מחק את הפריטים."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"בטל את המחיקות."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"אל תעשה דבר בינתיים."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"VPN של <xliff:g id="PROFILENAME">%s</xliff:g> מחובר"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"VPN של <xliff:g id="PROFILENAME">%s</xliff:g> נותק"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"גע כדי להתחבר שוב ל-VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"בחר חשבון"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"הוספה"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"הפחתה"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"כרטיס SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"אמצעי אחסון מסוג USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"ערוך..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"אזהרת שימוש בנתונים"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"השימוש חורג מ-<xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"נתוני 2G-3G מושבתים"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"נתוני 4G מושבתים"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"נתונים לנייד מושבתים"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"הקש כדי להפעיל"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"אישור אבטחה"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"אישור זה תקף."</string>
+    <string name="issued_to" msgid="454239480274921032">"הוקצה ל:"</string>
+    <string name="common_name" msgid="2233209299434172646">"שם משותף:"</string>
+    <string name="org_name" msgid="6973561190762085236">"ארגון:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"יחידה ארגונית:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"הונפק על ידי:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"חוקיות:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"הונפק בתאריך:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"פג תוקף ב:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 388b47b..9b7e80e 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"機内モード"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"機内モードON"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"機内モードOFF"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100超"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"セーフモード"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Androidシステム"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"料金の発生するサービス"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"連絡先データの書き込み"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"タブレットに保存されている連絡先(アドレス)データの変更をアプリケーションに許可します。この許可を悪意のあるアプリケーションに利用されると、連絡先データが消去または変更される恐れがあります。"</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"端末に保存した連絡先(アドレス)データの変更をアプリケーションに許可します。悪意のあるアプリケーションが連絡先データを消去/変更する恐れがあります。"</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"プロフィールデータの読み取り"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"アプリケーションによる個人の全プロフィール情報の読み取りを許可します。この場合、悪意のあるアプリケーションによって身元が特定されたり個人情報が第三者に転送されたりする危険があります。"</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"プロフィールデータの書き込み"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"アプリケーションによる個人のプロフィール情報の変更を許可します。この場合、悪意のあるアプリケーションによってプロフィールデータが消去または変更される危険があります。"</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"カレンダーの予定の読み取り"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"タブレットに保存されているカレンダーの予定の読み取りをアプリケーションに許可します。この許可を悪意のあるアプリケーションに利用されると、カレンダーの予定が他人に送信される恐れがあります。"</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"端末に保存したカレンダーの予定の読み取りをアプリケーションに許可します。悪意のあるアプリケーションがカレンダーの予定を他人に送信する恐れがあります。"</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"キャッシュファイルシステムへの読み書きをアプリケーションに許可します。"</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"インターネット通話の発着信"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"インターネット通話の発着信にSIPサービスを使用することをアプリケーションに許可します。"</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"ネットワーク使用履歴の読み取り"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"アプリケーションによる、特定のネットワークやアプリケーションについてのネットワーク使用履歴の読み取りを許可します。"</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"ネットワークポリシーの管理"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"アプリケーションによるネットワークポリシーの管理とアプリケーション固有のルールの定義を許可します。"</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"ネットワークの課金の変更"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"ネットワーク利用の課金を変更することをアプリケーションに許可します。通常のアプリケーションでは不要です。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"パスワードルールの設定"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"画面ロック解除パスワードの長さと使用できる文字数を制御する"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"画面ロック解除試行の監視"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"ロック解除パスワードの変更が必要になる頻度を指定します"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"ストレージ暗号化の設定"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"保存したアプリケーションデータが暗号化されるようにする"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"カメラを無効にする"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"すべての端末カメラを使用できないようにします"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"自宅"</item>
     <item msgid="869923650527136615">"携帯"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"タブレット内にSIMカードがありません。"</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"SIMカードが挿入されていません"</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"SIMカードを挿入してください。"</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"SIMカードが見つからないか読み取れません。SIMカードを挿入してください。"</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"お使いのSIMカードは永久に無効となっています。"\n"ワイヤレスサービスプロバイダに問い合わせて新しいSIMカードを入手してください。"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"緊急通報のみ"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"ネットワークがロックされました"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIMカードはPUKでロックされています。"</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USBストレージをONにすると、使用中のアプリケーションの一部が停止し、USBストレージをOFFにするまで使用できなくなる場合があります。"</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB操作に失敗しました"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USBストレージのフォーマット"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SDカードをフォーマット"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"ユーザー補助"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁紙"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"壁紙を変更"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"ポイントツーポイントトンネリングプロトコル"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"レイヤー2トンネリングプロトコル"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPNベースの事前共有鍵"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPNベースの証明書"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"ネットワークを管理するにはタップしてください。"</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>に接続しました。ネットワークを管理するにはタップしてください。"</string>
     <string name="upload_file" msgid="2897957172366730416">"ファイルを選択"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"ファイルが選択されていません"</string>
     <string name="reset" msgid="2448168080964209908">"リセット"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"アイテムを削除する"</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"削除を元に戻す"</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"今は何もしない"</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> VPNに接続しました"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> VPNが切断されました"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"タップしてVPNに再接続してください。"</string>
     <string name="choose_account_label" msgid="4191313562041125787">"アカウントを選択"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"増やす"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"減らす"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SDカード"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USBストレージ"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"編集..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"データ使用の警告"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"使用が<xliff:g id="SIZE">%s</xliff:g>を超えています"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G~3Gデータが無効になりました"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4Gデータが無効になりました"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"モバイルデータが無効になりました"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"有効にするにはタップしてください"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"セキュリティ証明書"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"証明書は有効です。"</string>
+    <string name="issued_to" msgid="454239480274921032">"発行先:"</string>
+    <string name="common_name" msgid="2233209299434172646">"共通名:"</string>
+    <string name="org_name" msgid="6973561190762085236">"組織:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"組織単位:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"発行者:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"有効期間:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"発行:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"有効期限:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index f7e1a75..15b3240 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"비행기 모드"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"비행기 모드 사용"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"비행기 모드 사용 안함"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"안전 모드"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 시스템"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"요금이 부과되는 서비스"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"연락처 데이터 작성"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"애플리케이션이 태블릿에 저장된 연락처(주소) 데이터를 수정할 수 있도록 합니다. 이 경우 악성 애플리케이션이 연락처 데이터를 지우거나 수정할 수 있습니다."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"애플리케이션이 휴대전화에 저장된 연락처(주소) 데이터를 수정할 수 있도록 합니다. 이 경우 악성 애플리케이션이 연락처 데이터를 지우거나 수정할 수 있습니다."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"프로필 데이터 읽기"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"애플리케이션이 개인 프로필 정보를 모두 읽을 수 있도록 합니다. 이렇게 하면 악성 애플리케이션이 이 정보를 사용하여 사용자를 식별하고 개인 정보를 다른 사용자에게 보낼 수 있습니다."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"프로필 데이터 작성"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"애플리케이션이 개인 프로필 정보를 수정할 수 있도록 허용합니다. 이렇게 하면 악성 애플리케이션이 이 정보를 사용하여 프로필 데이터를 지우거나 수정할 수 있습니다."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"캘린더 일정 읽기"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"애플리케이션이 태블릿에 저장된 모든 캘린더 일정을 읽을 수 있도록 합니다. 이 경우 악성 애플리케이션이 캘린더 일정을 다른 사람에게 보낼 수 있습니다."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"애플리케이션이 휴대전화에 저장된 모든 캘린더 일정을 읽을 수 있도록 합니다. 이 경우 악성 애플리케이션이 캘린더 일정을 다른 사람에게 보낼 수 있습니다."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"애플리케이션이 캐시 파일시스템을 읽고 쓸 수 있도록 합니다."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"인터넷 전화 걸기/받기"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"애플리케이션에서 SIP 서비스를 사용하여 인터넷 전화를 걸거나 받을 수 있습니다."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"이전 네트워크 사용량 읽기"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"애플리케이션이 특정 네트워크 및 애플리케이션에 대한 이전 네트워크 사용량을 읽을 수 있도록 합니다."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"네트워크 정책 관리"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"애플리케이션이 네트워크 정책을 관리하고 애플리케이션별 규칙을 정의할 수 있도록 합니다."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"네트워크 사용량 계산 수정"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"애플리케이션에 대해 네트워크 사용량을 계산하는 방법을 수정하도록 허용합니다. 일반 애플리케이션에서는 사용할 수 없습니다."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"비밀번호 규칙 설정"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"화면 잠금해제 비밀번호에 허용되는 길이 및 문자 수를 제어합니다."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"화면 잠금해제 시도 모니터링"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"화면 잠금 비밀번호 변경 빈도 설정"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"저장소 암호화 설정"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"저장한 애플리케이션 데이터를 암호화해야 합니다."</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"카메라 사용 안함"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"모든 기기 카메라의 사용 차단"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"집"</item>
     <item msgid="869923650527136615">"모바일"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"태블릿에 SIM 카드가 없습니다."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"휴대전화에 SIM 카드가 없습니다."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"SIM 카드를 삽입하세요."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"SIM 카드가 없거나 읽을 수 없습니다. SIM 카드를 삽입하세요."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"SIM 카드 사용이 영구적으로 중지됩니다."\n"다른 SIM 카드를 사용하려면 무선 서비스 제공업체에 문의하시기 바랍니다."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"긴급 통화만"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"네트워크 잠김"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM 카드가 PUK 잠김 상태입니다."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USB 저장소를 사용하면 사용 중인 일부 애플리케이션이 중지되어 USB 저장소를 사용 중지할 때까지 사용할 수 없게 됩니다."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB 작업 실패"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"확인"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB 저장소 포맷"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD 카드 포맷"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"접근성"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"배경화면"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"배경화면 변경"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"PPTP(Point-to-Point Tunneling Protocol)"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"L2TP(Layer 2 Tunneling Protocol)"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"사전 공유 키 기반 L2TP/IPSec VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"인증서 기반 L2TP/IPSec VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"네트워크를 관리하려면 누르세요."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>에 연결되어 있습니다. 네트워크를 관리하려면 누르세요."</string>
     <string name="upload_file" msgid="2897957172366730416">"파일 선택"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"파일을 선택하지 않았습니다."</string>
     <string name="reset" msgid="2448168080964209908">"초기화"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"항목 삭제"</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"삭제 실행취소"</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"나중에 작업"</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN 연결됨"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN 연결 끊김"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"VPN에 다시 연결하려면 터치하세요."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"계정 선택"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"올리기"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"줄이기"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD 카드"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB 저장소"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"수정..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"데이터 사용 경고"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"사용량이 <xliff:g id="SIZE">%s</xliff:g>을(를) 초과했습니다."</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-3G 데이터 사용중지됨"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G 데이터 사용중지됨"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"모바일 데이터 사용중지됨"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"사용하려면 누르세요."</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"보안 인증서"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"유효한 인증서입니다."</string>
+    <string name="issued_to" msgid="454239480274921032">"발급 대상:"</string>
+    <string name="common_name" msgid="2233209299434172646">"일반 이름:"</string>
+    <string name="org_name" msgid="6973561190762085236">"조직:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"조직 구성 단위:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"발급 기관:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"유효성:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"발급 날짜:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"만료 날짜:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index c500fd3..ec2313c 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -39,6 +39,6 @@
     <dimen name="action_bar_subtitle_text_size">12dp</dimen>
 
     <!-- Size of clock font in LockScreen on Unsecure unlock screen. -->
-    <dimen name="keyguard_lockscreen_clock_font_size">80sp</dimen>
+    <dimen name="keyguard_lockscreen_clock_font_size">70sp</dimen>
 
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 549641f..b57455f 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lėktuvo režimas"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"ĮJUNGTAS lėktuvo režimas"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"lėktuvo režimas IŠJUNGTAS"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Saugos režimas"</string>
     <string name="android_system_label" msgid="6577375335728551336">"„Android“ sistema"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Paslaugos, už kurias mokėjote"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"rašyti adresatų duomenis"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Leidžiama programai keisti kontaktų (adreso) duomenis, išsaugotus planšetiniame kompiuteryje. Kenkėjiškos programos gali tai naudoti, kad ištrintų ar keistų kontaktų duomenis."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Leidžia programai keisti adresatų (adresų) duomenis, išsaugotus jūsų telefone. Kenkėjiškos programos gali tai naudoti, kad ištrintų ar pakeistų jūsų adresatų duomenis."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"skaityti profilio duomenis"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Leidžiama programai skaityti visą asmeninę profilio informaciją. Piktybinės programos gali tai naudoti, kad jus identifikuotų ir siųstų asmeninę informaciją kitiems žmonėms."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"įrašyti profilio duomenis"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Leidžiama programai keisti asmeninę profilio informaciją. Piktybinės programos gali tai naudoti profilio duomenims ištrinti arba keisti."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"skaityti kalendoriaus įvykius"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Leidžiama programai skaityti visus kalendoriaus įvykius, išsaugotus jūsų planšetiniame kompiuteryje. Kenkėjiškos programos gali tai naudoti, kad siųstų jūsų kalendoriaus įvykius kitiems žmonėms."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Leidžia programai skaityti visus kalendoriaus įvykius, išsaugotus jūsų telefone. Kenkėjiškos programos tai gali naudoti, kad siųstų kalendoriaus įvykius kitiems žmonėms."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Leidžia programai skaityti ir rašyti į talpyklos failų sistemą."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"skambinti / priimti skambučius internetu"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Leidžiama programai naudoti SIP paslaugą norint skambinti / priimti skambučius internetu."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"skaityti tinklo naudojimo istoriją"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Leidžiama programai skaityti konkrečių tinklų ir programų tinklo naudojimo istoriją."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"valdyti tinklo politiką"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Leidžiama programai valdyti tinklo politiką ir apibrėžti konkrečios programos taisykles."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"keisti tinklo naudojimo apskaitą"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Leidžiama keisti, kaip tinklo naudojimas apskaičiuojamas programose. Neskirta naudoti įprastoms programoms."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nustatyti slaptažodžio taisykles"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Valdyti leidžiamą ekrano atrakinimo slaptažodžių ilgį ir juose leidžiamus naudoti simbolius"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Stebėti bandymus atrakinti ekraną"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Valdykite, kaip dažnai reikia keisti ekrano užrakto slaptažodį"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nustatyti atmintinės šifruotę"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Saugomos programos duomenys turi būti šifruoti"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Neleisti fotoaparatų"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Neleisti naudoti visų įrenginio fotoaparatų"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Pagrindinis"</item>
     <item msgid="869923650527136615">"Mobilusis"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Planšetiniame kompiuteryje nėra SIM kortelės."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefone nėra SIM kortelės."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Įdėkite SIM kortelę."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Trūksta SIM kortelės arba ji neskaitoma. Įdėkite SIM kortelę."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"SIM kortelė visam laikui neleidžiama."\n" Jei norite gauti kitą SIM kortelę, susisiekite su belaidžio ryšio paslaugos teikėju."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Tik pagalbos skambučiai"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Tinklas užrakintas"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM kortelė užrakinta PUK kodu."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jei įjungiate USB saugyklą, kai kurios naudojamos programos sustos ir gali būti negalimos, kol išjungsite USB saugyklą."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB operacija nepavyko"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Gerai"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format. USB atmint."</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatuoti SD kortelę"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Pasiekiamumas"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Darbalaukio fonas"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Keisti darbalaukio foną"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Tiesioginio tunelinio ryšio protokolas"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"2 sluoksnio tunelinis protokolas"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Iš anksto bendrinamas raktas, pagrįstas L2TP/IPSec VPT"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sertifikatas pagrįstas L2TP/IPSec VPT"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Jei norite valdyti tinklą, palieskite."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Prisijungta prie <xliff:g id="SESSION">%s</xliff:g>. Jei norite valdyti tinklą, palieskite."</string>
     <string name="upload_file" msgid="2897957172366730416">"Pasirinkti failą"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nepasirinktas joks failas"</string>
     <string name="reset" msgid="2448168080964209908">"Atstatyti"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Ištrinti elementus."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Anuliuoti ištrynimus."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Kol kas nieko nedaryti."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> VPT prijungtas"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> VPT atjungtas"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Jei norite iš naujo prisijungti prie VPT, palieskite."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Pasirinkti paskyrą"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Padidinti"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Sumažinti"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD kortelė"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB atmintis"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Redaguoti..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Įspėjimas dėl duomenų naudojimo"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"naudojimas viršija <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G–3G duomenys neleidžiami"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G duomenys neleidžiami"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobilieji duomenys neleidžiami"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"jei norite įgalinti, palieskite"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Saugos sertifikatas"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Šis sertifikatas galioja."</string>
+    <string name="issued_to" msgid="454239480274921032">"Išduota:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Bendras pavadinimas:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organizacija:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Organizacinis vienetas:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Išdavė:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Galiojimas:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Išduota:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Galiojimas baigiasi:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index e32df3b..6fed017 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lidojuma režīms"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Lidojuma režīms ir IESLĒGTS."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Lidojuma režīms ir IZSLĒGTS."</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"Pārsniedz"</string>
     <string name="safeMode" msgid="2788228061547930246">"Drošais režīms"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistēma"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Maksas pakalpojumi"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"rakstīt kontaktpersonu datus"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Ļauj lietojumprogrammai pārveidot planšetdatorā saglabātos kontaktpersonu (adrešu) datus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai dzēstu vai pārveidotu jūsu kontaktpersonu datus."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Ļauj lietojumprogrammai pārveidot tālrunī saglabātos kontaktpersonu (adrešu) datus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai dzēstu vai pārveidotu jūsu kontaktpersonu datus."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"lasīt profila datus"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Ļauj lietojumprogrammai lasīt visu jūsu personas informāciju profilā. Ļaunprātīgas lietojumprogrammas var izmantot šo iespēju, lai identificētu jūs un sūtītu jūsu personas informāciju citām personām."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"rakstīt profila datus"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Ļauj lietojumprogrammai mainīt jūsu personas informāciju profilā. Ļaunprātīgas lietojumprogrammas var izmantot šo iespēju, lai dzēstu vai mainītu jūsu profila datus."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"lasīt kalendāra pasākumus"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Ļauj lietojumprogrammai lasīt visus planšetdatorā saglabātos kalendāra notikumus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai sūtītu jūsu kalendāra notikumus citām personām."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Ļauj lietojumprogrammai lasīt visus tālrunī saglabātos kalendāra pasākumus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai sūtītu kalendāra pasākumus citām personām."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Ļauj lietojumprogrammai lasīt kešatmiņas failu sistēmu un rakstīt tajā."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"veikt/saņemt interneta zvanus"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Ļauj lietojumprogrammai izmantot SIP pakalpojumu, vai veiktu/saņemtu interneta zvanus."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"lasīt informāciju par iepriekšēju tīkla izmantošanu"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Ļauj lietojumprogrammai lasīt informāciju par iepriekšēju tīkla izmantošanu saistībā ar noteiktiem tīkliem un lietojumprogrammām."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"pārvaldīt tīkla politiku"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Ļauj lietojumprogrammai pārvaldīt tīkla politikas un noteikt lietojumprogrammas kārtulas."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"Tīkla lietojuma uzskaites mainīšana"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Ļauj mainīt to, kā tīkla lietojums tiek uzskaitīts saistībā ar lietojumprogrammām. Nav paredzēts lietošanai parastās lietojumprogrammās."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Paroles kārtulu iestatīšana"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontrolē ekrāna atbloķēšanas parolē atļautās rakstzīmes un garumu"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekrāna atbloķēšanas mēģinājumu pārraudzīšana"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrolē, cik bieži ir jāmaina ekrāna bloķēšanas parole."</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Skatīt atmiņas šifrējumu"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Pieprasīt, lai saglabātie lietojumprogrammas dati tiktu šifrēti"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Atspējot kameras"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Neļaut izmantot nevienu kameru"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Mājas"</item>
     <item msgid="869923650527136615">"Mobilais"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Planšetdatorā nav SIM kartes."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Tālrunī nav SIM kartes."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Lūdzu, ievietojiet SIM karti."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Nav SIM kartes, vai arī tā nav lasāma. Lūdzu, ievietojiet SIM karti."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Jūsu SIM karte ir neatgriezeniski atspējota."\n"Lūdzu, sazinieties ar savu bezvadu pakalpojumu sniedzēju, lai iegūtu citu SIM karti."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Tikai ārkārtas zvani"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Tīkls ir bloķēts."</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM karte ir bloķēta ar PUK kodu."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ja ieslēgsiet USB krātuvi, dažu joprojām lietoto lietojumprogrammu darbība tiks apturēta un tās, iespējams, nebūs pieejamas līdz brīdim, kad USB krātuve tiks izslēgta."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB darbība neizdevās."</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Labi"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB kr. formatēšana"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD kartes formatēšana"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Pieejamība"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fona tapete"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Tapetes maiņa"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Tunelēšanas divpunktu protokols"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"2. slāņa tunelēšanas protokols"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Uz iepriekš koplietotas atslēgas balstīts L2TP/IPSec VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Uz sertifikātu balstīts L2TP/IPSec VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Pieskarieties, lai pārvaldītu tīklu."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Ir izveidots savienojums ar: <xliff:g id="SESSION">%s</xliff:g>. Pieskarieties, lai pārvaldītu tīklu."</string>
     <string name="upload_file" msgid="2897957172366730416">"Izvēlēties failu"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Neviens fails nav izvēlēts"</string>
     <string name="reset" msgid="2448168080964209908">"Atiestatīt"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Dzēsiet šos vienumus."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Atsauciet dzēšanu."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Pagaidām neveiciet nekādas darbības."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> Savienojums ar VPN ir izveidots"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> Savienojums ar VPN ir pārtraukts"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Pieskarieties, lai atkārtoti izveidotu savienojumu ar VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Atlasīt kontu"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Palielināt"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Samazināt"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD karte"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB atmiņa"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Rediģēt..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Datu izmantošanas brīdinājums"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"izmant. datu apj. pārsniedz <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G–3G dati ir atspējoti"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G dati ir atspējoti"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobilie dati ir atspējoti"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"pieskarieties, lai iespējotu"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Drošības sertifikāts"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Sertifikāts ir derīgs."</string>
+    <string name="issued_to" msgid="454239480274921032">"Izdots:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Kopējais nosaukums:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organizācija:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Organizatoriskā vienība:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Izsniedzējs:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Derīgums:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Izsniegšanas datums:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Derīguma termiņš:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 15896ae..87b169d 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -510,6 +510,10 @@
     <skip />
     <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
     <skip />
+    <!-- no translation found for permlab_modifyNetworkAccounting (5088217309088729650) -->
+    <skip />
+    <!-- no translation found for permdesc_modifyNetworkAccounting (8702285686629184404) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Tetapkan peraturan kata laluan"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan buka kunci skrin"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Memantau percubaan buka kunci skrin"</string>
@@ -642,7 +646,7 @@
     <string name="relationTypeSister" msgid="1735983554479076481">"Kakak/Adik"</string>
     <string name="relationTypeSpouse" msgid="394136939428698117">"Pasangan"</string>
     <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Peribadi"</string>
-    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Laman Utama"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Rumah"</string>
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"Kerja"</string>
     <string name="sipAddressTypeOther" msgid="4408436162950119849">"Lain-lain"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Masukkan kod PIN"</string>
@@ -730,7 +734,7 @@
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"tulis sejarah dan penanda halaman Penyemak Imbas"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Membenarkan aplikasi mengubah suai sejarah atau penanda halaman Penyemak Imbas yang disimpan pada tablet anda. Aplikasi berniat jahat boleh menggunakannya untuk memadamkan atau mengubah suai data Penyemak Imbas anda."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Membenarkan aplikasi mengubah suai sejarah atau penanda halaman Penyemak Imbas yang disimpan pada telefon anda. Aplikasi berniat jahat boleh menggunakannya untuk memadamkan atau mengubah data Penyemak Imbas anda."</string>
-    <string name="permlab_setAlarm" msgid="5924401328803615165">"menetapkan penggera dalam jam penggera"</string>
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"menetapkan penggera pada jam penggera"</string>
     <string name="permdesc_setAlarm" msgid="5966966598149875082">"Membenarkan aplikasi menetapkan penggera dalam aplikasi jam penggera yang dipasang. Sesetengah aplikasi jam penggera mungkin tidak melaksanakan ciri ini."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Ubah suai kebenaran geolokasi Penyemak Imbas"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Membenarkan aplikasi mengubah suai kebenaran geolokasi Penyemak Imbas. Aplikasi berniat jahat boleh menggunakannya untuk membenarkan penghantaran maklumat lokasi ke sembarangan tapak web."</string>
@@ -968,9 +972,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jika anda menghidupkan storan USB, sesetengah aplikasi yang anda sedang gunakan akan terhenti dan mungkin tidak akan tersedia sehingga anda memadamkan storan USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Pengendalian USB gagal"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format storan USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Format kad SD"</string>
@@ -1035,13 +1043,9 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Kebolehaksesan"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Kertas dinding"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Tukar kertas dinding"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Protokol Penerowongan Titik Ke Titik"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protokol Penerowongan Lapisan ke-2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec berasaskan kunci prakongsi"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec berasaskan sijil"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
     <!-- no translation found for vpn_text (1610714069627824309) -->
     <skip />
@@ -1066,14 +1070,14 @@
     <string name="find_on_page" msgid="1946799233822820384">"Cari di halaman"</string>
   <plurals name="matches_found">
     <item quantity="one" msgid="8167147081136579439">"1 padanan"</item>
-    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> dari <xliff:g id="TOTAL">%d</xliff:g>"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> daripada <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
     <string name="action_mode_done" msgid="7217581640461922289">"Selesai"</string>
     <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Menyahlekap storan USB..."</string>
     <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Menyahlekap kad SD..."</string>
-    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Memadam storan USB..."</string>
-    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Memadam kad SD..."</string>
-    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Gagal memadam storan USB."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Memadamkan storan USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Memadamkan kad SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Gagal memadamkan storan USB."</string>
     <string name="format_error" product="default" msgid="1343380371925238343">"Gagal memadamkan kad SD."</string>
     <string name="media_bad_removal" msgid="7960864061016603281">"Kad SD telah dikeluarkan sebelum dinyahlekap."</string>
     <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Storan USB sedang disemak buat masa ini."</string>
@@ -1083,7 +1087,7 @@
     <string name="media_shared" product="default" msgid="5706130568133540435">"Kad SD sedang digunakan oleh komputer buat masa ini."</string>
     <string name="media_unknown_state" msgid="729192782197290385">"Media luaran dalam keadaan yang tidak diketahui."</string>
     <string name="share" msgid="1778686618230011964">"Kongsi"</string>
-    <string name="find" msgid="4808270900322985960">"Cari"</string>
+    <string name="find" msgid="4808270900322985960">"Dapatkan"</string>
     <string name="websearch" msgid="4337157977400211589">"Carian Web"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Permintaan lokasi daripada <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="gpsNotifTitle" msgid="5446858717157416839">"Permintaan lokasi"</string>
@@ -1095,9 +1099,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Padam item."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Buat asal pemadaman."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Jangan lakukan apa-apa sekarang."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> disambungkan"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> diputuskan sambungannya"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Sentuh untuk menyambung semula ke VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Pilih akaun"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Kenaikan"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Penyusutan"</string>
@@ -1127,4 +1128,28 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <string name="ssl_certificate" msgid="6510040486049237639">"Sijil keselamatan"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Sijil ini sah."</string>
+    <string name="issued_to" msgid="454239480274921032">"Dikeluarkan kepada:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Nama biasa:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organisasi:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Unit organisasi:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Dikeluarkan oleh:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Kesahan:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Dikeluarkan pada:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Tamat tempoh pada:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
+    <skip />
+    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <skip />
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
+    <skip />
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index ca6d608..ca40558 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flymodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flymodus er på"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flymodus er av"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"Over 100"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Sikkermodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Betaltjenester"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"skrive kontaktinformasjon"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Lar programmet endre kontaktinformasjon (adresser) lagret på nettbrettet. Skadelige programmet kan bruke dette til å slette eller endre kontaktinformasjonen."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Lar applikasjonen endre kontakt- og adresseinformasjon lagret på telefonen. Ondsinnede applikasjoner kan bruke dette til å redigere eller endre kontaktinformasjonen."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"les profildata"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Gir applikasjoner tillatelse til å lese all din personlige profilinformasjon. Ondsinnede applikasjoner kan bruke dette til å identifisere deg og sende den personlige informasjonen din til andre."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"skriv profildata"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Gir applikasjoner tillatelse til å endre den personlige profilen din. Ondsinnede applikasjoner kan bruke dette til å slette eller endre profildataene dine."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"les kalenderaktiviteter"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Lar programmet lese alle kalenderhendelser lagret på nettbrettet. Skadelige programmer kan bruke dette til å sende kalenderhendelsene dine til andre."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Lar applikasjonen lese alle kalenderhendelser lagret på telefonen. Ondsinnede applikasjoner kan bruke dette til å sende kalenderhendelser til andre."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Tillater et program å lese og skrive til bufrede filer."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"foreta/motta Internett-anrop"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Tillater et program å bruke SIP-tjenesten til å foreta og motta Internett-anrop."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"les tidligere nettverksbruk"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Gir applikasjoner tillatelse til å lese tidligere nettverksbruk for bestemte nettverk og applikasjoner."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"administrer retningslinjene for nettverk"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Gir applikasjoner tillatelse til å administrere retningslinjene for nettverket og definere appllikasjonsspesifikke regler."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"Modifisering av regnskapsføring av nettverksbruk"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Gir tillatelse til modifisering av hvordan nettverksbruk blir redegjort for i henhold til applikasjoner. Skal ikke brukes av normale applikasjoner."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontroller tillatt lengde og tegn i passord for opplåsing av skjerm"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk forsøk på opplåsing av skjerm"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Velg hvor lenge det skal gå før passordet til skjermlåsen må byttes"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Angi lagringskryptering"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Krever at lagrede programdata krypteres"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Deaktiver kameraer"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Hindre bruk av alle kameraer på enheten"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hjemmenummer"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nettbrettet mangler SIM-kort."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Ikke noe SIM-kort i telefonen."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Sett inn et SIM-kort."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"SIM-kort mangler eller er uleselig. Sett inn et SIM-kort."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"SIM-kortet er permanent deaktivert."\n" Ta kontakt med mobiltjenesteleverandøren din for å få et annet SIM-kort."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Kun nødanrop"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Nettverk ikke tillatt"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM-kortet er PUK-låst."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Hvis du aktiverer USB-lagring, virker ikke lenger enkelte av programmene du bruker, og de kan være utilgjengelige inntil du deaktiverer USB-lagringen."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-operasjonen mislyktes"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formaterer USB-lagring"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatere minnekort"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Tilgjengelighet"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Bakgrunnsbilde"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Velg bakgrunnsbilde"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Punkt-til-punkt-tunneleringsprotokoll"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Lag 2-tunneleringsprotokoll"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Passordbasert L2TP/IPSec-VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sertifikatbasert L2TP/IPSec-VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Trykk for å administrere nettverket."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Koblet til <xliff:g id="SESSION">%s</xliff:g>. Trykk for å administrere nettverket."</string>
     <string name="upload_file" msgid="2897957172366730416">"Velg fil"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil er valgt"</string>
     <string name="reset" msgid="2448168080964209908">"Tilbakestill"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Slett elementene."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Opphev slettinger."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Ikke gjør noe nå."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> er tilkoblet VPN"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> er frakoblet VPN"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Trykk for å koble til et VPN på nytt."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Velg en konto"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Øke"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Senke"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD-kort"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-lagring"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Rediger"</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Advarsel for høyt dataforbruk"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"bruken overstiger <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G–3G-data er deaktivert"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G-data er deaktivert"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobildata er deaktivert"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"klikk for å aktivere"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Sikkerhetssertifikat"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Sertifikatet er gyldig."</string>
+    <string name="issued_to" msgid="454239480274921032">"Utstedt til:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Ordinært navn:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organisasjon:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Organisasjonsenhet:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Utstedt av:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Gyldighet:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Utstedt den:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Utløper den:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 8f54331..757091f 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -141,7 +141,7 @@
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Uw telefoon wordt uitgeschakeld."</string>
     <string name="shutdown_confirm_question" msgid="6656441286856415014">"Wilt u afsluiten?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recent"</string>
-    <string name="no_recent_tasks" msgid="279702952298056674">"Geen recente toepassingen."</string>
+    <string name="no_recent_tasks" msgid="279702952298056674">"Geen recente apps."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Tabletopties"</string>
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefoonopties"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Schermvergrendeling"</string>
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Vliegmodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Vliegmodus is AAN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Vliegmodus is UIT"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
     <string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-systeem"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services waarvoor u moet betalen"</string>
@@ -203,13 +203,13 @@
     <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Hiermee kan een app naar de op uw telefoon of SIM-kaart opgeslagen SMS-berichten schrijven. Schadelijke apps kunnen uw berichten mogelijk verwijderen."</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"WAP ontvangen"</string>
     <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Hiermee kan een app WAP-berichten ontvangen en verwerken. Schadelijke apps kunnen uw berichten bijhouden of deze verwijderen zonder dat u ze te zien krijgt."</string>
-    <string name="permlab_getTasks" msgid="5005277531132573353">"actieve toepassingen ophalen"</string>
+    <string name="permlab_getTasks" msgid="5005277531132573353">"actieve apps ophalen"</string>
     <string name="permdesc_getTasks" msgid="7048711358713443341">"Hiermee kan een app informatie over huidige en recent uitgevoerde taken ophalen. Schadelijke apps kunnen op deze manier mogelijk privé-informatie over andere apps achterhalen."</string>
-    <string name="permlab_reorderTasks" msgid="5669588525059921549">"actieve toepassingen opnieuw indelen"</string>
+    <string name="permlab_reorderTasks" msgid="5669588525059921549">"actieve apps opnieuw indelen"</string>
     <string name="permdesc_reorderTasks" msgid="126252774270522835">"Hiermee kan een app taken naar de voor- en achtergrond verplaatsen. Schadelijke apps kunnen zichzelf op de voorgrond plaatsen zonder dat u hier iets aan kunt doen."</string>
-    <string name="permlab_removeTasks" msgid="4802740047161700683">"stoppen met toepassingen uitvoeren"</string>
+    <string name="permlab_removeTasks" msgid="4802740047161700683">"stoppen met apps uitvoeren"</string>
     <string name="permdesc_removeTasks" msgid="2000332928514575461">"Hiermee kan een app taken verwijderen en de bijbehorende apps sluiten. Schadelijke apps kunnen het gedrag van andere apps beïnvloeden."</string>
-    <string name="permlab_setDebugApp" msgid="4339730312925176742">"foutopsporing in toepassingen inschakelen"</string>
+    <string name="permlab_setDebugApp" msgid="4339730312925176742">"foutopsporing in apps inschakelen"</string>
     <string name="permdesc_setDebugApp" msgid="5584310661711990702">"Hiermee kan een app de foutopsporing voor een andere app inschakelen. Schadelijke apps kunnen dit gebruiken om andere apps af te sluiten."</string>
     <string name="permlab_changeConfiguration" msgid="8214475779521218295">"uw UI-instellingen wijzigen"</string>
     <string name="permdesc_changeConfiguration" msgid="3465121501528064399">"Hiermee kan een app de huidige configuratie, zoals de landinstelling of de algemene lettergrootte, wijzigen."</string>
@@ -217,7 +217,7 @@
     <string name="permdesc_enableCarMode" msgid="5673461159384850628">"Staat een app toe de automodus in te schakelen."</string>
     <string name="permlab_killBackgroundProcesses" msgid="8373714752793061963">"processen op de achtergrond beëindigen"</string>
     <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Staat een app toe processen op de achtergrond te beëindigen, zelfs als er voldoende geheugen beschikbaar is."</string>
-    <string name="permlab_forceStopPackages" msgid="1447830113260156236">"andere toepassingen gedwongen stoppen"</string>
+    <string name="permlab_forceStopPackages" msgid="1447830113260156236">"andere apps gedwongen stoppen"</string>
     <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"Staat een app toe andere apps te stoppen."</string>
     <string name="permlab_forceBack" msgid="1804196839880393631">"app nu sluiten"</string>
     <string name="permdesc_forceBack" msgid="6534109744159919013">"Hiermee kan een app elke willekeurige activiteit die op de voorgrond wordt uitgevoerd, sluiten en naar de achtergrond verplaatsen. Nooit vereist voor normale apps."</string>
@@ -227,9 +227,9 @@
     <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Hiermee kan een app de inhoud van het actieve venster ophalen. Schadelijke apps kunnen de volledige inhoud van het venster ophalen en alle tekst bekijken, behalve wachtwoorden."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"gedeeltelijke uitschakeling"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Hiermee wordt activiteitenbeheer uitgeschakeld. Er wordt geen volledige uitschakeling uitgevoerd."</string>
-    <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"schakelen tussen toepassingen voorkomen"</string>
+    <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"schakelen tussen apps voorkomen"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Hiermee wordt voorkomen dat de gebruiker overschakelt naar een andere app."</string>
-    <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"alle startende toepassingen bijhouden en beheren"</string>
+    <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"alle startende apps bijhouden en beheren"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Hiermee kan een app de manier waarop het systeem activiteiten start, bijhouden en beheren. Schadelijke apps kunnen het systeem volledig in gevaar brengen. Deze machtiging is alleen voor ontwikkeling vereist, nooit voor normaal gebruik."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"melding verzenden dat pakket is verwijderd"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Hiermee kan een app een melding verzenden dat een applicatiepakket (APK) is verwijderd. Schadelijke apps kunnen hiervan gebruik maken om alle andere actieve apps af te sluiten."</string>
@@ -242,49 +242,49 @@
     <string name="permlab_setAlwaysFinish" msgid="5342837862439543783">"alle achtergrondtoepassingen sluiten"</string>
     <string name="permdesc_setAlwaysFinish" msgid="8773936403987091620">"Hiermee kan een app bepalen of activiteiten altijd worden afgesloten zodra deze naar de achtergrond gaan. Nooit nodig voor normale apps."</string>
     <string name="permlab_batteryStats" msgid="7863923071360031652">"accustatistieken aanpassen"</string>
-    <string name="permdesc_batteryStats" msgid="5847319823772230560">"Hiermee kunnen verzamelde accustatistieken worden gewijzigd. Niet voor gebruik door normale toepassingen."</string>
+    <string name="permdesc_batteryStats" msgid="5847319823772230560">"Hiermee kunnen verzamelde accustatistieken worden gewijzigd. Niet voor gebruik door normale apps."</string>
     <string name="permlab_backup" msgid="470013022865453920">"systeemback-up en -herstel beheren"</string>
     <string name="permdesc_backup" msgid="4837493065154256525">"Hiermee kan de app het mechanisme voor systeemback-up en -herstel beheren. Niet voor gebruik door normale apps."</string>
     <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"een volledige back-up- of herstelbewerking bevestigen"</string>
     <string name="permdesc_confirm_full_backup" msgid="9005017754175897954">"Hiermee kan de applicatie de gebruikersinterface voor bevestiging van de volledige back-up starten. Moet niet worden gebruikt door een applicatie."</string>
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"niet-geautoriseerde vensters weergeven"</string>
-    <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Hiermee kunnen vensters worden gemaakt die door de interne systeemgebruikersinterface worden gebruikt. Niet voor gebruik door normale toepassingen."</string>
+    <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Hiermee kunnen vensters worden gemaakt die door de interne systeemgebruikersinterface worden gebruikt. Niet voor gebruik door normale apps."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"waarschuwingen op systeemniveau weergeven"</string>
     <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Hiermee kan een app systeemwaarschuwingen weergeven. Schadelijke apps kunnen op deze manier het hele scherm van de tablet overnemen."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"algemene animatiesnelheid wijzigen"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Hiermee kan een app op elk gewenst moment de algemene animatiesnelheid wijzigen (snellere of tragere animaties)."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"toepassingstokens beheren"</string>
-    <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Hiermee kunnen toepassingen hun eigen tokens maken en beheren, waarbij de normale Z-volgorde wordt overgeslagen. Nooit nodig voor normale toepassingen."</string>
+    <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Hiermee kunnen apps hun eigen tokens maken en beheren, waarbij de normale Z-volgorde wordt overgeslagen. Nooit nodig voor normale apps."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"drukken op toetsen en bedieningselementen"</string>
     <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Hiermee kan een app de eigen invoergebeurtenissen (toetsaanslagen, enzovoort) aan andere apps doorgeven. Schadelijke apps kunnen dit gebruiken om de tablet over te nemen."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Hiermee kan een app zijn de invoergebeurtenissen (toetsaanslagen, enzovoort) aan andere apps doorgeven. Schadelijke apps kunnen dit gebruiken om de telefoon over te nemen."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"uw invoer en acties vastleggen"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Hiermee kan een app uw toetsaanslagen registreren, zelfs tijdens de interactie met een andere app (zoals de invoer van een wachtwoord). Nooit vereist voor normale apps."</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"verbinden aan een invoermethode"</string>
-    <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Hiermee staat u de houder toe zich te verbinden met de hoofdinterface van een invoermethode. Nooit vereist voor normale toepassingen."</string>
+    <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Hiermee staat u de houder toe zich te verbinden met de hoofdinterface van een invoermethode. Nooit vereist voor normale apps."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"verbinden met een achtergrond"</string>
-    <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Hiermee staat u de houder toe zich te verbinden met de hoofdinterface van een achtergrond. Nooit vereist voor normale toepassingen."</string>
+    <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Hiermee staat u de houder toe zich te verbinden met de hoofdinterface van een achtergrond. Nooit vereist voor normale apps."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"verbinden met een widgetservice"</string>
-    <string name="permdesc_bindRemoteViews" msgid="2930855984822926963">"Hiermee staat u de houder toe verbinding te maken met de hoofdinterface van een widgetservice. Nooit vereist voor normale toepassingen."</string>
+    <string name="permdesc_bindRemoteViews" msgid="2930855984822926963">"Hiermee staat u de houder toe verbinding te maken met de hoofdinterface van een widgetservice. Nooit vereist voor normale apps."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactie met apparaatbeheer"</string>
-    <string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Staat de houder toe intenties te verzenden naar een apparaatbeheerder. Nooit vereist voor normale toepassingen."</string>
+    <string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Staat de houder toe intenties te verzenden naar een apparaatbeheerder. Nooit vereist voor normale apps."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"schermstand wijzigen"</string>
     <string name="permdesc_setOrientation" msgid="6335814461615851863">"Hiermee kan een app op elk gewenst moment de oriëntatie van het scherm wijzigen. Nooit vereist voor normale apps."</string>
     <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"aanwijzersnelheid wijzigen"</string>
     <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Hiermee kan een app de snelheid van de muis- of trackpadaanwijzer op elk moment wijzigen. Dit zou voor normale apps niet nodig moeten zijn."</string>
-    <string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"Linux-signalen verzenden naar toepassingen"</string>
+    <string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"Linux-signalen verzenden naar apps"</string>
     <string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Hiermee kan de app ervoor zorgen dat het geleverde signaal wordt verzonden naar alle persistente processen."</string>
     <string name="permlab_persistentActivity" msgid="8659652042401085862">"app altijd laten uitvoeren"</string>
     <string name="permdesc_persistentActivity" msgid="5037199778265006008">"Hiermee kan een app delen van zichzelf persistent maken, zodat het systeem dat deel niet voor andere apps kan gebruiken."</string>
-    <string name="permlab_deletePackages" msgid="3343439331576348805">"toepassingen verwijderen"</string>
+    <string name="permlab_deletePackages" msgid="3343439331576348805">"apps verwijderen"</string>
     <string name="permdesc_deletePackages" msgid="3634943677518723314">"Hiermee kan een app Android-pakketten verwijderen. Schadelijke apps kunnen dit gebruiken om belangrijke apps te verwijderen."</string>
-    <string name="permlab_clearAppUserData" msgid="2192134353540277878">"gegevens van andere toepassingen verwijderen"</string>
+    <string name="permlab_clearAppUserData" msgid="2192134353540277878">"gegevens van andere apps verwijderen"</string>
     <string name="permdesc_clearAppUserData" msgid="7546345080434325456">"Hiermee kan een app gebruikersgegevens wissen."</string>
-    <string name="permlab_deleteCacheFiles" msgid="1518556602634276725">"caches van andere toepassingen verwijderen"</string>
+    <string name="permlab_deleteCacheFiles" msgid="1518556602634276725">"caches van andere apps verwijderen"</string>
     <string name="permdesc_deleteCacheFiles" msgid="2283074077168165971">"Hiermee kan een app cachebestanden verwijderen."</string>
     <string name="permlab_getPackageSize" msgid="4799785352306641460">"opslagruimte van app bepalen"</string>
     <string name="permdesc_getPackageSize" msgid="5557253039670753437">"Hiermee kan een app de bijbehorende code, gegevens en cachegrootten ophalen."</string>
-    <string name="permlab_installPackages" msgid="335800214119051089">"toepassingen rechtstreeks installeren"</string>
+    <string name="permlab_installPackages" msgid="335800214119051089">"apps rechtstreeks installeren"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Hiermee kan een app nieuwe of bijgewerkte Android-pakketten installeren. Schadelijke apps kunnen hiervan gebruik maken om nieuwe apps met willekeurig krachtige machtigingen toe te voegen."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"alle cachegegevens van app verwijderen"</string>
     <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Hiermee kan een app opslagruimte op de tablet vrij maken door bestanden te verwijderen uit de cachemap van de app. De toegang is doorgaans beperkt tot het systeemproces."</string>
@@ -319,31 +319,27 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"contactgegevens schrijven"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Hiermee kan een app de op uw tablet opgeslagen contactgegevens (adresgegevens) wijzigen. Schadelijke apps kunnen hiermee uw contactgegevens verwijderen of wijzigen."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Hiermee kan een app de op uw telefoon opgeslagen contactgegevens (adresgegevens) wijzigen. Schadelijke apps kunnen hiermee uw contactgegevens verwijderen of wijzigen."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"profielgegevens lezen"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Hiermee kan een app al uw persoonlijke profielgegevens lezen. Schadelijke apps kunnen dit gebruiken om u te identificeren en uw persoonlijke gegevens naar andere mensen te verzenden."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"profielgegevens schrijven"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Hiermee kan een app uw persoonlijke profielgegevens aanpassen. Schadelijke apps kunnen dit gebruiken om uw profielgegevens te wissen of aan te passen."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"agendagebeurtenissen lezen"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Hiermee kan een app alle agendagebeurtenissen lezen die zijn opgeslagen op uw tablet. Schadelijke apps kunnen hiervan gebruik maken om uw agendagebeurtenissen te verzenden naar andere personen."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Hiermee kan een app alle agendagebeurtenissen lezen die zijn opgeslagen op uw telefoon. Schadelijke apps kunnen hiervan gebruik maken om uw agendagebeurtenissen te verzenden naar andere personen."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"agendagebeurtenissen toevoegen of aanpassen en e-mail verzenden naar gasten"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Een app toestaan gebeurtenissen aan uw agenda toe te voegen of te wijzigen, wat inhoudt dat er e-mails kunnen worden verzonden naar gasten. Schadelijke apps kunnen dit gebruiken om uw agendagebeurtenissen te wissen of aan te passen of om e-mail naar gasten te verzenden."</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"neplocatiebronnen voor test"</string>
-    <string name="permdesc_accessMockLocation" msgid="7648286063459727252">"Neplocatiebronnen voor testdoeleinden maken. Schadelijke toepassingen kunnen dit gebruiken om de locatie en/of status te overschrijven die door de echte locatiebronnen wordt aangegeven, zoals GPS of netwerkaanbieders."</string>
+    <string name="permdesc_accessMockLocation" msgid="7648286063459727252">"Neplocatiebronnen voor testdoeleinden maken. Schadelijke apps kunnen dit gebruiken om de locatie en/of status te overschrijven die door de echte locatiebronnen wordt aangegeven, zoals GPS of netwerkaanbieders."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"toegang tot extra opdrachten van locatieaanbieder"</string>
-    <string name="permdesc_accessLocationExtraCommands" msgid="1948144701382451721">"Toegang tot extra opdrachten van locatieaanbieder. Schadelijke toepassingen kunnen hiervan gebruik maken om de werking van GPS of andere locatiebronnen te verstoren."</string>
+    <string name="permdesc_accessLocationExtraCommands" msgid="1948144701382451721">"Toegang tot extra opdrachten van locatieaanbieder. Schadelijke apps kunnen hiervan gebruik maken om de werking van GPS of andere locatiebronnen te verstoren."</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"toestemming om een locatieprovider te installeren"</string>
-    <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Neplocatiebronnen voor testdoeleinden maken. Schadelijke toepassingen kunnen dit gebruiken om de locatie en/of status te overschrijven die door de echte locatiebronnen, zoals GPS of netwerkaanbieders, wordt aangegeven of om uw locatie bij te houden en te rapporteren aan externe bronnen."</string>
+    <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Neplocatiebronnen voor testdoeleinden maken. Schadelijke apps kunnen dit gebruiken om de locatie en/of status te overschrijven die door de echte locatiebronnen, zoals GPS of netwerkaanbieders, wordt aangegeven of om uw locatie bij te houden en te rapporteren aan externe bronnen."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"nauwkeurige (GPS) locatie"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Toegang tot exacte locatiebronnen, zoals het Global Positioning System op de tablet, indien beschikbaar. Schadelijke toepassingen kunnen dit gebruiken om te bepalen waar u zich bevindt en mogelijk extra acculading verbruiken."</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Toegang tot exacte locatiebronnen, zoals het Global Positioning System op de telefoon, indien beschikbaar. Schadelijke toepassingen kunnen dit gebruiken om te bepalen waar u zich bevindt en mogelijk extra acculading verbruiken."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Toegang tot exacte locatiebronnen, zoals het Global Positioning System op de tablet, indien beschikbaar. Schadelijke apps kunnen dit gebruiken om te bepalen waar u zich bevindt en mogelijk extra acculading verbruiken."</string>
+    <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Toegang tot exacte locatiebronnen, zoals het Global Positioning System op de telefoon, indien beschikbaar. Schadelijke apps kunnen dit gebruiken om te bepalen waar u zich bevindt en mogelijk extra acculading verbruiken."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"globale (netwerkgebaseerde) locatie"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Toegang tot globale locatiebronnen, zoals de mobiele netwerkdatabase om een globale tabletlocatie te bepalen, indien beschikbaar. Schadelijke toepassingen kunnen hiervan gebruik maken om bij benadering te bepalen waar u zich bevindt."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Toegang tot globale locatiebronnen, zoals de mobiele netwerkdatabase om een globale telefoonlocatie te bepalen, indien beschikbaar. Schadelijke toepassingen kunnen hiervan gebruik maken om bij benadering te bepalen waar u zich bevindt."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Toegang tot globale locatiebronnen, zoals de mobiele netwerkdatabase om een globale tabletlocatie te bepalen, indien beschikbaar. Schadelijke apps kunnen hiervan gebruik maken om bij benadering te bepalen waar u zich bevindt."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Toegang tot globale locatiebronnen, zoals de mobiele netwerkdatabase om een globale telefoonlocatie te bepalen, indien beschikbaar. Schadelijke apps kunnen hiervan gebruik maken om bij benadering te bepalen waar u zich bevindt."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"toegang tot SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Hiermee kan een app SurfaceFlinger-functies op laag niveau gebruiken."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"framebuffer lezen"</string>
@@ -394,9 +390,9 @@
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"meteen starten met CDMA-telefooninstelling"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Hiermee kan de app starten met CDMA-provisioning. Schadelijke apps kunnen de CDMA-provisioning onnodig starten"</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"meldingen over locatie-updates beheren"</string>
-    <string name="permdesc_locationUpdates" msgid="2300018303720930256">"Hiermee kunnen updatemeldingen voor locaties van de radio worden ingeschakeld/uitgeschakeld. Niet voor gebruik door normale toepassingen."</string>
+    <string name="permdesc_locationUpdates" msgid="2300018303720930256">"Hiermee kunnen updatemeldingen voor locaties van de radio worden ingeschakeld/uitgeschakeld. Niet voor gebruik door normale apps."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"toegang tot checkin-eigenschappen"</string>
-    <string name="permdesc_checkinProperties" msgid="7150307006141883832">"Hiermee wordt lees-/schrijftoegang gegeven tot eigenschappen die door de checkin-service zijn geüpload. Niet voor gebruik door normale toepassingen."</string>
+    <string name="permdesc_checkinProperties" msgid="7150307006141883832">"Hiermee wordt lees-/schrijftoegang gegeven tot eigenschappen die door de checkin-service zijn geüpload. Niet voor gebruik door normale apps."</string>
     <string name="permlab_bindGadget" msgid="776905339015863471">"widgets kiezen"</string>
     <string name="permdesc_bindGadget" msgid="2098697834497452046">"Hiermee kan een app het systeem melden welke widgets door welke app kunnen worden gebruikt. Met deze toestemming kunnen apps andere apps toegang geven tot persoonlijke gegevens. Niet voor gebruik door normale apps."</string>
     <string name="permlab_modifyPhoneState" msgid="8423923777659292228">"telefoonstatus wijzigen"</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Staat een app toe het cachebestandssysteem te lezen en te schrijven."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"internetoproepen starten/ontvangen"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Hiermee kan een app de SIP-service gebruiken om internetoproepen te starten/te ontvangen."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"historisch netwerkgebruik lezen"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Hiermee kan een app historisch netwerkgebruik voor specifieke netwerken en apps lezen."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"netwerkbeleid beheren"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Hiermee kan een app het netwerkbeleid beheren en app-specifieke regels definiëren."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"verrekening van netwerkgebruik aanpassen"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Toestaan dat de manier waarop het netwerkgebruik wordt verrekend met applicaties, wordt aangepast. Niet voor gebruik door normale applicaties."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Wachtwoordregels instellen"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"De lengte en tekens beheren die zijn toegestaan in wachtwoorden voor schermontgrendeling"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Pogingen voor schermontgrendeling bijhouden"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Beheren hoe vaak het wachtwoord voor schermvergrendeling moet worden gewijzigd"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Codering voor opslag instellen"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Vereisen dat opgeslagen toepassingsgegevens kunnen worden gecodeerd"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Camera\'s uitschakelen"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Het gebruik van alle apparaatcamera\'s voorkomen"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Thuis"</item>
     <item msgid="869923650527136615">"Mobiel"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Geen SIM-kaart in tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Geen SIM-kaart in telefoon."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Plaats een SIM-kaart."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"De simkaart ontbreekt of kan niet worden gelezen. Plaats een simkaart."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Uw simkaart is permanent uitgeschakeld."\n" Neem contact op met uw draadloze serviceprovider voor een nieuwe simkaart."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Alleen noodoproepen"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Netwerk vergrendeld"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM-kaart is vergrendeld met PUK-code."</string>
@@ -951,12 +941,16 @@
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"USB-opslag uitschakelen"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Er is een probleem opgetreden tijdens het uitschakelen van de USB-opslag. Controleer of u de USB-host heeft losgekoppeld en probeer het opnieuw."</string>
     <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"USB-opslag inschakelen"</string>
-    <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Als u USB-opslag inschakelt, worden bepaalde toepassingen die u gebruikt, gestopt en worden deze mogelijk pas weer beschikbaar wanneer u USB-opslag uitschakelt."</string>
+    <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Als u USB-opslag inschakelt, worden bepaalde apps die u gebruikt, gestopt en worden deze mogelijk pas weer beschikbaar wanneer u USB-opslag uitschakelt."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-bewerking mislukt"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB-opslag formatt."</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD-kaart formatteren"</string>
@@ -995,9 +989,9 @@
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-kaart verwijderd. Plaats een nieuwe."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Geen overeenkomende activiteiten gevonden"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"gebruiksstatistieken van component bijwerken"</string>
-    <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Hiermee kunnen verzamelde gebruiksstatistieken van een component worden gewijzigd. Niet voor gebruik door normale toepassingen."</string>
-    <string name="permlab_copyProtectedData" msgid="1660908117394854464">"Staat het aanroepen van de standaardcontainerservice toe om inhoud te kopiëren. Niet voor gebruik door normale toepassingen."</string>
-    <string name="permdesc_copyProtectedData" msgid="537780957633976401">"Staat het aanroepen van de standaardcontainerservice toe om inhoud te kopiëren. Niet voor gebruik door normale toepassingen."</string>
+    <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Hiermee kunnen verzamelde gebruiksstatistieken van een component worden gewijzigd. Niet voor gebruik door normale apps."</string>
+    <string name="permlab_copyProtectedData" msgid="1660908117394854464">"Staat het aanroepen van de standaardcontainerservice toe om inhoud te kopiëren. Niet voor gebruik door normale apps."</string>
+    <string name="permdesc_copyProtectedData" msgid="537780957633976401">"Staat het aanroepen van de standaardcontainerservice toe om inhoud te kopiëren. Niet voor gebruik door normale apps."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tik twee keer voor zoomregeling"</string>
     <string name="gadget_host_error_inflating" msgid="2613287218853846830">"Fout bij uitbreiden van widget"</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Ga"</string>
@@ -1009,7 +1003,7 @@
     <string name="ime_action_default" msgid="2840921885558045721">"Uitvoeren"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Nummer bellen"\n"met <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Contact maken"\n"met <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="grant_credentials_permission_message_header" msgid="6824538733852821001">"De volgende toepassingen vragen toegang tot uw account, nu en in de toekomst."</string>
+    <string name="grant_credentials_permission_message_header" msgid="6824538733852821001">"De volgende apps vragen toegang tot uw account, nu en in de toekomst."</string>
     <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Wilt u dit verzoek toestaan?"</string>
     <string name="grant_permissions_header_text" msgid="2722567482180797717">"Toegangsverzoek"</string>
     <string name="allow" msgid="7225948811296386551">"Toestaan"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Toegankelijkheid"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Achtergrond"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Achtergrond wijzigen"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Point-to-Point Tunneling Protocol (PPTP)"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunneling Protocol (L2TP)"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Vooraf gedeelde sleutel op basis van L2TP/IPSec VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Certificaat op basis van L2TP/IPSec VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Tik om het netwerk te beheren."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Verbonden met <xliff:g id="SESSION">%s</xliff:g>. Tik om het netwerk te beheren."</string>
     <string name="upload_file" msgid="2897957172366730416">"Bestand kiezen"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Geen bestand geselecteerd"</string>
     <string name="reset" msgid="2448168080964209908">"Opnieuw instellen"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"De items verwijderen."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Verwijderingen ongedaan maken."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Nu niets doen."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> verbonden via VPN"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"VPN-verbinding met <xliff:g id="PROFILENAME">%s</xliff:g> verbroken"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Raak aan om opnieuw verbinding te maken met een VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Selecteer een account"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Hoger"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Lager"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD-kaart"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-opslag"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Bewerken..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Waarschuwing v. gegevensgebruik"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"gebruik hoger dan <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-/3G-gegevens uitgeschakeld"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G-gegevens uitgeschakeld"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobiele gegevens uitgeschakeld"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"tik om in te schakelen"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Beveiligingscertificaat"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Dit certificaat is geldig."</string>
+    <string name="issued_to" msgid="454239480274921032">"Uitgegeven voor:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Algemene naam:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organisatie:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Organisatie-eenheid:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Uitgegeven door:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Geldigheid:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Uitgegeven op:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Verloopt op:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 10bc614..85f2bad 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Tryb samolotowy"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Tryb samolotowy jest włączony"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Tryb samolotowy jest wyłączony"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string>
     <string name="android_system_label" msgid="6577375335728551336">"System Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Usługi płatne"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"zapisywanie danych kontaktowych"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Zezwala aplikacji na modyfikowanie danych kontaktowych (adresów) zapisanych w tablecie. Złośliwe aplikacje mogą wykorzystać tę możliwość w celu usunięcia lub zmodyfikowania danych kontaktowych."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Pozwala aplikacji na zmianę danych kontaktowych (adresowych) zapisanych w telefonie. Szkodliwe aplikacje mogą to wykorzystać, aby usunąć lub zmienić dane kontaktowe."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"odczyt danych profilu"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Zezwala aplikacji na odczyt wszystkich informacji z Twojego profilu osobistego. Złośliwe aplikacje mogą wykorzystać tę możliwość w celu zidentyfikowania Cię i wysłania Twoich informacji osobistych do innych osób."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"zapis danych profilu"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Zezwala aplikacji na modyfikowanie informacji w Twoim profilu osobistym. Złośliwe aplikacje mogą wykorzystać tę możliwość w celu usunięcia lub zmodyfikowania danych profilu."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"odczytywanie wydarzeń w kalendarzu"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Zezwala aplikacji na odczyt wszystkich wydarzeń z kalendarza zapisanych w tablecie. Złośliwe aplikacje mogą wykorzystać tę możliwość w celu wysłania wydarzeń z kalendarza do innych osób."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Pozwala aplikacji na odczytywanie wszystkich wydarzeń z kalendarza, zapisanych w telefonie. Szkodliwe aplikacje mogą to wykorzystać do rozsyłania wydarzeń z kalendarza do innych ludzi."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Zezwala aplikacji na odczyt i zapis w systemie plików pamięci podręcznej."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"nawiązywanie/odbieranie połączeń przez internet"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Umożliwia aplikacji korzystanie z usługi SIP do nawiązywania/odbierania połączeń przez internet."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"odczyt historii wykorzystania sieci"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Zezwala aplikacji na odczyt historii wykorzystania określonych sieci przez poszczególne aplikacje."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"zarządzanie zasadami dotyczącymi sieci"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Zezwala aplikacji na zarządzanie zasadami dotyczącymi sieci i definiowanie reguł aplikacji."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modyfikowanie sposobu naliczania użycia sieci"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Umożliwia modyfikowanie sposobu naliczania użycia sieci dla aplikacji. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Określ reguły hasła"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontrolowanie długości haseł odblokowania ekranu i dozwolonych w nich znaków"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitoruj próby odblokowania ekranu"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrola częstości zmian hasła ekranu blokady"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Ustaw szyfrowanie pamięci"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Wymaga szyfrowania danych zapisanych aplikacji"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Wyłącz aparaty"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Nie zezwalaj na używanie żadnego aparatu w urządzeniu"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Dom"</item>
     <item msgid="869923650527136615">"Komórka"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Brak karty SIM w tablecie."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Brak karty SIM w telefonie."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Włóż kartę SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Brak karty SIM lub nie można jej odczytać. Włóż kartę SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Karta SIM jest trwale wyłączona."\n" Skontaktuj się z dostawcą usług bezprzewodowych, aby uzyskać inną kartę SIM."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Tylko połączenia alarmowe"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Sieć zablokowana"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Karta SIM jest zablokowana kodem PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Po włączeniu nośnika USB niektóre używane aplikacje zostaną zatrzymane i mogą być niedostępne do chwili wyłączenia nośnika USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Operacja USB nie powiodła się"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatuj nośnik USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatuj kartę SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Ułatwienia dostępu"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Zmień tapetę"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Protokół PPTP"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protokół L2TP"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Sieć VPN L2TP/IPSec z kluczem PSK"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sieć VPN L2TP/IPSec z certyfikatem"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Dotknij, aby zarządzać siecią."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Nawiązano połączenie: <xliff:g id="SESSION">%s</xliff:g>. Dotknij, aby zarządzać siecią."</string>
     <string name="upload_file" msgid="2897957172366730416">"Wybierz plik"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nie wybrano pliku"</string>
     <string name="reset" msgid="2448168080964209908">"Resetuj"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Usuń elementy."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Cofnij usunięcie."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Nie wykonuj teraz żadnych czynności."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"Połączono z siecią VPN <xliff:g id="PROFILENAME">%s</xliff:g>"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"Rozłączono z siecią VPN <xliff:g id="PROFILENAME">%s</xliff:g>"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Dotknij, aby ponownie połączyć się z siecią VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Wybierz konto"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Zwiększ"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Zmniejsz"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Karta SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Nośnik USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Edytuj..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Ostrzeżenie o transmisji danych"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"ilość danych przekracza <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Wyłączono transmisję danych 2G/3G"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Wyłączono transmisję danych 4G"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Wyłączono komórkową transm. danych"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"dotknij, aby włączyć"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Certyfikat zabezpieczeń"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Certyfikat jest ważny."</string>
+    <string name="issued_to" msgid="454239480274921032">"Wystawiony dla:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Nazwa pospolita (CN):"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organizacja:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Jednostka organizacyjna:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Wystawca:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Ważność:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Data wystawienia:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Wygasa:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 4972e56..9761b71 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo de avião"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"O modo de voo está activado"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"O modo de voo está desactivado"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serviços que implicam pagamento"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"escrever dados de contacto"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite a uma aplicação modificar os dados de contacto (endereço) armazenados no seu tablet. Algumas aplicações maliciosas podem utilizar estes dados para apagar ou modificar os dados dos seus contactos."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permite a uma aplicação modificar os dados de contacto (endereço) armazenados no seu telefone. Algumas aplicações maliciosas podem utilizar estes dados para apagar ou modificar os dados dos seus contactos."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"ler os dados de perfil"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Permite que uma aplicação leia as informações pessoais do seu perfil. As aplicações maliciosas poderão utilizar isto para identificá-lo e enviar os seus dados pessoais para outras pessoas."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"escrever os dados do perfil"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Permite que uma aplicação altere as informações pessoais do seu perfil. As aplicações maliciosas podem utilizar isto para apagar ou alterar os dados do seu perfil."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"ler eventos da agenda"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permite a uma aplicação ler todos os eventos do calendário armazenados no seu tablet. Algumas aplicações maliciosas podem utilizar este item para enviar os eventos do seu calendário a outras pessoas."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permite a uma aplicação ler todos os eventos do calendário armazenados no seu telefone. Algumas aplicações maliciosas podem utilizar este item para enviar os eventos do seu calendário a outras pessoas."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite a uma aplicação ler e escrever no sistema de ficheiros da cache."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"fazer/receber chamadas pela internet"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Autoriza uma aplicação a utilizar o serviço SIP para fazer/receber chamadas pela internet."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"ler utilização histórica da rede"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Permite que uma aplicação leia utilização histórica da rede para redes e aplicações específicas."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"gerir a política de rede"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Permite que uma aplicação faça a gestão de políticas de rede e defina regras específicas de aplicações."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificar contabilização da utilização da rede"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Permite a modificação da contabilização da utilização da rede relativamente às aplicações. Não se destina à utilização em aplicações normais."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras de palavra-passe"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlar o comprimento e os caracteres permitidos nas palavras-passe de desbloqueio do ecrã"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizar tentativas de desbloqueio do ecrã"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar a frequência com que a palavra-passe deve ser alterada"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Def. encriptação armazenamento"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Requerer encriptação dos dados da aplicação armazenados"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Desativar câmaras"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Evitar a utilização de todas as câmaras do aparelho"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Residência"</item>
     <item msgid="869923650527136615">"Móvel"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nenhum cartão SIM no tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Nenhum cartão SIM no telefone."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Introduza um cartão SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"O cartão SIM está em falta ou não é legível. Introduza um cartão SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"O seu cartão SIM está desativado definitivamente."\n" Contacte o seu fornecedor de serviços de rede sem fios para obter outro cartão."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Apenas chamadas de emergência"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Rede bloqueada"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"O cartão SIM está bloqueado por PUK"</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se activar o armazenamento USB, algumas aplicações que estiver a utilizar serão paradas e poderão ficar indisponíveis até desactivar o armazenamento USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Falha na operação USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatar armaz. USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatar cartão SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Acessibilidade"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagem de fundo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar imagem de fundo"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Protocolo de túnel ponto a ponto (PPTP)"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocolo de túnel de camada 2 (L2TP)"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec baseada em chave pré- partilhada"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec baseada em certificado"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Toque para gerir a rede."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Ligado a <xliff:g id="SESSION">%s</xliff:g>. Toque para gerir a rede."</string>
     <string name="upload_file" msgid="2897957172366730416">"Escolher ficheiro"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Não foi seleccionado nenhum ficheiro"</string>
     <string name="reset" msgid="2448168080964209908">"Repor"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Eliminar os itens."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Anular as eliminações."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Não fazer nada por agora."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> ligada"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> desligada"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Toque para voltar a ligar a uma VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Seleccionar conta"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Aumentar"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Diminuir"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Cartão SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Armazenamento USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Editar..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Aviso de utilização de dados"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"a utilização excede <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Os dados 2G-3G estão desativados"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Os dados 4G estão desativados"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Os dados móveis estão desativados"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"toque para ativar"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Certificado de segurança"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Este certificado é válido."</string>
+    <string name="issued_to" msgid="454239480274921032">"Emitido para:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Nome comum:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organização:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Unidade organizacional:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Emitido por:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Validade:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Emitido em:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Expira em:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index a17277e..a56523f 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo de avião"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modo de avião ATIVADO"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modo de avião DESATIVADO"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"Mais de cem"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serviços que geram gastos"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"gravar dados de contato"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite que um aplicativo modifique os dados de contato (endereço) armazenados em seu tablet. Aplicativos maliciosos podem usar isso para apagar ou modificar seus dados de contato."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permite que um aplicativo modifique os dados de contato (endereço) armazenados no seu telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar os seus dados de contato."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"ler dados do perfil"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Permite que um aplicativo leia todas as informações pessoais do seu perfil. Aplicativos suspeitos podem usar isso para identificá-lo e enviar suas informações pessoais para outras pessoas."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"gravar dados do perfil"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Permite que um aplicativo modifique as informações pessoais do seu perfil. Aplicativos suspeitos podem usar isso para apagar ou alterar dados do seu perfil."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"ler eventos da agenda"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permite que um aplicativo leia todos os eventos da agenda armazenados em seu tablet. Aplicativos maliciosos podem usar isso para enviar eventos de sua agenda para outras pessoas."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permite que um aplicativo leia todos os eventos da agenda armazenados no seu telefone. Aplicativos maliciosos podem usar isso para enviar eventos da sua agenda para outras pessoas."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite que um aplicativo leia e grave no sistema de arquivos de cache."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"fazer/receber chamadas pela internet"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Permite que um aplicativo use o serviço SIP para fazer/receber chamadas pela internet."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"ler histórico de uso da rede"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Permite que um aplicativo leia o histórico de uso da rede em redes e aplicativos específicos."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"gerenciar a política de rede"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Permite que um aplicativo gerencie as políticas de rede e defina regras específicas aos aplicativos."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificar contagem de uso da rede"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Permite modificar como o uso da rede é registrado em comparação aos aplicativos. Não deve ser usado em aplicativos normais."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controla o tamanho e os caracteres permitidos nas senhas de desbloqueio de tela"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorar tentativas de desbloqueio da tela"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar a frequência com que a senha da tela de bloqueio deve ser alterada"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Definir criptografia de armazenamento"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Exigir que os dados do aplicativo armazenado sejam criptografados"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Desativar câmeras"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Impedir o uso de todas as câmeras do dispositivo"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Residencial"</item>
     <item msgid="869923650527136615">"Celular"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Não há um cartão SIM no tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Não há um cartão SIM no telefone."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Insira um cartão SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"O cartão SIM não foi inserido ou não está legível. Insira um cartão SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Seu cartão SIM está permanentemente desativado."\n" Entre em contato com seu provedor de serviços de rede sem fio para obter outro cartão SIM."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Apenas chamadas de emergência"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Rede bloqueada"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"O cartão SIM está bloqueado pelo PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se você ativar o armazenamento USB, alguns aplicativos que estão em uso serão interrompidos e poderão não estar disponíveis até você desativar o armazenamento USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Falha de operação de USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatar armaz. USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatar cartão SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Acessibilidade"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Plano de fundo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar plano de fundo"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Protocolo de encapsulamento ponto a ponto"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocolo de encapsulamento de camada 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec com base em chave pré-compartilhada"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec com base em certificado"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Toque para gerenciar a rede."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toque para gerenciar a rede."</string>
     <string name="upload_file" msgid="2897957172366730416">"Escolher arquivo"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nenhum arquivo escolhido"</string>
     <string name="reset" msgid="2448168080964209908">"Redefinir"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Excluir os itens."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Desfazer as exclusões."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Não fazer nada por enquanto."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"VPN de <xliff:g id="PROFILENAME">%s</xliff:g> conectada"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"VPN de <xliff:g id="PROFILENAME">%s</xliff:g> desconectada"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Toque para reconectar-se a uma VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Selecione uma conta"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Incremento"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Redução"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Cartão SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Armazenamento USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Editar..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Aviso sobre uso de dados"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"o uso excede <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Dados 2G e 3G desativados"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Dados 4G desativados"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Dados móveis desativados"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"toque para ativar"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Certificado de segurança"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Este certificado é válido."</string>
+    <string name="issued_to" msgid="454239480274921032">"Emitido para:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Nome comum:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organização:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Unidade organizacional:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Emitido por:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Validade:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Emitido em:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Expira em:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index b1fa217..7048c69 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -528,6 +528,10 @@
     <skip />
     <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
     <skip />
+    <!-- no translation found for permlab_modifyNetworkAccounting (5088217309088729650) -->
+    <skip />
+    <!-- no translation found for permdesc_modifyNetworkAccounting (8702285686629184404) -->
+    <skip />
     <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Limitar il pled-clav"</string>
     <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Restrenscher ils tips da pleds-clav che Vus pudais utilisar."</string>
     <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Survegliar las emprovas da s\'annunziar"</string>
@@ -1029,9 +1033,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Sche Vus activais l\'apparat periferic da memoria USB sa ferman tschertas applicaziuns che Vus utilisais. Ellas n\'èn probablamain betg disponiblas enfin che l\'apparat periferic vegn puspè deactivà."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Operaziun USB betg reussida"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatar la carta SD"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatar la carta SD"</string>
@@ -1098,13 +1106,9 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Agids d\'access"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fund davos"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Midar il fund davos"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Point-to-Point Tunneling Protocol"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocol Layer 2 Tunneling"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec basà sin ina clav precundividida"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec basà sin in certificat"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
     <!-- no translation found for vpn_text (1610714069627824309) -->
     <skip />
@@ -1185,12 +1189,6 @@
     <skip />
     <!-- no translation found for sync_do_nothing (8717589462945226869) -->
     <skip />
-    <!-- no translation found for vpn_notification_title_connected (3197819122581348515) -->
-    <skip />
-    <!-- no translation found for vpn_notification_title_disconnected (4614192702448522822) -->
-    <skip />
-    <!-- no translation found for vpn_notification_hint_disconnected (4689796928510104200) -->
-    <skip />
     <!-- no translation found for choose_account_label (4191313562041125787) -->
     <skip />
     <!-- no translation found for number_picker_increment_button (4830170763103463443) -->
@@ -1223,4 +1221,38 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <!-- no translation found for ssl_certificate (6510040486049237639) -->
+    <skip />
+    <!-- no translation found for ssl_certificate_is_valid (6825263250774569373) -->
+    <skip />
+    <!-- no translation found for issued_to (454239480274921032) -->
+    <skip />
+    <!-- no translation found for common_name (2233209299434172646) -->
+    <skip />
+    <!-- no translation found for org_name (6973561190762085236) -->
+    <skip />
+    <!-- no translation found for org_unit (7265981890422070383) -->
+    <skip />
+    <!-- no translation found for issued_by (2647584988057481566) -->
+    <skip />
+    <!-- no translation found for validity_period (8818886137545983110) -->
+    <skip />
+    <!-- no translation found for issued_on (5895017404361397232) -->
+    <skip />
+    <!-- no translation found for expires_on (3676242949915959821) -->
+    <skip />
+    <!-- no translation found for serial_number (758814067660862493) -->
+    <skip />
+    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <skip />
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
+    <skip />
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 404570a..69b111e 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mod Avion"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modul Avion este ACTIVAT"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modul avion este DEZACTIVAT"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100 +"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"˃999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicii cu plată"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"scriere date de contact"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite unei aplicaţii să modifice datele de contact (adresele) stocate pe computerul tablet PC. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a şterge sau a modifica datele dvs. de contact."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permite unei aplicaţii să modifice datele de contact (adresele) stocate pe telefon. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a şterge sau a modifica datele dvs. de contact."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"citeşte datele de profil"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Permite unei aplicaţii să citească toate informaţiile din profilul dvs. personal. Aplicaţiile rău-intenţionate pot utiliza această permisiune pentru a vă identifica şi a trimite informaţiile dvs. personale altor persoane."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"scrie datele de profil"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Permite unei aplicaţii să modifice informaţiile din profilul dvs. personal. Aplicaţiile rău-intenţionate pot folosi această permisiune pentru a şterge sau a modifica datele de profil."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"citire evenimente din calendar"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permite unei aplicaţii să citească toate evenimentele din calendar stocate pe computerul tablet PC. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a trimite evenimentele din calendar către alte persoane."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permite unei aplicaţii să citească toate evenimentele din calendar stocate pe telefon. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a trimite evenimentele din calendar către alte persoane."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite unei aplicaţii să scrie şi să citească sistemul de fişiere cache."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"efectuare/primire apeluri prin internet"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Permite unei aplicaţii să utilizeze serviciul SIP pentru a efectua/primi apeluri prin internet."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"citeşte utilizarea statistică a reţelei"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Permite unei aplicaţii să citească utilizarea statistică a reţelei pentru anumite reţele şi aplicaţii."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"gestionează politica de reţea"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Permite unei aplicaţii să gestioneze politicile de reţea şi să definească regulile specifice aplicaţiilor."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificaţi modul de calcul al utilizării reţelei"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Permite modificarea modului în care este calculată utilizarea reţelei în privinţa aplicaţiilor. Nu se utilizează de aplicaţiile obişnuite."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setaţi reguli pentru parolă"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlarea lungimii şi a tipului de caractere permise în parolele pentru deblocarea ecranului."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizaţi încercările de deblocare a ecranului"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Stabiliţi frecvenţa de schimbare a parolei de blocare a ecranului"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Setaţi criptarea stocării"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Necesită ca datele aplicaţiei stocate să fie criptate"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Dezactivaţi camerele foto"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Împiedică utilizarea camerelor foto de pe dispozitiv"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domiciliu"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nu există card SIM în computerul tablet PC."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefonul nu are card SIM."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Introduceţi un card SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Cartela SIM lipseşte sau nu poate fi citită. Introduceţi o cartelă SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Cartela dvs. SIM este dezactivată definitiv."\n" Contactaţi furnizorul de servicii wireless pentru a obţine o altă cartelă SIM."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Numai apeluri de urgenţă"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Reţea blocată"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Cardul SIM este blocat cu codul PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Dacă activaţi stocarea USB, unele aplicaţii pe care le utilizaţi în prezent se vor opri şi ar putea să nu fie disponibile până când dezactivaţi stocarea USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Operaţie USB nereuşită"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formataţi stoc. USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formataţi cardul SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accesibilitate"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagine de fundal"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Modificaţi imaginea de fundal"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Protocol de tunel punct la punct"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocol de tunel Nivel 2 (L2TP)"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec bazat pe cheie prepartajată"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec bazat pe certificat"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Apăsaţi pentru a gestiona reţeaua."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Conectat la <xliff:g id="SESSION">%s</xliff:g>. Apăsaţi pentru a gestiona reţeaua."</string>
     <string name="upload_file" msgid="2897957172366730416">"Alegeţi un fişier"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nu au fost găsite fişiere"</string>
     <string name="reset" msgid="2448168080964209908">"Resetaţi"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Ştergeţi elementele."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Anulaţi aceste ştergeri."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Pentru moment, nu efectuaţi nicio acţiune."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> conectat"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> deconectat"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Atingeţi pentru a vă reconecta la o reţea VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Selectaţi un cont"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Incrementaţi"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Decrementaţi"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Card SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Dsipozitiv de stocare USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Editaţi..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Avertisment de utiliz. a datelor"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"utilizarea depăşeşte <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Datele 2G-3G au fost dezactivate"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Datele 4G au fost dezactivate"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Datele mobile au fost dezactiv."</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"atingeţi pentru activare"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Certificat de securitate"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Certificatul este valid."</string>
+    <string name="issued_to" msgid="454239480274921032">"Emis către:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Nume comun:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organizaţie:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Unitate organizatorică:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Emis de:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Validitate:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Emis pe:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Expiră pe:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 44cc9df..95d4077 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим полета"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Режим полета ВКЛЮЧЕН"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Режим полета ВЫКЛЮЧЕН"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безопасный режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Платные услуги"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"перезаписывать данные контакта"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Позволяет приложению изменять данные (адрес) контакта, сохраненные в памяти планшетного ПК. Вредоносные приложения могут использовать эту возможность для удаления или изменения данных контакта."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Позволяет приложению изменять данные (адрес) контакта, сохраненные в памяти телефона. Вредоносные приложения могут использовать эту возможность для удаления или изменения данных контакта."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"получать данные профиля"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Разрешает приложению читать все личные данные вашего профиля. Вредоносные приложения могут использовать эту возможность, чтобы идентифицировать вас и отправить вашу личную информацию другим людям."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"записывать данные профиля"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Разрешает приложению изменять личную информацию вашего профиля. Вредоносные приложения могут использовать эту возможность для удаления или изменения данных профиля."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"считывать мероприятия в календаре"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Позволяет приложению считывать все события календаря, сохраненные на планшетном ПК. Вредоносные приложения могут использовать эту возможность для передачи ваших событий календаря посторонним лицам."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Позволяет приложению считывать все события календаря, сохраненные на телефоне. Вредоносные приложения могут использовать эту возможность для передачи ваших событий календаря посторонним лицам."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Разрешает программам доступ для записи и чтения к кэшу файловой системы."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"совершать и принимать интернет-вызовы"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Позволяет приложению использовать службу SIP для интернет-вызовов."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"читать журнал использования сети"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Разрешает приложению читать журнал использования определенных сетей и приложений."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"управление сетевой политикой"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Разрешает приложению управлять сетевыми политиками и задавать правила для приложений."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"изменение учета использования сети"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Позволяет изменить способ учета использования сети приложениями. Не для использования обычными приложениями."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Правила выбора паролей"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Контролировать длину и символы при вводе паролей для снятия блокировки экрана"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Отслеживать попытки снятия блокировки экрана"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Укажите, как часто следует менять пароль блокировки экрана"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Настроить шифрование хранилища"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Требует шифровать данные приложений, находящиеся в хранилище."</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Отключить камеры"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Запретить использование всех камер устройства"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Домашний"</item>
     <item msgid="869923650527136615">"Мобильный"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"SIM-карта не установлена."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"SIM-карта не установлена."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Вставьте SIM-карту."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"SIM-карта отсутствует или не читается. Вставьте SIM-карту."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Ваша SIM-карта окончательно заблокирована."\n"Чтобы получить новую SIM-карту, обратитесь к оператору мобильной связи."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Только экстренные вызовы"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Сеть заблокирована"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM-карта заблокирована с помощью кода PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"При включении USB-накопителя некоторые используемые приложения могут прекратить работу и оставаться недоступными до отключения USB-накопителя."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Сбой операции USB-подключения"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"ОК"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматирование"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Очистить SD-карту"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Спец. возможности"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновый рисунок"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Сменить обои"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Протокол PPTP"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Протокол L2TP"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN с использованием общего ключа"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN с использованием сертификатов"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Нажмите здесь, чтобы изменить настройки сети."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Подключено: \"<xliff:g id="SESSION">%s</xliff:g>\". Нажмите здесь, чтобы изменить настройки сети."</string>
     <string name="upload_file" msgid="2897957172366730416">"Выбрать файл"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Не выбран файл"</string>
     <string name="reset" msgid="2448168080964209908">"Сбросить"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Удалить элементы."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Отменить удаления."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Ничего не делать сейчас."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"Сеть VPN (<xliff:g id="PROFILENAME">%s</xliff:g>) подключена"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"Сеть VPN (<xliff:g id="PROFILENAME">%s</xliff:g>) отключена"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Нажмите для повторного подключения к VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Выберите аккаунт"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Увеличить"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Уменьшить"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD-карта"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-накопитель"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Изменить..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Осталось мало трафика"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"израсходовано больше <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Передача данных 2G/3G отключена"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Передача данных 4G отключена"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Мобильный Интернет отключен"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"Нажмите, чтобы снова включить."</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Сертификат безопасности"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Этот сертификат действителен."</string>
+    <string name="issued_to" msgid="454239480274921032">"Кому выдан:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Стандартное название:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Организация:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Подразделение организации:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Кем выдан:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Срок действия:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Дата выпуска:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Срок действия:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index dc962b1..e622cf1 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Režim V lietadle"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Režim V lietadle je ZAPNUTÝ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Režim V lietadle je VYPNUTÝ"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Núdzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Spoplatnené služby"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"zápis údajov kontaktov"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Umožňuje aplikácii zmeniť kontaktné údaje (adresu) uložené v tablete. Škodlivé aplikácie môžu pomocou tohto nastavenia vymazať alebo pozmeniť kontaktné údaje."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Umožňuje aplikácii zmeniť kontaktné údaje (adresu) uložené v telefóne. Škodlivé aplikácie môžu pomocou tohto nastavenia vymazať alebo pozmeniť kontaktné údaje."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"čítať údaje profilu"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Umožňuje aplikácii čítať všetky informácie osobného profilu. Škodlivé aplikácie to môžu využiť na zistenie vašej totožnosti a odosielanie vašich osobných informácií iným osobám."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"písať údaje profilu"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Umožňuje aplikácii zmeniť vaše osobné informácie v profile. Škodlivé aplikácie môžu pomocou tohto nastavenia vymazať alebo upraviť údaje vo vašom profile."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"čítanie udalostí v kalendári"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Umožňuje aplikácii načítať všetky udalosti kalendára uložené vo vašom tablete. Škodlivé aplikácie potom môžu ďalším ľuďom odoslať udalosti z vášho kalendára."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Umožňuje aplikácii načítať všetky udalosti kalendára uložené vo vašom telefóne. Škodlivé aplikácie potom môžu ďalším ľuďom odoslať udalosti z vášho kalendára."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Umožňuje aplikácii čítať a zapisovať do súborového systému vyrovnávacej pamäte."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"uskutočňovať a prijímať internetové hovory"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Umožňuje aplikácii uskutočniť a prijímať internetové hovory pomocou služby SIP."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"čítať históriu používania siete"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Umožňuje aplikácii čítať históriu používania siete (pri určitých sieťach a aplikáciách)."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"spravovať pravidlá siete"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Umožňuje aplikácii spravovať pravidlá siete a definovať pravidlá pre konkrétnu aplikáciu."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"zmeniť kontrolu používania siete"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Umožňuje upraviť spôsob kontroly používania siete v súvislosti s aplikáciami. Nie je určené pre bežné aplikácie."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastaviť pravidlá pre heslo"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Ovládať dĺžku hesiel pre odomknutie obrazovky a v nich používané znaky"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Sledovať pokusy o odomknutie obrazovky"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Nastavte, ako často sa musí zmeniť heslo na uzamknutie obrazovky"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nastaviť šifr. ukl. priestoru"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Vyžaduje šifrovanie uložených údajov aplikácií"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Zakázať fotoaparáty"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Zakázať používanie všetkých fotoaparátov zariadenia"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domovská stránka"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tablete nie je žiadna karta SIM."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"V telefóne nie je žiadna karta SIM."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Vložte kartu SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Karta SIM chýba alebo sa z nej nedá čítať. Vložte kartu SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Vaša karta SIM je natrvalo zakázaná."\n"Ak chcete získať inú kartu SIM, kontaktujte poskytovateľa bezdrôtových služieb."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Len tiesňové volania"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Sieť je zablokovaná"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Karta SIM je uzamknutá pomocou kódu PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ak zapnete ukladací priestor USB, dôjde k zastaveniu niektorých používaných aplikácií. Tieto aplikácie pravdepodobne nebudú k dispozícii až do vypnutia ukladacieho priestoru USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Chyba operácie na rozhraní USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formát. ukl. priestor USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formátovať kartu SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Zjednodušenie"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Zmeniť tapetu"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Protokol PPTP (Point-to-Point Tunneling Protocol)"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protokol L2TP (Layer 2 Tunneling Protocol)"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Sieť VPN L2TP/IPSec s vopred zdieľaným kľúčom"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sieť VPN L2TP/IPSec s certifikátom"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Kliknutím zobrazíte správu siete."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Pripojené k relácii <xliff:g id="SESSION">%s</xliff:g>. Po klepnutí môžete sieť spravovať."</string>
     <string name="upload_file" msgid="2897957172366730416">"Zvoliť súbor"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nie je vybratý žiadny súbor"</string>
     <string name="reset" msgid="2448168080964209908">"Obnoviť"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Odstrániť položky."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Vrátiť späť odstránenia."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Nevykonať akciu."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"Sieť VPN <xliff:g id="PROFILENAME">%s</xliff:g> je pripojená"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"Sieť VPN <xliff:g id="PROFILENAME">%s</xliff:g> odpojená"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Dotykom sa znova pripojíte k sieti VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Vybrať účet"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Zvýšenie"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Zníženie"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Karta SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Ukladací priestor USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Upraviť..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Upozornenie o využití dát"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"Objem prenes. dát prekrač. <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Dátové prenosy 2G a 3G zakázané"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Dátové prenosy 4G zakázané"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobilné dátové prenosy zakázané"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"klepnutím povolíte"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Certifikát zabezpečenia"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Certifikát je platný."</string>
+    <string name="issued_to" msgid="454239480274921032">"Vydané pre:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Bežný názov:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organizácia:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Organizačná jednotka:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Vydal:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Platnosť:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Dátum vydania:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Platnosť vyprší:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index e613bf0..d68a3a5 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Način za letalo"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Način za letalo je VKLOPLJEN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Način za letalo je IZKLOPLJEN"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100 +"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
     <string name="safeMode" msgid="2788228061547930246">"Varni način"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Plačljive storitve"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"pisanje podatkov stika"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Programu omogoča spreminjanje podatkov (naslovov), shranjenih v tabličnem računalniku. Zlonamerni programi lahko s tem dovoljenjem izbrišejo ali spremenijo podatke o stikih."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Programu dovoljuje spreminjanje podatkov stika (naslov), shranjenih v telefonu. Zlonamerni programi lahko to uporabijo za brisanje ali spreminjanje podatkov stika."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"branje podatkov profila"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Programu omogoča branje podatkov o osebnem profilu. Zlonamerni programi lahko to izkoristijo, da vas prepoznajo in drugim pošiljajo vaše osebne podatke."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"pisanje podatkov o profilu"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Programu omogoča spreminjanje podatkov o osebnem profilu. Zlonamerni programi lahko to izkoristijo za brisanje ali spreminjanje podatkov o profilu."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"branje koledarskih dogodkov"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Programu omogoča branje vseh koledarskih vnosov, shranjenih v tabličnem računalniku. Zlonamerni programi lahko s tem dovoljenjem pošljejo vnose drugim uporabnikom."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Programu dovoljuje branje vseh dogodkov koledarja, shranjenih v telefonu. Zlonamerni programi lahko to uporabijo za pošiljanje dogodkov koledarja drugim osebam."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Programu dovoljuje branje in pisanje v datotečni sistem predpomnilnika."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"opravljanje/sprejemanje internetnih klicev"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Programu omogoča uporabo storitve SIP za opravljanje in sprejemanje internetnih klicev."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"branje prejšnje uporabe omrežja"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Programu omogoča branje pretekle uporabe omrežja za določena omrežja in programe."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"upravljanje pravilnika o omrežju"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Programu omogoča upravljanje pravilnikov o omrežju in določanje pravil za program."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"spremeni obračunavanje uporabe omrežja"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Omogoča spreminjanje načina obračunavanja uporabe omrežja za posamezne programe. Ni za uporabo za pri navadnih programih."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavitev pravil za geslo"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih za odklepanje zaslona"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"nadzor nad poskusi odklepanja zaslona"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Določite, kako pogosto je treba spremeniti geslo za zaklepanje zaslona"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nastavitev šifriranja shrambe"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Shranjeni podatki programa morajo biti šifrirani"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Onemogoči fotoaparate"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Onemogočite uporabo vseh fotoaparatov v napravi"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Začetna stran"</item>
     <item msgid="869923650527136615">"Mobilni"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tabličnem računalniku ni kartice SIM."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"V telefonu ni kartice SIM."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Vstavite kartico SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Ni kartice SIM ali je ni mogoče prebrati. Vstavite kartico SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Kartica SIM je trajno onemogočena."\n" Če želite dobiti drugo kartico SIM, se obrnite na ponudnika brezžičnih storitev."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Le klici v sili"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Omrežje je zaklenjeno"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Kartica SIM je zaklenjena s kodo PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Če vklopite shrambo USB, bodo nekateri programi, ki jih uporabljate, ustavljeni in morda ne bodo na voljo, dokler je ne izklopite."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Operacija USB ni uspela"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"V redu"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatiranje pomnilnika USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatiraj kartico SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Pripomočki za osebe s posebnimi potrebami"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ozadje"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Spreminjanje ozadja"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"PPTP"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Tunelski protokol L2TP"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN, ki temelji na ključu v vnaprejšnji skupni rabi"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN, ki temelji na potrdilu"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Tapnite za upravljanje omrežja."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Povezan z mestom <xliff:g id="SESSION">%s</xliff:g>. Tapnite za upravljanje omrežja."</string>
     <string name="upload_file" msgid="2897957172366730416">"Izberi datoteko"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Nobena datoteka ni izbrana"</string>
     <string name="reset" msgid="2448168080964209908">"Ponastavi"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Izbriši elemente."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Razveljavi brisanje."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Zaenkrat ne naredi ničesar."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"Povezava z navideznim zasebnim omrežjem <xliff:g id="PROFILENAME">%s</xliff:g> je vzpostavljena"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"Povezava z navideznim zasebnim omrežjem <xliff:g id="PROFILENAME">%s</xliff:g> prekinjena"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Dotaknite se, če želite znova vzpostaviti povezavo z navideznim zasebnim omrežjem."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Izberite račun"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Povečaj"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Zmanjšaj"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Kartica SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Pomnilnik USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Urejanje ..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Opozorilo o uporabi podatkov"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"poraba presega <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Podatki 2G-3G so onemogočeni"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Podatki 4G so onemogočeni"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobilni podatki so onemogočeni"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"tapnite, če želite omogočiti"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Varnostno potrdilo"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"To potrdilo je veljavno."</string>
+    <string name="issued_to" msgid="454239480274921032">"Izdano za:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Pravo ime:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organizacija:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Organizacijska enota:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Izdal:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Veljavnost:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Izdano:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Velja do:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 455e1a9..1604a94 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим рада у авиону"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Режим рада у авиону је УКЉУЧЕН"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Режим рада у авиону је ИСКЉУЧЕН"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android систем"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Услуге које се плаћају"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"уписивање података о контактима"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Омогућава апликацији да измени податке о контакту (адресу) сачуване на таблету. Злонамерне апликације на тај начин могу да избришу или измене податке о контакту."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Омогућава да апликација измени податке о контакту (адреси) сачуване на телефону. Злонамерне апликације могу то да злоупотребе и да избришу или измене податке о контакту."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"читање података о профилу"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Омогућава да апликација чита све личне податке о профилу. Злонамерне апликације могу то да искористе да би утврдиле ваш идентитет и послале личне информације другим људима."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"писање података о профилу"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Омогућава да апликација мења личне податке о профилу. Злонамерне апликације могу то да искористе да би избрисале или измениле податке о профилу."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"читање догађаја из календара"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Омогућава апликацији да чита све догађаје из календара сачуване на таблету. Злонамерне апликације то могу да злоупотребе и пошаљу ваше догађаје из календара другим особама."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Омогућава да апликација чита све догађаје из календара сачуване на телефону. Злонамерне апликације могу то да злоупотребе и искористе за слање догађаја из календара другим људима."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Омогућава да апликација чита систем датотека кеша и уписује податке у њега."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"упућивање/пријем Интернет позива"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Омогућава апликацији да користи SIP услугу за упућивање/пријем Интернет позива."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"чита историју коришћења мреже"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Омогућава апликацији да чита историју коришћења мреже за посебне мреже и апликације."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"управљање смерницама за мрежу"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Омогућава да апликација управља смерницама за мрежу и дефинише посебна правила за апликацију."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"измените обрачунавање коришћења мреже"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Дозвољава измену начина на који се коришћење мреже обрачунава у односу на апликације. Не користи се за обичне апликације."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Подешавање правила за лозинку"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Контрола дужине и знакова дозвољених у лозинкама за откључавање лозинки"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Надгледање покушаја откључавања екрана"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролишите колико често лозинка за закључавање екрана мора да се мења"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Подешавање шифровања складишта"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Захтева да сачувани подаци апликације буду шифровани"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Онемогућавање камера"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Спречавање коришћења свих камера уређаја"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Кућа"</item>
     <item msgid="869923650527136615">"Мобилни"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"У таблету нема SIM картице."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"У телефон није уметнута SIM картица."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Уметните SIM картицу."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Недостаје SIM картица или не може да се прочита. Уметните SIM картицу."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"SIM картица је трајно онемогућена."\n" Обратите се добављачу услуге бежичне мреже да бисте добили другу SIM картицу."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Само хитни позиви"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Мрежа је закључана"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM картица је закључана PUK кодом."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ако укључите USB складиште, поједине апликације које користите престаће да раде и могу да постану недоступне док га поново не укључите."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Грешка са USB складиштем"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Потврди"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматирање USB меморије"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Форматирање SD картице"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Приступачност"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Позадина"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промена позадине"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Протокол за тунеловање од тачке до тачке"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Протокол тунеловања слоја 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Унапред дељени кључ заснован на протоколу L2TP/IPSec за VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Сертификат заснован на протоколу L2TP/IPSec за VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Додирните да бисте управљали мрежом."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Повезано са сесијом <xliff:g id="SESSION">%s</xliff:g>. Додирните да бисте управљали мрежом."</string>
     <string name="upload_file" msgid="2897957172366730416">"Одабери датотеку"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Није изабрана ниједна датотека"</string>
     <string name="reset" msgid="2448168080964209908">"Поново постави"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Избриши ставке."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Опозови брисања."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Не ради ништа за сада."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN веза је успостављена"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN веза је прекинута"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Додирните да бисте се поново повезали са VPN-ом."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Избор налога"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Повећање"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Смањење"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD картица"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB меморија"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Измени..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Упозорење о потрошњи података"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"потрошња премашује <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-3G подаци су онемогућени"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G подаци су онемогућени"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Подаци мобилне мреже су онемогућени"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"додирните да бисте омогућили"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Безбедносни сертификат"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Овај сертификат је важећи."</string>
+    <string name="issued_to" msgid="454239480274921032">"Издато за:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Уобичајени назив:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Организација:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Организациона јединица:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Издао/ла:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Важност:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Издато:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Истиче:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 22ca7e2..d3e3848 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flygplansläge"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flygplansläge är AKTIVERAT"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flygplansläge är INAKTIVERAT"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;100"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Säkert läge"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Tjänster som kostar pengar"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"skriva kontaktuppgifter"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Tillåter att ett program ändrar kontaktuppgifter (adresser) som har lagrats på pekdatorn. Skadliga program kan använda detta för att radera eller ändra kontaktuppgifter."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Tillåter att ett program ändrar kontaktuppgifter (adress) som har lagrats på din telefon. Skadliga program kan använda detta för att radera eller ändra kontaktuppgifter."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"läsa profildata"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Tillåter att en app läser din personliga profilinformation. Skadliga program kan använda detta för att identifiera dig och skicka dina personuppgifter till andra personer."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"skriva profildata"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Tillåter att en app ändrar din personliga profilinformation. Skadliga program kan använda detta för att radera eller ändra dina profildata."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"läsa kalenderhändelser"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Tillåter att ett program läser alla händelser i kalendern som har lagrats på pekdatorn. Skadliga program kan använda detta för att skicka dina kalenderuppgifter till andra personer."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Tillåter att ett program läser alla händelser i kalendern som har lagrats på din telefon. Skadliga program kan använda detta för att skicka din kalender till andra personer."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Tillåter att ett program läser och skriver till cachefilsystemet."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"ringa/ta emot Internetsamtal"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Tillåter att appen använder SIP-tjänsten för att ringa och ta emot Internetsamtal."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"läsa historisk nätverksanvändning"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Tillåter att en app läser den historiska nätverksanvändningen för specifika nätverk och appar."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"hantera nätverkspolicy"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Tillåter att en app hanterar nätverkspolicyer och definierar programspecifika regler."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"ändra nätverksredovisningen"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Tillåter att appen ändrar hur nätverksanvändningen redovisas för appar. Används inte av vanliga appar."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ange lösenordsregler"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Bestäm hur många och vilka tecken som är tillåtna i skärmlåsets lösenord"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Övervaka försök att låsa upp skärmen"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Styr hur ofta lösenordet till skärmlåset måste ändras"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Ange krypterad lagring"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Kräv att sparade applikationsdata krypteras."</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Inaktivera kameror"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Förhindra att enhetens kameror används"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Hem"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Inget SIM-kort i pekdatorn."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Inget SIM-kort i telefonen."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Sätt i ett SIM-kort."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"SIM-kort saknas eller kan inte läsas. Sätt i ett SIM-kort."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"SIM-kortet har inaktiverats permanent."\n" Beställ ett nytt SIM-kort från din operatör."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Endast nödsamtal"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Nätverk låst"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM-kortet är PUK-låst."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Om du aktiverar USB-lagring avbryts några av de appar som körs och de kanske inte blir tillgängliga igen förrän du inaktiverar USB-lagring."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-åtgärd misslyckades"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatera USB-enhet"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatera SD-kort"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Tillgänglighet"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Bakgrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ändra bakgrund"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Point-to-Point Tunneling Protocol"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunneling Protocol"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"I förväg delad L2TP/IPSec VPN-nyckel"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Certifikatsbaserad L2TP/IPSec VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Knacka lätt för att hantera nätverket."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Ansluten till <xliff:g id="SESSION">%s</xliff:g>. Knacka lätt för att hantera nätverket."</string>
     <string name="upload_file" msgid="2897957172366730416">"Välj fil"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil har valts"</string>
     <string name="reset" msgid="2448168080964209908">"Återställ"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Ta bort objekten."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Ångra borttagningarna."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Gör ingenting just nu."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN anslutet"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN frånkopplat"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Tryck här om du vill återansluta till ett VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Välj ett konto"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Öka"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Minska"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD-kort"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB-lagring"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Redigera..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Varning angående dataanvändning"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"användning överstiger <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Data via 2G-3G har inaktiverats"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Data via 4G har inaktiverats"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobildata har inaktiverats"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"knacka lätt om du vill aktivera"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Säkerhetscertifikat"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Certifikatet är giltigt."</string>
+    <string name="issued_to" msgid="454239480274921032">"Utfärdad till:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Nätverksnamn:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Organisation:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Organisationsenhet:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Utfärdat av:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Giltighet:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Utfärdat den:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Upphör att gälla:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 27109c8..0bf9ddf 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -685,6 +685,10 @@
     <skip />
     <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
     <skip />
+    <!-- no translation found for permlab_modifyNetworkAccounting (5088217309088729650) -->
+    <skip />
+    <!-- no translation found for permdesc_modifyNetworkAccounting (8702285686629184404) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Weka kanuni za nenosiri"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Dhibiti urefu na vibambo vilivyoruhusiwa kwenye manenosiri ya kufungua skrini"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Chunguza majaribio ya kutofun gua skrini"</string>
@@ -1243,9 +1247,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ikiwa utawezesha hifadhi ya UsB, baadhi ya programu unazozitumia zitakoma na huenda zisipatikane hadi uzime hifadhi ya UsB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Uendeshi wa USB umeshindikana"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Sawa"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Fomati hifadhi ya USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Fomati kadi ya SD"</string>
@@ -1311,13 +1319,9 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Ufikiaji"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Pazia"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Badilisha pazia"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Itifaki ya Kupitisha Pointi hadi Pointi"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Itifaki ya Kupitisha Tabaka 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Ufunguo ulioshirikiwa mapema unaotegemea L2TP/IPSec VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Cheti kinachotegemea L2TP/IPSec VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
     <!-- no translation found for vpn_text (1610714069627824309) -->
     <skip />
@@ -1371,12 +1375,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Futa vipengee."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Tendua ufutaji."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Usifanye chochote kwa sasa."</string>
-    <!-- no translation found for vpn_notification_title_connected (3197819122581348515) -->
-    <skip />
-    <!-- no translation found for vpn_notification_title_disconnected (4614192702448522822) -->
-    <skip />
-    <!-- no translation found for vpn_notification_hint_disconnected (4689796928510104200) -->
-    <skip />
     <!-- no translation found for choose_account_label (4191313562041125787) -->
     <skip />
     <!-- no translation found for number_picker_increment_button (4830170763103463443) -->
@@ -1409,4 +1407,38 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <!-- no translation found for ssl_certificate (6510040486049237639) -->
+    <skip />
+    <!-- no translation found for ssl_certificate_is_valid (6825263250774569373) -->
+    <skip />
+    <!-- no translation found for issued_to (454239480274921032) -->
+    <skip />
+    <!-- no translation found for common_name (2233209299434172646) -->
+    <skip />
+    <!-- no translation found for org_name (6973561190762085236) -->
+    <skip />
+    <!-- no translation found for org_unit (7265981890422070383) -->
+    <skip />
+    <!-- no translation found for issued_by (2647584988057481566) -->
+    <skip />
+    <!-- no translation found for validity_period (8818886137545983110) -->
+    <skip />
+    <!-- no translation found for issued_on (5895017404361397232) -->
+    <skip />
+    <!-- no translation found for expires_on (3676242949915959821) -->
+    <skip />
+    <!-- no translation found for serial_number (758814067660862493) -->
+    <skip />
+    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <skip />
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
+    <skip />
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index d6a0cdd..13bbac6 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -23,9 +23,6 @@
     <!-- see comment in values/config.xml -->
     <integer name="config_longPressOnPowerBehavior">2</integer>
 
-    <!-- Show sliding tab before lockscreen -->
-    <bool name="config_enableSlidingTabFirst">false</bool>
-
     <!-- Enable lockscreen rotation -->
     <bool name="config_enableLockScreenRotation">true</bool>
 
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index b6de800..2d5b249 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"โหมดใช้งานบนเครื่องบิน"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"เปิดโหมดใช้งานบนเครื่องบิน"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"โหมดใช้งานบนเครื่องบินปิดทำงานอยู่"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"โหมดปลอดภัย"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ระบบ Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"บริการที่ต้องเสียค่าใช้จ่าย"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"เขียนข้อมูลที่อยู่ติดต่อ"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"อนุญาตให้แอปพลิเคชันแก้ไขข้อมูลรายชื่อติดต่อ (ที่อยู่) ที่จัดเก็บอยู่บนแท็บเล็ตของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ลบหรือแก้ไขข้อมูลรายชื่อติดต่อของคุณได้"</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"อนุญาตให้แอปพลิเคชันแก้ไขข้อมูลที่อยู่ติดต่อ (ที่อยู่) ที่จัดเก็บบนโทรศัพท์ของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ลบหรือแก้ไขข้อมูลที่อยู่ติดต่อของคุณได้"</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"อ่านข้อมูลโปรไฟล์"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลโปรไฟล์ส่วนบุคคลของคุณทั้งหมด ซึ่งอาจทำให้แอปพลิเคชันที่เป็นอันตรายสามารถระบุตัวคุณและส่งข้อมูลส่วนบุคคลของคุณให้กับบุคคลอื่นได้"</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"เขียนข้อมูลโปรไฟล์"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"อนุญาตให้แอปพลิเคชันแก้ไขข้อมูลโปรไฟล์ส่วนบุคคลของคุณ ซึ่งอาจทำให้แอปพลิเคชันที่เป็นอันตรายสามารถลบหรือแก้ไขข้อมูลโปรไฟล์ของคุณได้"</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"อ่านกิจกรรมบนปฏิทิน"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"อนุญาตให้แอปพลิเคชันอ่านกิจกรรมในปฏิทินทั้งหมดที่จัดเก็บอยู่บนแท็บเล็ตของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ส่งกิจกรรมในปฏิทินของคุณให้แก่ผู้อื่นได้"</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"อนุญาตให้แอปพลิเคชันอ่านกิจกรรมบนปฏิทินทั้งหมดที่จัดเก็บบนโทรศัพท์ของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ส่งกิจกรรมบนปฏิทินไปหาผู้อื่นได้"</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"อนุญาตให้แอปพลิเคชันอ่านและเขียนระบบไฟล์แคช"</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"โทรออก/รับสายอินเทอร์เน็ต"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"อนุญาตให้แอปพลิเคชันใช้บริการ SIP เพื่อโทรออก/รับสายอินเทอร์เน็ต"</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"อ่านประวัติการใช้เครือข่าย"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"อนุญาตให้แอปพลิเคชันอ่านประวัติการใช้เครือข่ายสำหรับเครือข่ายและแอปพลิเคชันเฉพาะ"</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"จัดการนโยบายเครือข่าย"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"อนุญาตให้แอปพลิเคชันจัดการนโยบายเครือข่ายและกำหนดกฎเฉพาะแอปพลิเคชัน"</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"แก้ไขการบันทึกบัญชีการใช้งานเครือข่าย"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"อนุญาตให้แก้ไขวิธีการบันทึกบัญชีการใช้งานเครือข่ายที่ไม่ตรงกับในแอปพลิเคชันได้ ทั้งนี้ไม่ใช้กับแอปพลิเคชันโดยทั่วไป"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ตั้งค่ากฎรหัสผ่าน"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"ควบคุมความยาวและอักขระที่อนุญาตให้ใช้ในรหัสผ่านการปลดล็อกหน้าจอ"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"ควบคุมความถี่ในการเปลี่ยนรหัสผ่านล็อกหน้าจอ"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"ตั้งค่าการเข้ารหัสที่เก็บข้อมูล"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"กำหนดว่าแอปพลิเคชันที่จัดเก็บต้องมีการเข้ารหัส"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"ปิดใช้งานกล้องถ่ายรูป"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"ป้องกันการใช้กล้องถ่ายรูปของอุปกรณ์ทั้งหมด"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"บ้าน"</item>
     <item msgid="869923650527136615">"มือถือ"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ไม่มีซิมการ์ดในแท็บเล็ต"</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ไม่มีซิมการ์ดในโทรศัพท์"</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"โปรดใส่ซิมการ์ด"</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"ไม่มีซิมการ์ดหรือไม่สามารถอ่านได้ โปรดใส่ซิมการ์ด"</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"ซิมการ์ดของคุณถูกปิดใช้งานอย่างถาวร"\n"โปรดติดต่อผู้ให้บริการไร้สายของคุณเพื่อรับซิมการ์ดอีกอันหนึ่ง"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"โทรฉุกเฉินเท่านั้น"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"ล็อกเครือข่ายไว้"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"ซิมการ์ดถูกล็อกด้วย PUK"</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"หากคุณเปิดที่จัดเก็บข้อมูล USB แอปพลิเคชันบางอย่างที่คุณใช้อยู่จะหยุดและอาจใช้งานไม่ได้จนกว่าคุณจะปิดที่จัดเก็บข้อมูล USB"</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"การปฏิบัติงานของ USB ล้มเหลว"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"ตกลง"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"ฟอร์แมตที่เก็บข้อมูล USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"ฟอร์แมตการ์ด SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"การเข้าถึง"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"วอลเปเปอร์"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"เปลี่ยนวอลเปเปอร์"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Point-to-Point Tunneling Protocol"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunneling Protocol"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN ตามคีย์ที่ให้ใช้ร่วมกันล่วงหน้า"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/ VPN ตามใบรับรอง"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"แตะเพื่อจัดการเครือข่าย"</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"เชื่อมต่อกับ <xliff:g id="SESSION">%s</xliff:g> แตะเพื่อจัดการเครือข่าย"</string>
     <string name="upload_file" msgid="2897957172366730416">"เลือกไฟล์"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"ไม่ได้เลือกไฟล์ไว้"</string>
     <string name="reset" msgid="2448168080964209908">"รีเซ็ต"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"ลบรายการ"</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"เลิกทำการลบ"</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"ไม่ต้องทำอะไรในขณะนี้"</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> เชื่อมต่อ VPN แล้ว"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> ตัดการเชื่อมต่อ VPN แล้ว"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"แตะเพื่อเชื่อมต่อกับ VPN อีกครั้ง"</string>
     <string name="choose_account_label" msgid="4191313562041125787">"เลือกบัญชี"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"การเพิ่ม"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"การลด"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"การ์ด SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"ที่เก็บข้อมูล USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"แก้ไข..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"คำเตือนการใช้ข้อมูล"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"การใช้งานเกิน <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"ปิดใช้งานข้อมูล 2G-3G"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"ปิดใช้งานข้อมูล 4G"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"ปิดใช้งานข้อมูลมือถือ"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"แตะเพื่อเปิดใช้งาน"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"ใบรับรองความปลอดภัย"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"ใบรับรองนี้ใช้งานได้"</string>
+    <string name="issued_to" msgid="454239480274921032">"ออกให้แก่:"</string>
+    <string name="common_name" msgid="2233209299434172646">"ชื่อทั่วไป:"</string>
+    <string name="org_name" msgid="6973561190762085236">"องค์กร:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"หน่วยองค์กร:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"ออกโดย:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"อายุการใช้งาน:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"ออกเมื่อ:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"หมดอายุวันที่:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index bba5e2f..5b3eed0 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Airplane mode"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Naka-ON ang airplane mode"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Naka-OFF ang airplane mode"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Mga serbisyong ginagastusan mo"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"sumulat ng data ng pakikipag-ugnay"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Pinapayagan ang application na baguhin ang data ng contact (address) na nakaimbak sa iyong tablet. Maaari itong gamitin ng mga nakapanghahamak na application upang burahin o baguhin ang data ng iyong contact."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Pinapayagan ang isang application na baguhin ang data ng pakikipag-ugny (address) na nakaimbak sa iyong telepono. Magagamit ito ng mga nakakahamak na application upang burahin o baguhin ang iyong data ng pakikipag-ugnay."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"basahin ang data ng profile"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Pinapayagan ang isang application upang basahin ang lahat ng iyong mga personal na impormasyon sa profile. Magagamit ito ng mga kahina-hinalang application upang makilala ka at ipadala ang iyong personal na impormasyon sa iba pang tao."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"magsulat ng data ng profile"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Pinapayagan ang isang application upang baguhin ang iyong personal na impormasyon sa profile. Magagamit ito ng mga kahina-hinalang application upang burahin o baguhin ang iyong data ng profile."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"basahin ang mga kaganapan sa kalendaryo"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Pinapayagan ang application na basahin ang lahat ng mga kaganapan sa kalendaryo na nakaimbak sa iyong tablet. Maaari itong gamitin ng mga nakapanghahamak na application upang ipadala ang iyong mga kaganapan sa kalendaryo sa mga ibang tao."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Pinapayagan ang isang application na basahin ang lahat ng mga kaganapan sa kalendaryong nakaimbak sa iyong telepono. Magagamit ito ng mga nakakahamak na application upang ipadala ang iyong mga kaganapan sa kalendaryo sa ibang tao."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Pinapayagan ang isang application na basahin at isulat ang cache filesystem."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"gumawa/tumanggap ng mga tawag sa Internet"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Pinapayagan ang application upang gamitin ang serbisyong SIP upang gumawa/tumanggap ng mga tawag sa Internet."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"basahin ang makasaysayang paggamit ng network"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Pinapayagan ang isang application na basahin ang makasaysayang paggamit network para sa mga tukoy na network at application."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"pamahalaan ang patakaran ng network"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Pinapayagan ang application upang pamahalaan ang mga patakaran ng network at alamin ang mga patakaran sa mga tukoy na application."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"baguhin ang pagkukuwenta sa paggamit ng network"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Pinapayagan ang pagbabago kung paano kinukuwenta ang paggamit ng network kumpara sa mga application. Hindi para sa paggamit ng mga karaniwang application."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Magtakda ng mga panuntunan sa password"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontrolin ang haba at mga character na pinapayagan sa mga password sa pag-unlock ng screen"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Subaybayan ang mga pagsubok sa pag-unlock ng screen"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrolin kung gaano kadalas dapat na mapalitan ang password sa pag-lock ng screen"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Itakda pag-encrypt ng imbakan"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Hinging naka-encrypt ang nakaimbak na data ng application"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Huwag paganahin mga camera"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Pigilan ang paggamit ng lahat ng camera ng device"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Home"</item>
     <item msgid="869923650527136615">"Mobile"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Walang SIM card sa tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Walang SIM card sa telepono."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Mangyaring magpasok ng SIM card."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Nawawala o hindi nababasa ang SIM card. Mangyaring magpasok ng isang SIM card."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Ang iyong SIM card ay permanenteng hindi pinagana."\n" Mangyaring makipag-ugnay sa iyong wireless service provider upang makakuha ng isa pang SIM card."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Mga pang-emergency na tawag lang"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Naka-lock ang network"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Naka-PUK-lock ang SIM card."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Kung io-on mo ang USB storage, titigil ang ilang application na ginagamit mo at maaaring maging hindi available hanggang sa i-off mo ang USB storage."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Nabigo ang pagpapatakbo ng USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"I-format USB storage"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"I-format ang SD card"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Kakayahang Ma-access"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Baguhin ang wallpaper"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Point-to-Point Tunneling Protocol"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunneling Protocol"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Unang ibinahaging key na batay sa L2TP/IPSec VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Batay sa certificate na L2TP/IPSec VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Tapikin upang pamahalaan ang network."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Nakakonekta sa <xliff:g id="SESSION">%s</xliff:g>. Tapikin upang pamahalaan ang network."</string>
     <string name="upload_file" msgid="2897957172366730416">"Pumili ng file"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Walang napiling file"</string>
     <string name="reset" msgid="2448168080964209908">"I-reset"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Tanggalin ang mga item."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"I-undo ang mga pagtanggal."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Walang gawin sa ngayon."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"Nakakonekta ang <xliff:g id="PROFILENAME">%s</xliff:g> sa VPN"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"Hindi nakakonekta ang <xliff:g id="PROFILENAME">%s</xliff:g> VPN"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Pindutin upang muling kumonekta sa VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Pumili ng account"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Taasan"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Babaan"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD Card"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB storage"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"I-edit..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Babala sa paggamit ng data"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"lumampas sa paggamit ng <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Di pinagana ang data ng 2G-3G"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Di pinagana ang data ng 4G"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Di pinagana ang data ng mobile"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"tapikin upang paganahin"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Certificate ng seguridad"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"May-bisa ang certificate na ito."</string>
+    <string name="issued_to" msgid="454239480274921032">"Ibinigay kay:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Karaniwang pangalan:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Samahan:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Yunit na pangsamahan:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Ibinigay ng/ni:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Pagkabisa:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Ibinigay noong:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Mag-e-expire sa:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 3bce91b..8aea16d 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Uçak modu"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Uçak modu AÇIK"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Uçak modu KAPALI"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android Sistemi"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Size maliyet getiren hizmetler"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"kişi verileri yaz"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Uygulamaya, tabletinizde depolanan kişi (adres) verilerini değiştirme izni verir. Kötü amaçlı uygulamalar bu işlevi kişi verilerinizi silmek veya değiştirmek için kullanabilir."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Uygulamaların telefonunuzda depolanan kişi (adres) verilerini değiştirmesine izin verir. Kötü amaçlı uygulamalar bu işlevi kişi verilerinizi silmek veya değiştirmek için kullanabilir."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"profil verilerini oku"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Uygulamaya tüm kişisel profil bilgilerinizi okuma izni verir. Kötü amaçlı uygulamalar bunu sizin kimliğinizi belirlemek ve kişisel bilgilerinizi başkalarına göndermek için kullanabilir."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"profil verilerini yaz"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Uygulamaya kişisel profil bilgilerinizi değiştirme izni verir. Kötü amaçlı uygulamalar bu işlevi profil verilerinizi silmek veya değiştirmek için kullanabilir."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"takvim etkinliklerini oku"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Uygulamaya, tabletinizde depolanan takvim etkinliklerinin tümünü okuma izni verir. Kötü amaçlı uygulamalar bunu, takvim etkinliklerinizi başkalarına göndermek için kullanabilir."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Uygulamaların telefonunuzda depolanan takvim etkinliklerinin tümünü okumasına izin verir. Kötü amaçlı uygulamalar bunu, takvim etkinliklerinizi başkalarına göndermek için kullanabilir."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Bir uygulamanın önbellek dosya sisteminde okuma yazma yapmasına izin verir."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"İnternet çağrılar yap/alma"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Uygulamanın İnternet çağ yapmak/almak için SIP hiz kullanmasına izin verir."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"geçmiş ağ kullanımını oku"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Uygulamaya, özel ağlar ve uygulamalar için geçmiş ağ kullanımını okuma izni verir."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"ağ politikasını yönet"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Uygulamaya ağ politikalarını yönetme ve uygulamaya özgü kurallar belirleme izni verir."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"ağ kullanım hesaplamasını değiştir"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Uygulamalarda ağ kullanımının nasıl hesaplanacağının değiştirilmesine izin verir. Normal uygulamaların kullanımına yönelik değildir."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Şifre kuralları ayarla"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Ekran kilidini açma şifrelerinde izin verilen uzunluğu ve karakterleri kontrol edin"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekran kilidini açma denemelerini izle"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Ekran kilitleme şifresinin hangi sıklıkla değiştirilmesi gerektiğini denetleyin"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Deplm şifrelemesini ayarla"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Depolanan uygulama verisinin şifrelenmiş olmasını gerektir"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Kameraları devre dışı bırak"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Tüm cihaz kameralarının kullanımını engelle"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Ev"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tablette SIM kart yok."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefonda SIM kart yok."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Lütfen SIM kart takın."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"SIM kart eksik veya okunamıyor. Bir SIM kart takın."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"SIM kartınız kalıcı olarak devre dışı bırakıldı."\n" Başka bir SIM kart almak için kablosuz servis sağlayıcınıza başvurun."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Yalnızca acil çağrılar için"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Ağ kilitli"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM kart PUK kilidi devrede."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USB depolama birimini açarsanız, kullanmakta olduğunuz bazı uygulamalar durur ve USB depolama birimi kapatılıncaya kadar kullanılamayabilir."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB işlemi başarısız oldu"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Tamam"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB\'yi biçimlendir"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD kartı biçimlendir"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Erişebilirlik"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Duvar Kağıdı"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Duvar kağıdını değiştir"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Noktadan Noktaya Tünel Protokolü Kuralları"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Katman 2 Tünel Protokolü"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN temelli önceden paylaşılmış anahtar"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN temelli sertifika"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Ağı yönetmek için hafifçe vurun."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> oturumuna bağlı. Ağı yönetmek için hafifçe vurun."</string>
     <string name="upload_file" msgid="2897957172366730416">"Dosya seç"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Seçili dosya yok"</string>
     <string name="reset" msgid="2448168080964209908">"Sıfırla"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Öğeleri sil."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Silme işlemlerini geri alın."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Şimdilik bir şey yapma."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN bağlandı"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN bağlantısı kesildi"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"VPN\'ye tekrar bağlanmak için dokunun."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Bir hesap seçin"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Artır"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Azalt"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD Kart"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB depolama birimi"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Düzenle..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Veri kullanım uyarısı"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"kullanım <xliff:g id="SIZE">%s</xliff:g> boyutunu aşıyor"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-3G verileri devre dışı"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G verileri devre dışı"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobil veriler devre dışı"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"etkinleştirmek içn hafifçe vurun"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Güvenlik sertifikası"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Bu sertifika geçerli."</string>
+    <string name="issued_to" msgid="454239480274921032">"Verilen:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Ortak ad:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Kuruluş:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Kuruluş birimi:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Sertifikayı veren:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Geçerlilik:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Yayınlanma tarihi:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Sona erme tarihi:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 3bb3788..5f50208 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим польоту"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Режим польоту ВВІМК."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Режим польоту ВИМК."</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безп. режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Служби, які потребують оплати"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"запис. контактні дані"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Дозволяє програмі змінювати контактні дані (адреси), збереж. в пристрої. Шкідливі програми можуть використ. це для видалення чи зміни ваших контактних даних."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Дозволяє програмі змінювати контактні дані (адресу), збереж. в телефоні. Шкідливі програми можуть використ. це для видалення чи зміни ваших контактних даних."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"читання даних профілю"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Дозволяє програмі читати всю особисту інформацію профілю. Шкідливі програми можуть використовувати це для вашої ідентифікації та надсилання особистої інформації іншим людям."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"записувати дані профілю"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Дозволяє програмі змінювати особисту інформацію профілю. Шкідливі програми можуть використовувати це для видалення чи зміни даних вашого профілю."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"читати події календаря"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Дозволяє програмі зчитувати всі події календаря, збережені в пристрої. Шкідливі програми можуть використовувати це для надсилання ваших подій календаря іншим людям."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Дозволяє програмі зчитувати всі події календаря, збережені у вашому телефоні. Шкідливі програми можуть використ-ти це для надсилання подій календаря іншим людям."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Дозволяє програмі зчитувати та записувати файлову сист. кешу."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"здійсн./отрим. Інтернет-дзвін."</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Дозволяє програмі використ. службу SIP, щоб здійсн./отрим. Інтернет-дзвінки."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"читати історію використання мережі"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Дозволяє програмі читати історію використання мережі для певних мереж і програм."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"керувати політикою мережі"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Дозволяє програмі керувати політикою мережі та визначити спеціальні правила для програм."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"змінювати облік використання мережі"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Дозволяє змінювати спосіб, у який програми використовують мережу. Не для використання звичайними програмами."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Устан. правила пароля"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Контролює довжину паролів для розблокув. екрана та дозволені в них символи"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Відстежув. спроби розблок. екрана"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролювати частоту зміни пароля блокування екрана"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Установити шифрування носія"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Потрібно, щоб дані збереженої програми були зашифровані"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Вимкнути камери"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Запобігати використанню всіх камер пристрою"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Дом."</item>
     <item msgid="869923650527136615">"Мобільний"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"У пристр. нема SIM-карти."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"У тел. немає SIM-карти."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Вставте SIM-карту."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"SIM-карта відсутня або недоступна для зчитування. Вставте SIM-карту."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Вашу SIM-карту вимкнено назавжди."\n" Зверніться до свого постачальника послуг бездротового зв’язку, щоб отримати іншу SIM-карту."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Лише аварійні виклики"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Мережу заблок."</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM-карту заблоковано PUK."</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Якщо ввімкнути носій USB, деякі програми, які викор., припинять свою роботу та можуть бути недоступними до вимкнення носія USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Помилка операції з USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматув. носій USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Формат. карти SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Доступність"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновий мал."</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Змінити фон. мал."</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Тунельний протокол PPTP"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Тунельний протокол рівня 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Спільн. ключ на осн. L2TP/IPSec VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN на осн. сертифіката"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Торкніться, щоб керувати мережею."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Під’єднано до <xliff:g id="SESSION">%s</xliff:g>. Торкніться, щоб керувати мережею."</string>
     <string name="upload_file" msgid="2897957172366730416">"Виберіть файл"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Не вибрано файл"</string>
     <string name="reset" msgid="2448168080964209908">"Віднов."</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Видалити елементи."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Скасувати видалення."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Наразі нічого не робіть."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"Профіль <xliff:g id="PROFILENAME">%s</xliff:g> підключено через VPN"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> роз\'єднано"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Торкніться для повторного з\'єднання з VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Вибрати обліковий запис"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Додати"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Відняти"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Картка SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Носій USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Редагувати..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Застереження про використ. даних"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"використання перевищує <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Дані 2G–3G вимкнено"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Дані 4G вимкнено"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Мобільне передав. даних вимкнено"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"торкніться, щоб увімкнути"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Сертифікат безпеки"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Цей сертифікат дійсний."</string>
+    <string name="issued_to" msgid="454239480274921032">"Кому видано:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Загальне ім’я:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Організація:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Організаційний підрозділ:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Ким видано:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Чинність:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Дата видачі:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Діє до:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index db408d8..38e33e3 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -130,7 +130,7 @@
     <string name="low_memory" product="default" msgid="6632412458436461203">"Bộ nhớ điện thoại đã đầy! Hãy xoá một số tệp để tạo thêm dung lượng."</string>
     <string name="me" msgid="6545696007631404292">"Tôi"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tùy chọn máy tính bảng"</string>
-    <string name="power_dialog" product="default" msgid="1319919075463988638">"Tuỳ chọn điện thoại"</string>
+    <string name="power_dialog" product="default" msgid="1319919075463988638">"Tùy chọn điện thoại"</string>
     <string name="silent_mode" msgid="7167703389802618663">"Chế độ im lặng"</string>
     <string name="turn_on_radio" msgid="3912793092339962371">"Bật không dây"</string>
     <string name="turn_off_radio" msgid="8198784949987062346">"Tắt không dây"</string>
@@ -143,7 +143,7 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Gần đây"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Không có ứng dụng nào gần đây."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Tùy chọn máy tính bảng"</string>
-    <string name="global_actions" product="default" msgid="2406416831541615258">"Tuỳ chọn điện thoại"</string>
+    <string name="global_actions" product="default" msgid="2406416831541615258">"Tùy chọn điện thoại"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Khoá màn hình"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Tắt nguồn"</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Chế độ im lặng"</string>
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Chế độ trên máy bay"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Chế độ trên máy bay BẬT"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Chế độ trên máy bay TẮT"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Chế độ an toàn"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Hệ thống Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Dịch vụ tính tiền của bạn"</string>
@@ -285,7 +285,7 @@
     <string name="permlab_getPackageSize" msgid="4799785352306641460">"đo dung lượng lưu trữ ứng dụng"</string>
     <string name="permdesc_getPackageSize" msgid="5557253039670753437">"Cho phép ứng dụng truy xuất mã, dữ liệu và kích thước bộ nhớ cache của nó"</string>
     <string name="permlab_installPackages" msgid="335800214119051089">"cài đặt trực tiếp ứng dụng"</string>
-    <string name="permdesc_installPackages" msgid="526669220850066132">"Cho phép ứng dụng cài đặt các gói Android mới hoặc đã được cập nhật. Các ứng dụng độc hại có thể sử dụng quyền này để thêm ứng dụng mới có quyền mạnh mẽ tuỳ ý."</string>
+    <string name="permdesc_installPackages" msgid="526669220850066132">"Cho phép ứng dụng cài đặt các gói Android mới hoặc đã được cập nhật. Các ứng dụng độc hại có thể sử dụng quyền này để thêm ứng dụng mới có quyền mạnh mẽ tùy ý."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"xoá tất cả dữ liệu bộ nhớ cache của ứng dụng"</string>
     <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Cho phép ứng dụng giải phóng bộ nhớ máy tính bảng bằng cách xóa các tệp trong thư mục bộ nhớ cache ứng dụng. Quyền truy cập thường rất hạn chế đối với quy trình hệ thống."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Cho phép ứng dụng tạo thêm dung lượng điện thoại bằng cách xoá các tệp trong thư mục bộ nhớ cache ứng dụng. Quyền truy cập thường rất hạn chế đối với quy trình hệ thống."</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"ghi dữ liệu liên hệ"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Cho phép ứng dụng sửa đổi dữ liệu (địa chỉ) liên hệ được lưu trữ trên máy tính bảng của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Cho phép ứng dụng sửa đổi dữ liệu liên hệ (địa chỉ) được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xoá hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"đọc dữ liệu tiểu sử"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Cho phép ứng dụng đọc tất cả các thông tin tiểu sử cá nhân của bạn. Các ứng dụng độc hại có thể lợi dụng quyền này để nhận dạng bạn và gửi thông tin cá nhân của bạn cho người khác."</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"ghi dữ liệu tiểu sử"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Cho phép ứng dụng sửa đổi thông tin tiểu sử cá nhân của bạn. Các ứng dụng độc hại có thể lợi dụng quyền này để xóa hoặc sửa đổi dữ liệu tiểu sử của bạn."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"Đọc sự kiện lịch"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Cho phép ứng dụng đọc tất cả các sự kiện lịch được lưu trữ trên máy tính bảng của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để gửi các sự kiện lịch của bạn cho những người khác."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Cho phép ứng dụng đọc tất cả các sự kiện lịch được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để gửi các sự kiện lịch của bạn cho những người khác."</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Cho phép ứng dụng đọc và ghi hệ thống tệp bộ nhớ cache."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"thực hiện/nhận cuộc gọi qua Internet"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"Cho phép ứng dụng sử dụng dịch vụ SIP để thực hiện/nhận cuộc gọi qua Internet."</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"đọc quá trình sử dụng mạng trước đây"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Cho phép ứng dụng đọc quá trình sử dụng mạng trước đây đối với các mạng và ứng dụng cụ thể."</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"quản lý chính sách mạng"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Cho phép ứng dụng quản lý các chính sách mạng và xác định các quy tắc cụ thể dành cho ứng dụng."</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"sửa đổi hạch toán sử dụng mạng"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"Cho phép sửa đổi cách sử dụng mạng được hạch toán đối với các ứng dụng. Không dành cho các ứng dụng bình thường sử dụng."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Đặt quy tắc mật khẩu"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kiểm soát độ dài và ký tự được phép trong mật khẩu mở khóa màn hình"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Giám sát những lần thử mở khóa màn hình"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"Kiểm soát tần suất bắt buộc phải thay đổi mật khẩu khóa màn hình"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Đặt mã hóa dung lượng lưu trữ"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Yêu cầu dữ liệu ứng dụng được lưu trữ phải được mã hóa"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Vô hiệu hóa máy ảnh"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"Ngăn việc sử dụng tất cả các máy ảnh của điện thoại"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Nhà riêng"</item>
     <item msgid="869923650527136615">"ĐT di động"</item>
@@ -529,30 +521,30 @@
     <item msgid="1735177144948329370">"Số fax Nhà riêng"</item>
     <item msgid="603878674477207394">"Số máy nhắn tin"</item>
     <item msgid="1650824275177931637">"Khác"</item>
-    <item msgid="9192514806975898961">"Tuỳ chỉnh"</item>
+    <item msgid="9192514806975898961">"Tùy chỉnh"</item>
   </string-array>
   <string-array name="emailAddressTypes">
     <item msgid="8073994352956129127">"Nhà riêng"</item>
     <item msgid="7084237356602625604">"Cơ quan"</item>
     <item msgid="1112044410659011023">"Khác"</item>
-    <item msgid="2374913952870110618">"Tuỳ chỉnh"</item>
+    <item msgid="2374913952870110618">"Tùy chỉnh"</item>
   </string-array>
   <string-array name="postalAddressTypes">
     <item msgid="6880257626740047286">"Nhà riêng"</item>
     <item msgid="5629153956045109251">"Cơ quan"</item>
     <item msgid="4966604264500343469">"Khác"</item>
-    <item msgid="4932682847595299369">"Tuỳ chỉnh"</item>
+    <item msgid="4932682847595299369">"Tùy chỉnh"</item>
   </string-array>
   <string-array name="imAddressTypes">
     <item msgid="1738585194601476694">"Nhà riêng"</item>
     <item msgid="1359644565647383708">"Cơ quan"</item>
     <item msgid="7868549401053615677">"Khác"</item>
-    <item msgid="3145118944639869809">"Tuỳ chỉnh"</item>
+    <item msgid="3145118944639869809">"Tùy chỉnh"</item>
   </string-array>
   <string-array name="organizationTypes">
     <item msgid="7546335612189115615">"Cơ quan"</item>
     <item msgid="4378074129049520373">"Khác"</item>
-    <item msgid="3455047468583965104">"Tuỳ chỉnh"</item>
+    <item msgid="3455047468583965104">"Tùy chỉnh"</item>
   </string-array>
   <string-array name="imProtocols">
     <item msgid="8595261363518459565">"AIM"</item>
@@ -564,7 +556,7 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
-    <string name="phoneTypeCustom" msgid="1644738059053355820">"Tuỳ chỉnh"</string>
+    <string name="phoneTypeCustom" msgid="1644738059053355820">"Tùy chỉnh"</string>
     <string name="phoneTypeHome" msgid="2570923463033985887">"Nhà riêng"</string>
     <string name="phoneTypeMobile" msgid="6501463557754751037">"ĐT di động"</string>
     <string name="phoneTypeWork" msgid="8863939667059911633">"Cơ quan"</string>
@@ -589,20 +581,20 @@
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Ngày sinh"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Ngày kỷ niệm"</string>
     <string name="eventTypeOther" msgid="7388178939010143077">"Khác"</string>
-    <string name="emailTypeCustom" msgid="8525960257804213846">"Tuỳ chỉnh"</string>
+    <string name="emailTypeCustom" msgid="8525960257804213846">"Tùy chỉnh"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Nhà riêng"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Cơ quan"</string>
     <string name="emailTypeOther" msgid="2923008695272639549">"Khác"</string>
     <string name="emailTypeMobile" msgid="119919005321166205">"ĐT di động"</string>
-    <string name="postalTypeCustom" msgid="8903206903060479902">"Tuỳ chỉnh"</string>
+    <string name="postalTypeCustom" msgid="8903206903060479902">"Tùy chỉnh"</string>
     <string name="postalTypeHome" msgid="8165756977184483097">"Nhà riêng"</string>
     <string name="postalTypeWork" msgid="5268172772387694495">"Cơ quan"</string>
     <string name="postalTypeOther" msgid="2726111966623584341">"Khác"</string>
-    <string name="imTypeCustom" msgid="2074028755527826046">"Tuỳ chỉnh"</string>
+    <string name="imTypeCustom" msgid="2074028755527826046">"Tùy chỉnh"</string>
     <string name="imTypeHome" msgid="6241181032954263892">"Nhà riêng"</string>
     <string name="imTypeWork" msgid="1371489290242433090">"Cơ quan"</string>
     <string name="imTypeOther" msgid="5377007495735915478">"Khác"</string>
-    <string name="imProtocolCustom" msgid="6919453836618749992">"Tuỳ chỉnh"</string>
+    <string name="imProtocolCustom" msgid="6919453836618749992">"Tùy chỉnh"</string>
     <string name="imProtocolAim" msgid="7050360612368383417">"AIM"</string>
     <string name="imProtocolMsn" msgid="144556545420769442">"Windows Live"</string>
     <string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo"</string>
@@ -614,7 +606,7 @@
     <string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string>
     <string name="orgTypeWork" msgid="29268870505363872">"Cơ quan"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Khác"</string>
-    <string name="orgTypeCustom" msgid="225523415372088322">"Tuỳ chỉnh"</string>
+    <string name="orgTypeCustom" msgid="225523415372088322">"Tùy chỉnh"</string>
     <string name="relationTypeCustom" msgid="3542403679827297300">"Tùy chỉnh"</string>
     <string name="relationTypeAssistant" msgid="6274334825195379076">"Trợ lý"</string>
     <string name="relationTypeBrother" msgid="8757913506784067713">"Anh em trai"</string>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Không có thẻ SIM nào trong máy tính bảng."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Không có thẻ SIM nào trong điện thoại."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Vui lòng lắp thẻ SIM."</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Thẻ SIM bị thiếu hoặc không thể đọc được. Vui lòng lắp thẻ SIM."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Thẻ SIM của bạn đã bị vô hiệu hóa vĩnh viễn."\n" Hãy liên hệ với nhà cung cấp dịch vụ không dây của bạn để lấy thẻ SIM khác."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Chỉ cuộc gọi khẩn cấp"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Mạng đã khoá"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Thẻ SIM đã bị khoá PUK."</string>
@@ -702,7 +692,7 @@
     <string name="factorytest_reboot" msgid="6320168203050791643">"Khởi động lại"</string>
     <string name="js_dialog_title" msgid="8143918455087008109">"Trang tại \'<xliff:g id="TITLE">%s</xliff:g>\' cho biết:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
-    <string name="js_dialog_before_unload" msgid="1901675448179653089">"Điều hướng khỏi trang này?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Chọn OK để tiếp tục hoặc Huỷ để ở lại trang hiện tại."</string>
+    <string name="js_dialog_before_unload" msgid="1901675448179653089">"Điều hướng khỏi trang này?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Chọn OK để tiếp tục hoặc Hủy để ở lại trang hiện tại."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Xác nhận"</string>
     <string name="double_tap_toast" msgid="1068216937244567247">"Mẹo: nhấn đúp để phóng to và thu nhỏ."</string>
     <string name="autofill_this_form" msgid="1272247532604569872">"Tự động điền"</string>
@@ -843,9 +833,9 @@
     <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Dung lượng lưu trữ của máy tính bảng thấp."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Dung lượng lưu trữ của điện thoại thấp."</string>
     <string name="ok" msgid="5970060430562524910">"OK"</string>
-    <string name="cancel" msgid="6442560571259935130">"Huỷ"</string>
+    <string name="cancel" msgid="6442560571259935130">"Hủy"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
-    <string name="no" msgid="5141531044935541497">"Huỷ"</string>
+    <string name="no" msgid="5141531044935541497">"Hủy"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Chú ý"</string>
     <string name="loading" msgid="1760724998928255250">"Đang tải..."</string>
     <string name="capital_on" msgid="1544682755514494298">"BẬT"</string>
@@ -912,9 +902,9 @@
     <string name="select_character" msgid="3365550120617701745">"Chèn ký tự"</string>
     <string name="sms_control_default_app_name" msgid="7630529934366549163">"Ứng dụng không xác định"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"Đang gửi tin nhắn SMS"</string>
-    <string name="sms_control_message" msgid="1289331457999236205">"Một số lượng lớn các tin nhắn SMS đang được gửi. Chọn \"OK\" để tiếp tục hoặc \"Huỷ\" để dừng gửi."</string>
+    <string name="sms_control_message" msgid="1289331457999236205">"Một số lượng lớn các tin nhắn SMS đang được gửi. Chọn \"OK\" để tiếp tục hoặc \"Hủy\" để dừng gửi."</string>
     <string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
-    <string name="sms_control_no" msgid="1715320703137199869">"Huỷ"</string>
+    <string name="sms_control_no" msgid="1715320703137199869">"Hủy"</string>
     <!-- no translation found for sim_removed_title (6227712319223226185) -->
     <skip />
     <!-- no translation found for sim_removed_message (2064255102770489459) -->
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Nếu bạn bật bộ lưu trữ USB, một số ứng dụng bạn đang sử dụng sẽ dừng và có thể không khả dụng cho tới khi bạn tắt bộ lưu trữ USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Thao tác USB không thành công"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Định dạng b.nhớ USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Định dạng thẻ SD"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Khả năng truy cập"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Hình nền"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Thay đổi hình nền"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Giao thức Đường hầm Điểm nối Điểm"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Giao thức Đường hầm Tầng 2"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN dựa trên khoá chia sẻ trước"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN dựa trên chứng chỉ"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"Chạm để quản lý mạng."</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"Đã kết nối với <xliff:g id="SESSION">%s</xliff:g>. Chạm để quản lý mạng."</string>
     <string name="upload_file" msgid="2897957172366730416">"Chọn tệp"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Không có tệp nào được chọn"</string>
     <string name="reset" msgid="2448168080964209908">"Đặt lại"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Xóa mục."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Hoàn tác các tác vụ xóa."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Ngay bây giờ bạn không cần làm gì cả."</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"Đã kết nối VPN <xliff:g id="PROFILENAME">%s</xliff:g>"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"Đã ngắt kết nối VPN <xliff:g id="PROFILENAME">%s</xliff:g>"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Chạm để kết nối lại với VPN."</string>
     <string name="choose_account_label" msgid="4191313562041125787">"Chọn tài khoản"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"Tăng dần"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"Giảm dần"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"Thẻ SD"</string>
     <string name="storage_usb" msgid="3017954059538517278">"Bộ lưu trữ USB"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"Chỉnh sửa..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"Cảnh báo sử dụng dữ liệu"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"sử dụng vượt quá <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Đã tắt dữ liệu 2G-3G"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G dữ liệu bị vô hiệu hóa"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Dữ liệu di động bị vô hiệu hóa"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"chạm để bật"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"Chứng chỉ bảo mật"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Chứng chỉ này hợp lệ."</string>
+    <string name="issued_to" msgid="454239480274921032">"Cấp cho:"</string>
+    <string name="common_name" msgid="2233209299434172646">"Tên chung:"</string>
+    <string name="org_name" msgid="6973561190762085236">"Tổ chức:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"Đơn vị tổ chức:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"Cấp bởi:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"Tính hợp lệ:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"Cấp vào:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"Hết hạn vào:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-w480dp/bools.xml b/core/res/res/values-w480dp/bools.xml
index 8206e79..57a2939 100644
--- a/core/res/res/values-w480dp/bools.xml
+++ b/core/res/res/values-w480dp/bools.xml
@@ -17,7 +17,6 @@
 */
 -->
 <resources>
-    <bool name="allow_action_menu_item_text_with_icon">true</bool>
     <bool name="action_bar_embed_tabs">true</bool>
     <bool name="split_action_bar_is_narrow">false</bool>
 </resources>
diff --git a/core/res/res/values-w480dp/config.xml b/core/res/res/values-w480dp/config.xml
new file mode 100644
index 0000000..269a9b4
--- /dev/null
+++ b/core/res/res/values-w480dp/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <bool name="config_allowActionMenuItemTextWithIcon">true</bool>
+</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 18b2c06..863e3fa 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"飞行模式"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"已开启飞行模式"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"已关闭飞行模式"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"需要您付费的服务"</string>
@@ -319,14 +319,10 @@
     <string name="permlab_writeContacts" msgid="644616215860933284">"写入联系数据"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"允许应用程序修改您平板电脑上存储的联系人(地址)数据。恶意应用程序可借此清除或修改您的联系人数据。"</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"允许应用程序修改您手机上存储的联系人(地址)数据。恶意应用程序可借此清除或修改您的联系人数据。"</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permlab_readProfile" msgid="2211941946684590103">"读取个人资料数据"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"允许应用程序读取您的所有个人资料信息。恶意应用程序可能会利用此权限识别您的身份,并向他人发送您的个人信息。"</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"写入个人资料数据"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"允许应用程序修改您的个人资料信息。恶意应用程序可能会利用此权限清除或修改您的个人资料数据。"</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"读取日历活动"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"允许应用程序读取您平板电脑上存储的所有日历活动。恶意应用程序可借此将您的日历活动发送给其他人。"</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"允许应用程序读取您手机上存储的所有日历活动。恶意应用程序可借此将您的日历活动发送给其他人。"</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"允许应用程序读取和写入缓存文件系统。"</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"拨打/接听互联网通话"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"允许应用程序使用 SIP 服务拨打/接听互联网通话。"</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"读取网络使用情况历史记录"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"允许应用程序读取特定网络和应用程序的网络使用情况历史记录。"</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"管理网络政策"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"允许应用程序管理网络政策和定义专门针对应用程序的规则。"</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"修改网络使用情况记录方式"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"允许针对应用程序修改网络使用情况的记录方式。不适用于普通应用程序。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"控制屏幕解锁密码允许的长度和字符数"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"监视屏幕解锁尝试次数"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"控制锁定屏幕密码的更改频率"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"设置存储设备加密"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"需要对存储的应用程序数据进行加密"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"停用相机"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"禁止使用所有设备相机"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"住宅"</item>
     <item msgid="869923650527136615">"手机"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"平板电脑中没有 SIM 卡。"</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"手机中无 SIM 卡"</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"请插入 SIM 卡"</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"SIM 卡丢失或无法读取。请插入 SIM 卡。"</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"您的 SIM 卡已永久停用。"\n"请与您的无线服务提供商联系,以便重新获取一张 SIM 卡。"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"只能使用紧急呼叫"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"网络已锁定"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM 卡已用 PUK 码锁定"</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"如果您打开了 USB 存储设备,则您当前使用的某些应用程序会停止,而且在您关闭 USB 存储设备前可能都无法使用。"</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB 操作失败"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"确定"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"格式化 USB 存储设备"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"格式化 SD 卡"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"辅助功能"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁纸"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"更改壁纸"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"点对点隧道协议"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"第 2 层隧道协议"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"基于预共享密钥的 L2TP/IPSec VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"基于证书的 L2TP/IPSec VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"点按即可管理网络。"</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"已连接到<xliff:g id="SESSION">%s</xliff:g>。点按即可管理网络。"</string>
     <string name="upload_file" msgid="2897957172366730416">"选择文件"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"未选定任何文件"</string>
     <string name="reset" msgid="2448168080964209908">"重置"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"删除这些项。"</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"撤消删除。"</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"目前不进行任何操作。"</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"VPN“<xliff:g id="PROFILENAME">%s</xliff:g>”已连接"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"VPN“<xliff:g id="PROFILENAME">%s</xliff:g>”已断开连接"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"触摸可重新连接到 VPN。"</string>
     <string name="choose_account_label" msgid="4191313562041125787">"选择帐户"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"增加"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"减少"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD 卡"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB 存储器"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"编辑..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"数据使用情况警告"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"使用量超过 <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-3G 数据已停用"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G 数据已停用"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"移动数据已停用"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"点按即可启用"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"安全证书"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"该证书有效。"</string>
+    <string name="issued_to" msgid="454239480274921032">"颁发给:"</string>
+    <string name="common_name" msgid="2233209299434172646">"常用名称:"</string>
+    <string name="org_name" msgid="6973561190762085236">"组织:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"组织单位:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"颁发者:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"有效期:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"颁发时间:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"有效期至:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 6bbf019..a9a6e4e 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -152,7 +152,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"飛航模式"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"飛航模式為 [開啟]"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"飛航模式為 [關閉]"</string>
-    <!-- outdated translation 5833510281787786290 -->     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"超過 999"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"需要額外費用的服務。"</string>
@@ -309,27 +309,23 @@
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"允許應用程式修改 Google 服務地圖。一般應用程式不會使用此功能。"</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"開機時自動啟用"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"允許應用程式在系統完成開機程序時立即自行啟動。這會增加平板電腦的開機時間,而且會因為系統一直執行該應用程式而拖慢平板電腦的整體運作速度。"</string>
-    <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"允許應用程式在開機後盡快啟動。此項設定會讓開機時間拉長,並允許應用程式持續執行,因此拖慢手機速度。"</string>
+    <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"允許應用程式在系統開機後,立即自行啟動。這會拉長手機的開機時間,而且會因為該應用程式持續執行而拖慢手機的整體運作速度。"</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"傳送附屬廣播"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"允許應用程式傳送一種在廣播動作結束後仍繼續存在的記憶廣播。惡意應用程式可藉此讓平板電腦使用過多的記憶體,使其執行速度變慢或不穩定。"</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"允許應用程式傳送持久的廣播。請注意:惡意程式可能利用此功能來佔據過多記憶體,讓手機速度變慢或不穩定。"</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"讀取聯絡人資料"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"允許應用程式讀取平板電腦上儲存的所有聯絡人 (地址) 資料。惡意應用程式可藉此將您的資料傳送給其他人。"</string>
-    <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"允許應用程式讀取手機上所有聯絡人 (地址)。請注意:惡意程式可能利用此功能將您的資料傳送給其他人。"</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"允許應用程式讀取平板電腦上儲存的所有聯絡人 (地址) 資料。請注意,惡意應用程式可能利用這項功能將您的資料傳送給他人。"</string>
+    <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"允許應用程式讀取手機上所有聯絡人 (地址)。請注意,惡意應用程式可能利用這項功能將您的資料傳送給他人。"</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"輸入聯絡人資料"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"允許應用程式修改平板電腦上儲存的聯絡人 (地址) 資料。惡意應用程式可藉此清除或修改您的聯絡人資料。"</string>
-    <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"允許應用程式更改聯絡資訊 (地址)。請注意:惡意程式可能利用此功能,清除或修改聯絡資料。"</string>
-    <!-- no translation found for permlab_readProfile (2211941946684590103) -->
-    <skip />
-    <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
-    <skip />
-    <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
-    <skip />
-    <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
-    <skip />
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"允許應用程式修改平板電腦上儲存的聯絡人 (地址) 資料。請注意,惡意應用程式可能會利用這項功能清除或修改您的聯絡人資料。"</string>
+    <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"允許應用程式修改手機上儲存的聯絡人 (地址) 資料。請注意,惡意應用程式可能會利用這項功能清除或修改您的聯絡人資料。"</string>
+    <string name="permlab_readProfile" msgid="2211941946684590103">"讀取個人資料"</string>
+    <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"允許應用程式讀取您的所有個人資訊。惡意應用程式可能會藉此識別您的身分,並將您的個人資訊傳送給其他人。"</string>
+    <string name="permlab_writeProfile" msgid="6561668046361989220">"寫入個人資料"</string>
+    <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"允許應用程式修改您的個人資訊。惡意應用程式可能會藉此清除或修改您的個人資料。"</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"讀取日曆活動"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"允許應用程式讀取平板電腦上儲存的所有日曆活動。惡意應用程式可藉此將您的日曆活動傳送給其他人。"</string>
-    <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"允許應用程式讀取手機上所有日曆資料。請注意:惡意程式可能利用此功能將您的日曆資料傳送給其他人。"</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"允許應用程式讀取平板電腦上儲存的所有日曆活動。請注意,惡意應用程式可能會利用這項功能將您的日曆活動傳送給他人。"</string>
+    <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"允許應用程式讀取手機上所有日曆資料。請注意,惡意應用程式可能會利用這項功能將您的日曆活動傳送給他人。"</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"新增或修改日曆活動,並傳送電子郵件給他人"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"允許應用程式在您的日曆上新增或變更活動,此時,應用程式可能會傳送電子郵件給他人。不過,若允許的是惡意應用程式,日曆活動可能會因此遭到刪除或竄改,惡意應用程式也可能傳送電子郵件騷擾他人。"</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"模擬位置來源以供測試"</string>
@@ -339,11 +335,11 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"准許安裝位置提供者"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"建立虛構的位置來源以供測試。請注意:惡意應用程式可能利用此選項覆寫由真實位置來源 (例如 GPS 或網路供應商) 所傳回的位置及/或狀態,或者監控您的位置並將之提供給外部來源。"</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"精確定位 (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"在可能的情況下,存取精確的位置來源資訊 (例如:平板電腦的 GPS)。惡意應用程式可藉此得知您的位置,並可能消耗更多的電池電量。"</string>
-    <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"接收精確的位置來源 (例如:手機 GPS)。請注意:惡意程式可能使用此功能得知您的位置,並可能消耗額外電源。"</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"在可能的情況下,接收精確的位置來源資訊 (例如:平板電腦的 GPS)。請注意,惡意應用程式可能會利用這項功能得知您的位置,並消耗更多電量。"</string>
+    <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"在可能的情況下,接收精確的位置來源資訊 (例如:手機 GPS)。請注意,惡意應用程式可能會利用這項功能得知您的位置,並消耗更多電量。"</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"約略位置 (以網路為基準)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"在可能的情況下,存取約略的位置來源資訊 (例如:行動網路資料庫),以計算出平板電腦的大概位置。惡意應用程式可藉此得知您的約略位置。"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"接收約略的位置來源 (例如:行動網路資料庫),計算出目前大概位置。請注意:惡意程式可能使用此功能得知您的所在地。"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"在可能的情況下,存取約略的位置來源資訊 (例如:行動網路資料庫),以計算出平板電腦的大概位置。請注意,惡意應用程式可能會利用這項功能得知您的約略位置。"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"在可能的情況下,存取約略的位置來源資訊 (例如:行動網路資料庫),以計算手機的大概位置。請注意,惡意應用程式可能會利用這項功能得知您的約略位置。"</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"存取 SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"允許應用程式使用 SurfaceFlinger 低階功能。"</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"讀取框架緩衝"</string>
@@ -356,8 +352,8 @@
     <string name="permdesc_camera" msgid="6004878235852154239">"允許應用程式使用相機拍照和錄影,此功能可讓應用程式隨時透過相機收集圖片。"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"永久停用平板電腦"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"永久停用電話"</string>
-    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"允許應用程式永久停用平板電腦所有功能 (這類權限具有高度風險)。"</string>
-    <string name="permdesc_brick" product="default" msgid="5569526552607599221">"允許應用程式永久停用手機。此項操作非常危險。"</string>
+    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"允許應用程式永久停用平板電腦所有功能 (這種權限具有高度風險)。"</string>
+    <string name="permdesc_brick" product="default" msgid="5569526552607599221">"允許應用程式永久停用手機所有功能 (這種權限具有高度風險)。"</string>
     <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"強制重新啟動平板電腦"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"強制重開機"</string>
     <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"允許應用程式強制重新啟動平板電腦。"</string>
@@ -491,14 +487,12 @@
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"允許應用程式讀取及寫入快取檔案系統。"</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"撥打/接聽網路電話"</string>
     <string name="permdesc_use_sip" msgid="6320376185606661843">"允許應用程式使用 SIP 服務撥打/接聽網路電話。"</string>
-    <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
-    <skip />
-    <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
-    <skip />
-    <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
-    <skip />
-    <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
-    <skip />
+    <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"讀取網路用量記錄"</string>
+    <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"允許應用程式讀取特定網路和應用程式的網路使用量記錄。"</string>
+    <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"管理網路政策"</string>
+    <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"允許應用程式管理網路政策並定義應用程式專用規則。"</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"修改網路使用量計算方式"</string>
+    <string name="permdesc_modifyNetworkAccounting" msgid="8702285686629184404">"允許修改應用程式的網路使用量計算方式 (不建議一般應用程式使用)。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"控制螢幕解鎖密碼所允許的長度和字元"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"監視螢幕解鎖嘗試次數"</string>
@@ -517,10 +511,8 @@
     <string name="policydesc_expirePassword" msgid="4844430354224822074">"控制螢幕上鎖密碼的變更頻率"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"設定儲存裝置加密"</string>
     <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"必須為儲存的應用程式資料加密"</string>
-    <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
-    <skip />
-    <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
-    <skip />
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"停用相機"</string>
+    <string name="policydesc_disableCamera" msgid="5680054212889413366">"禁止使用所有裝置相機"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"住家電話"</item>
     <item msgid="869923650527136615">"行動電話"</item>
@@ -662,10 +654,8 @@
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"平板電腦中沒有 SIM 卡。"</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"手機未插入 SIM 卡。"</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"請插入 SIM 卡。"</string>
-    <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
-    <skip />
-    <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
-    <skip />
+    <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"找不到 SIM 卡或無法讀取 SIM 卡,請插入 SIM 卡。"</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"您的 SIM 卡已永久停用。"\n"請與您的無線服務供應商聯絡,以取得其他 SIM 卡。"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"僅可撥打緊急電話"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"網路已鎖定"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM 的 PUK 已鎖定。"</string>
@@ -954,9 +944,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"如果您開啟 USB 儲存裝置,則您正在使用的某些應用程式會停止運作,而且可能無法使用,待您將 USB 儲存裝置關閉才會恢復正常。"</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB 操作失敗"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"確定"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"格式化 USB 儲存空間"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"將 SD 卡格式化"</string>
@@ -1021,18 +1015,12 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"協助工具"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"桌布"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"變更桌布"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"點對點通道通訊協定"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"第二層通道通訊協定"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"採用預先共用金鑰的 L2TP/IPSec VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"採用憑證的 L2TP/IPSec VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
-    <!-- no translation found for vpn_text (1610714069627824309) -->
-    <skip />
-    <!-- no translation found for vpn_text_long (4907843483284977618) -->
-    <skip />
+    <string name="vpn_text" msgid="1610714069627824309">"輕按一下即可管理網路。"</string>
+    <string name="vpn_text_long" msgid="4907843483284977618">"已連線至 <xliff:g id="SESSION">%s</xliff:g>,輕按一下即可管理網路。"</string>
     <string name="upload_file" msgid="2897957172366730416">"選擇檔案"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"未選擇任何檔案"</string>
     <string name="reset" msgid="2448168080964209908">"重設"</string>
@@ -1081,9 +1069,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"刪除這些項目。"</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"復原刪除。"</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"暫不執行。"</string>
-    <string name="vpn_notification_title_connected" msgid="3197819122581348515">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN 已連線"</string>
-    <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"<xliff:g id="PROFILENAME">%s</xliff:g> VPN 已中斷連線"</string>
-    <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"輕觸即可重新連線至 VPN。"</string>
     <string name="choose_account_label" msgid="4191313562041125787">"選取帳戶"</string>
     <string name="number_picker_increment_button" msgid="4830170763103463443">"增加"</string>
     <string name="number_picker_decrement_button" msgid="2576606679160067262">"減少"</string>
@@ -1094,16 +1079,34 @@
     <string name="storage_sd_card" msgid="8921771478629812343">"SD 卡"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB 儲存裝置"</string>
     <string name="extract_edit_menu_button" msgid="302060189057163906">"編輯..."</string>
-    <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+    <string name="data_usage_warning_title" msgid="1955638862122232342">"資料用量警告"</string>
+    <string name="data_usage_warning_body" msgid="3354394590936526648">"用量超過 <xliff:g id="SIZE">%s</xliff:g>"</string>
+    <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"已停用 2G-3G 數據"</string>
+    <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"已停用 4G 數據"</string>
+    <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"已停用行動數據"</string>
+    <string name="data_usage_limit_body" msgid="2182247539226163759">"輕按一下即可啟用"</string>
+    <string name="ssl_certificate" msgid="6510040486049237639">"安全性憑證"</string>
+    <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"憑證有效。"</string>
+    <string name="issued_to" msgid="454239480274921032">"發佈至:"</string>
+    <string name="common_name" msgid="2233209299434172646">"常用名稱:"</string>
+    <string name="org_name" msgid="6973561190762085236">"機構:"</string>
+    <string name="org_unit" msgid="7265981890422070383">"機構單位:"</string>
+    <string name="issued_by" msgid="2647584988057481566">"發佈者:"</string>
+    <string name="validity_period" msgid="8818886137545983110">"有效期間:"</string>
+    <string name="issued_on" msgid="5895017404361397232">"發佈日期:"</string>
+    <string name="expires_on" msgid="3676242949915959821">"到期日:"</string>
+    <!-- no translation found for serial_number (758814067660862493) -->
     <skip />
-    <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+    <!-- no translation found for fingerprints (4516019619850763049) -->
     <skip />
-    <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
     <skip />
-    <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
     <skip />
-    <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
     <skip />
-    <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 2a87737..e712d7b 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -685,6 +685,10 @@
     <skip />
     <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
     <skip />
+    <!-- no translation found for permlab_modifyNetworkAccounting (5088217309088729650) -->
+    <skip />
+    <!-- no translation found for permdesc_modifyNetworkAccounting (8702285686629184404) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Misa imithetho yephasiwedi"</string>
     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Lawula ubude nezinhlamvu ezivunyelwe kumaphasiwedi okuvula isikrini"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Gaka imizamo yokuvula isikrini"</string>
@@ -1243,9 +1247,13 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Uma uvula ukugcina nge-USB, ezinye izinhlelo zokusebenza ozisebenzisayo zizoma futhi zingase zingatholakali kuze kube yilapho uvala ukugcina nge-USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Umsebenzi we-USB wehlulekile"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"KULUNGILE"</string>
-    <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+    <!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
     <skip />
-    <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+    <!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
+    <skip />
+    <!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
+    <skip />
+    <!-- no translation found for usb_notification_message (4447869605109736382) -->
     <skip />
     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Fometha ukugcina nge-USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Fometha ikhadi le=SD"</string>
@@ -1311,13 +1319,9 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Ukufinyeleleka"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Iphepha donga"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Shintsha iphephadonga"</string>
-    <string name="pptp_vpn_description" msgid="2688045385181439401">"Umthetho Olandelwayo Wokwenza Umbhoshongo Wephoyinti Ngalinye"</string>
-    <string name="l2tp_vpn_description" msgid="3750692169378923304">"Ingqimbi 2 Yomthetho Olandelwayo Wokwenza Umbhoshongo"</string>
-    <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Ukwabelana kwangaphambili kokhiye osekelwe ku-L2TP/IPSec VPN"</string>
-    <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Isitifiketi sisekelwe L2TP/IPSec VPN"</string>
-    <!-- no translation found for vpn_ticker (285642105845608311) -->
+    <!-- no translation found for vpn_title (8219003246858087489) -->
     <skip />
-    <!-- no translation found for vpn_title (5434034606697234123) -->
+    <!-- no translation found for vpn_title_long (6400714798049252294) -->
     <skip />
     <!-- no translation found for vpn_text (1610714069627824309) -->
     <skip />
@@ -1371,12 +1375,6 @@
     <string name="sync_really_delete" msgid="8933566316059338692">"Susa izintwana."</string>
     <string name="sync_undo_deletes" msgid="8610996708225006328">"Guqula okususiwe."</string>
     <string name="sync_do_nothing" msgid="8717589462945226869">"Ungenzi lutho okwamanje."</string>
-    <!-- no translation found for vpn_notification_title_connected (3197819122581348515) -->
-    <skip />
-    <!-- no translation found for vpn_notification_title_disconnected (4614192702448522822) -->
-    <skip />
-    <!-- no translation found for vpn_notification_hint_disconnected (4689796928510104200) -->
-    <skip />
     <!-- no translation found for choose_account_label (4191313562041125787) -->
     <skip />
     <!-- no translation found for number_picker_increment_button (4830170763103463443) -->
@@ -1409,4 +1407,38 @@
     <skip />
     <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
     <skip />
+    <!-- no translation found for ssl_certificate (6510040486049237639) -->
+    <skip />
+    <!-- no translation found for ssl_certificate_is_valid (6825263250774569373) -->
+    <skip />
+    <!-- no translation found for issued_to (454239480274921032) -->
+    <skip />
+    <!-- no translation found for common_name (2233209299434172646) -->
+    <skip />
+    <!-- no translation found for org_name (6973561190762085236) -->
+    <skip />
+    <!-- no translation found for org_unit (7265981890422070383) -->
+    <skip />
+    <!-- no translation found for issued_by (2647584988057481566) -->
+    <skip />
+    <!-- no translation found for validity_period (8818886137545983110) -->
+    <skip />
+    <!-- no translation found for issued_on (5895017404361397232) -->
+    <skip />
+    <!-- no translation found for expires_on (3676242949915959821) -->
+    <skip />
+    <!-- no translation found for serial_number (758814067660862493) -->
+    <skip />
+    <!-- no translation found for fingerprints (4516019619850763049) -->
+    <skip />
+    <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
+    <skip />
+    <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_see_all (180268188117163072) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_no_activities (1306964627596326933) -->
+    <skip />
+    <!-- no translation found for activity_chooser_view_select_default (5450262016073956587) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 58d25d6..9c2133f 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -40,6 +40,21 @@
              to use accelerated drawing (thus setting state_accelerated), the
              cache hint is ignored and always assumed to be transparent. -->
         <attr name="colorBackgroundCacheHint" format="color" />
+
+        <!-- Default highlight color for items that are pressed. -->
+        <attr name="colorPressedHighlight" format="color" />
+        <!-- Default highlight color for items that are long-pressed. -->
+        <attr name="colorLongPressedHighlight" format="color" />
+        <!-- Default highlight color for items that are
+             focused. (Focused meaning cursor-based selection.) -->
+        <attr name="colorFocusedHighlight" format="color" />
+        <!-- Default highlight color for items that are
+             activated. (Activated meaning persistent selection.) -->
+        <attr name="colorActivatedHighlight" format="color" />
+        <!-- Default highlight color for items in multiple selection
+             mode. -->
+        <attr name="colorMultiSelectHighlight" format="color" />
+
         <!-- Default disabled alpha for widgets that set enabled/disabled alpha programmatically. -->
         <attr name="disabledAlpha" format="float" />
         <!-- Default background dim amount when a menu, dialog, or something similar pops up. -->
@@ -596,6 +611,11 @@
         <attr name="actionOverflowButtonStyle" format="reference" />
         <!-- Reference to a style for the Action Bar -->
         <attr name="actionBarStyle" format="reference" />
+        <!-- Reference to a style for the split Action Bar. This style
+             controls the split component that holds the menu/action
+             buttons. actionBarStyle is still used for the primary
+             bar. -->
+        <attr name="actionBarSplitStyle" format="reference" />
         <!-- Size of the Action Bar, including the contextual
              bar used to present Action Modes. -->
         <attr name="actionBarSize" format="dimension" >
@@ -1967,6 +1987,28 @@
             <!-- Locale -->
             <enum name="locale" value="3" />
         </attr>
+        <!-- Direction of the text. A heuristic is used to determine the resolved text direction
+             of paragraphs. -->
+        <attr name="textDirection" format="integer">
+            <!-- Default -->
+            <enum name="inherit" value="0" />
+            <!-- Default for the root view. The first strong directional character determines the
+                 paragraph direction.  If there is no strong directional character, the paragraph
+                 direction is the view’s resolved layout direction. -->
+            <enum name="firstStrong" value="1" />
+            <!-- The paragraph direction is RTL if it contains any strong RTL character, otherwise
+                 it is LTR if it contains any strong LTR characters.  If there are neither, the
+                 paragraph direction is the view’s resolved layout direction. -->
+            <enum name="anyRtl" value="2" />
+            <!-- The paragraph direction is the same as the one held by a 60% majority of the
+                 characters. If there is no majority then the paragraph direction is the resolved
+                 layout direction of the View. -->
+            <enum name="charCount" value="3" />
+            <!-- The paragraph direction is left to right. -->
+            <enum name="ltr" value="4" />
+            <!-- The paragraph direction is right to left. -->
+            <enum name="rtl" value="5" />
+        </attr>
     </declare-styleable>
 
     <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
@@ -2125,6 +2167,12 @@
         <!--  Specifies extra space on the bottom side of this view.
               This space is outside this view's bounds. -->
         <attr name="layout_marginBottom" format="dimension"  />
+        <!--  Specifies extra space on the start side of this view.
+              This space is outside this view's bounds. -->
+        <attr name="layout_marginStart" format="dimension"  />
+        <!--  Specifies extra space on the end side of this view.
+              This space is outside this view's bounds. -->
+        <attr name="layout_marginEnd" format="dimension"  />
     </declare-styleable>
 
     <!-- Use <code>input-method</code> as the root tag of the XML resource that
@@ -2179,7 +2227,8 @@
         <!-- The event types this serivce would like to receive as specified in
              {@link android.view.accessibility.AccessibilityEvent}. This setting
              can be changed at runtime by calling
-             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+             android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
         <attr name="accessibilityEventTypes">
             <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} events.-->
             <flag name="typeViewClicked" value="0x00000001" />
@@ -2203,17 +2252,24 @@
             <flag name="typeTouchExplorationGestureStart" value="0x00000200" />
             <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END} events. -->
             <flag name="typeTouchExplorationGestureEnd" value="0x00000400" />
+            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events. -->
+            <flag name="typeWindowContentChanged" value="0x00000800" />
+            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED} events. -->
+            <flag name="typeViewScrolled" value="0x000001000" />
+            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED} events. -->
+            <flag name="typeViewTextSelectionChanged" value="0x000002000" />
             <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPES_ALL_MASK} i.e. all events. -->
             <flag name="typeAllMask" value="0xffffffff" />
         </attr>
         <!-- Comma separated package names from which this serivce would like to receive events (leave out for all packages).
-             This setting can be changed at runtime by calling
-             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+             android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
         <attr name="packageNames" format="string" />
         <!-- The feedback types this serivce provides as specified in
              {@link android.accessibilityservice.AccessibilityServiceInfo}. This setting
              can be changed at runtime by calling
-             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+             android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
         <attr name="accessibilityFeedbackType">
             <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_SPOKEN} feedback. -->
             <flag name="feedbackSpoken" value="0x00000001" />
@@ -2226,14 +2282,16 @@
             <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_GENERIC} feedback. -->
             <flag name="feedbackGeneric" value="0x00000010" />
         </attr>
-        <!-- The minimal period in milliseconds between two accessibility events are sent
-             to this serivce. This setting can be changed at runtime by calling
-             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+        <!-- The minimal period in milliseconds between two accessibility events of the same type
+             are sent to this serivce. This setting can be changed at runtime by calling
+             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+             android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->>
         <attr name="notificationTimeout" format="integer" />
         <!-- Additional flags as specified in
              {@link android.accessibilityservice.AccessibilityServiceInfo}.
              This setting can be changed at runtime by calling
-             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+             android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
         <attr name="accessibilityFlags">
             <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#DEFAULT} -->
             <flag name="flagDefault" value="0x00000001" />
@@ -2242,7 +2300,7 @@
              the settings for this service. This setting cannot be changed at runtime. -->
         <attr name="settingsActivity" />
         <!-- Flag whether the accessibility service wants to be able to retrieve the
-             focused window content. This setting cannot be changed at runtime. -->
+             active window content. This setting cannot be changed at runtime. -->
         <attr name="canRetrieveWindowContent" format="boolean" />
     </declare-styleable>
 
@@ -2767,6 +2825,8 @@
         <attr name="textColorHint" />
         <!-- Color of the links. -->
         <attr name="textColorLink" />
+        <!-- Present the text in ALL CAPS. This may use a small-caps form when available. -->
+        <attr name="textAllCaps" format="boolean" />
     </declare-styleable>
     <declare-styleable name="TextSwitcher">
     </declare-styleable>
@@ -3031,6 +3091,8 @@
         <attr name="textIsSelectable" />
         <!-- Suggestions will be displayed when the user double taps on editable text. -->
         <attr name="suggestionsEnabled" />
+        <!-- Present the text in ALL CAPS. This may use a small-caps form when available. -->
+        <attr name="textAllCaps" />
     </declare-styleable>
     <!-- An <code>input-extras</code> is a container for extra data to supply to
          an input method.  Contains
@@ -3285,11 +3347,6 @@
         The default is one.
         See {@link android.widget.GridLayout.Group}. -->
         <attr name="layout_rowSpan" format="integer" min="1" />
-        <!-- A number indicating the relative proportion of available space that
-        should be taken by this group of cells.
-        The default is zero.
-        See {@link android.widget.GridLayout.LayoutParams#columnWeight}. -->
-        <attr name="layout_rowWeight" format="float" />
         <!-- The column boundary delimiting the left of the group of cells
         occupied by this view. -->
         <attr name="layout_column" />
@@ -3298,15 +3355,26 @@
         The default is one.
         See {@link android.widget.GridLayout.Group}. -->
         <attr name="layout_columnSpan" format="integer" min="1" />
-        <!-- A number indicating the relative proportion of available space that
-        should be taken by this group of cells.
-        The default is zero.
-        See {@link android.widget.GridLayout.LayoutParams#columnWeight}.-->
-        <attr name="layout_columnWeight" format="float" />
         <!-- Gravity specifies how a component should be placed in its group of cells.
         The default is LEFT | BASELINE.
         See {@link android.widget.GridLayout.LayoutParams#setGravity(int)}. -->
         <attr name="layout_gravity" />
+        <!-- A value specifying how much deficit or excess width this component can accomodate.
+        The default is FIXED.
+        See {@link android.widget.GridLayout.Group#flexibility}.-->
+        <attr name="layout_columnFlexibility" >
+            <!-- If possible, width should be greater than or equal to the specified width.
+            See {@link android.widget.GridLayout#CAN_STRETCH}. -->
+            <enum name="canStretch" value="2" />
+        </attr>
+        <!-- A value specifying how much deficit or excess height this component can accomodate.
+        The default is FIXED.
+        See {@link android.widget.GridLayout.Group#flexibility}.-->
+        <attr name="layout_rowFlexibility" >
+            <!-- If possible, height should be greater than or equal to the specified height.
+            See {@link android.widget.GridLayout#CAN_STRETCH}. -->
+            <enum name="canStretch" value="2" />
+        </attr>
     </declare-styleable>
     <declare-styleable name="FrameLayout_Layout">
         <attr name="layout_gravity" />
@@ -4525,6 +4593,25 @@
              for more info. -->
         <attr name="actionViewClass" format="string" />
 
+        <!-- The name of an optional ActionProvider class to instantiate an action view
+             and perform operations such as default action for that menu item.
+             See {@link android.view.MenuItem#setActionProvider(android.view.ActionProvider)}
+             for more info. -->
+        <attr name="actionProviderClass" format="string" />
+
+    </declare-styleable>
+
+    <!-- Attrbitutes for a ActvityChooserView. -->
+    <declare-styleable name="ActivityChooserView">
+        <!-- The maximal number of items initially shown in the activity list. -->
+        <attr name="initialActivityCount" format="string" />
+        <!-- The drawable to show in the button for expanding the activities overflow popup.
+             <strong>Note:</strong> Clients would like to set this drawable
+             as a clue about the action the chosen activity will perform. For
+             example, if share activity is to be chosen the drawable should
+             give a clue that sharing is to be performed.
+         -->
+        <attr name="expandActivityOverflowButtonDrawable" format="reference" />
     </declare-styleable>
 
     <!-- **************************************************************** -->
@@ -5130,6 +5217,10 @@
         <attr name="divider" />
         <!-- Specifies a background drawable for the action bar. -->
         <attr name="background" />
+        <!-- Specifies a background drawable for a second stacked row of the action bar. -->
+        <attr name="backgroundStacked" format="reference" />
+        <!-- Specifies a background drawable for the bottom component of a split action bar. -->
+        <attr name="backgroundSplit" format="reference" />
         <!-- Specifies a layout for custom navigation. Overrides navigationMode. -->
         <attr name="customNavigationLayout" format="reference" />
         <!-- Specifies a fixed height. -->
@@ -5227,6 +5318,8 @@
         <attr name="mtpReserve" format="integer" />
         <!-- true if the storage can be shared via USB mass storage -->
         <attr name="allowMassStorage" format="boolean" />
+        <!-- maximum file size for the volume in megabytes, zero or unspecified if it is unbounded -->
+        <attr name="maxFileSize" format="integer" />
     </declare-styleable>
 
     <declare-styleable name="SwitchPreference">
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index f7974e9..dd16bd0 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -235,12 +235,13 @@
     <attr name="vmSafeMode" format="boolean" />
 
     <!-- <p>Flag indicating whether the application's rendering should be hardware
-         accelerated if possible. This flag is turned off by default, both for
-         applications and activities.</p>
+         accelerated if possible. This flag is turned on by default for applications
+         that are targeting {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}
+         or later.</p>
          <p>This flag can be set on the application and any activity declared
          in the manifest. When enabled for the application, each activity is
          automatically assumed to be hardware accelerated. This flag can be
-         overriden in the activity tags, either turning it off (if on for the
+         overridden in the activity tags, either turning it off (if on for the
          application) or on (if off for the application.)</p>
          <p>When this flag is turned on for an activity (either directly or via
          the application tag), every window created from the activity, including
@@ -695,13 +696,6 @@
          <p>The default value of this attribute is <code>false</code>. -->
     <attr name="restoreAnyVersion" format="boolean" />
 
-    <!-- The agent to use for a *full* backup of the package.  Only system applications
-         can use this to override the ordinary FullBackupAgent with a custom implementation.
-         It's needed strictly for packages with strongly device-specific data, such as the
-         Settings provider.
-         -->
-    <attr name="fullBackupAgent" format="string" />
-
     <!-- The default install location defined by an application. -->
     <attr name="installLocation">
         <!-- Let the system decide ideal install location -->
@@ -799,7 +793,6 @@
         <attr name="killAfterRestore" />
         <attr name="restoreNeedsApplication" />
         <attr name="restoreAnyVersion" />
-        <attr name="fullBackupAgent" />
         <attr name="neverEncrypt" />
         <!-- Request that your application's processes be created with
              a large Dalvik heap.  This applies to <em>all</em> processes
@@ -1020,7 +1013,7 @@
          {@link #AndroidManifest manifest} tag. -->
     <declare-styleable name="AndroidManifestSupportsScreens" parent="AndroidManifest">
         <!-- Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2},
-             this is the new way to specify the screens an application is
+             this is the new way to specify the minimum screen size an application is
              compatible with.  This attribute provides the required minimum
              "smallest screen width" (as per the -swNNNdp resource configuration)
              that the application can run on.  For example, a typical phone
@@ -1031,17 +1024,15 @@
              or xlargeScreens attributes will be used instead. -->
         <attr name="requiresSmallestWidthDp" format="integer" />
         <!-- Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2},
-             this is the new way to specify the screens an application is
+             this is the new way to specify the largest screens an application is
              compatible with.  This attribute provides the maximum
              "smallest screen width" (as per the -swNNNdp resource configuration)
              that the application is designed for.  If this value is smaller than
              the "smallest screen width" of the device it is running on, the user
-             will of offered to run it in a compatibility mode that emulates a
-             smaller screen.  Currently the compatibility mode only emulates
-             phone screens, so it will not be used it the application provides
-             a requiresSmallestWidthDp that is larger than 320.  Typical values
-             used with this attribute are 320 for a phone screen, 600 for a
-             7" tablet, and 720 for a 10" tablet. -->
+             is offered to run it in a compatibility mode that emulates a
+             smaller screen and zooms it to fit the screen. Currently the compatibility mode only
+             emulates phone screens with a 320dp width, so compatibility mode is not applied if the
+             value for compatibleWidthLimitDp is larger than 320. -->
         <attr name="compatibleWidthLimitDp" format="integer" />
         <!-- Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2},
              this is the new way to specify the screens an application is
@@ -1050,9 +1041,9 @@
              that the application can work well on.  If this value is smaller than
              the "smallest screen width" of the device it is running on, the
              application will be forced in to screen compatibility mode with
-             no way for the user to turn it off.  Currently the compatibility mode
-             only emulates phone screens, so even if this value is larger than 320
-             the width the app runs in will be a 320 phone dimension. -->
+             no way for the user to turn it off. Currently the compatibility mode only
+             emulates phone screens with a 320dp width, so compatibility mode is not applied if the
+             value for largestWidthLimitDp is larger than 320. -->
         <attr name="largestWidthLimitDp" format="integer" />
         <!-- Indicates whether the application supports smaller screen form-factors.
              A small screen is defined as one with a smaller aspect ratio than
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index 9647bb7..e51fc66 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -15,7 +15,6 @@
 -->
 
 <resources>
-    <bool name="allow_action_menu_item_text_with_icon">false</bool>
     <bool name="action_bar_embed_tabs">false</bool>
     <bool name="split_action_bar_is_narrow">true</bool>
     <bool name="preferences_prefer_dual_pane">false</bool>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 2a1ebfc..631d8c6 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -143,19 +143,42 @@
     <color name="link_text_holo_light">#0000ee</color>
 
     <!-- Group buttons -->
+    <eat-comment />
     <color name="group_button_dialog_pressed_holo_dark">#46c5c1ff</color>
     <color name="group_button_dialog_focused_holo_dark">#2699cc00</color>
 
     <color name="group_button_dialog_pressed_holo_light">#ffffffff</color>
     <color name="group_button_dialog_focused_holo_light">#4699cc00</color>
 
+    <!-- Highlight colors for the legacy themes -->
+    <eat-comment />
+    <color name="legacy_pressed_highlight">#fffeaa0c</color>
+    <color name="legacy_selected_highlight">#fff17a0a</color>
+    <color name="legacy_long_pressed_highlight">#ffffffff</color>
+
     <!-- General purpose colors for Holo-themed elements -->
     <eat-comment />
 
-    <!-- A Holo shade of blue -->
-    <color name="holo_blue">#ff6699ff</color>
-    <!-- A Holo shade of green -->
-    <color name="holo_green">#ff99cc00</color>
+    <!-- A light Holo shade of blue -->
+    <color name="holo_blue_light">#ff33b5e5</color>
+    <!-- A light Holo shade of green -->
+    <color name="holo_green_light">#ff99cc00</color>
+    <!-- A light Holo shade of red -->
+    <color name="holo_red_light">#ffff4444</color>
+    <!-- A dark Holo shade of blue -->
+    <color name="holo_blue_dark">#ff0099cc</color>
+    <!-- A dark Holo shade of green -->
+    <color name="holo_green_dark">#ff669900</color>
+    <!-- A dark Holo shade of red -->
+    <color name="holo_red_dark">#ffcc0000</color>
+    <!-- A Holo shade of purple -->
+    <color name="holo_purple">#ffaa66cc</color>
+    <!-- A light Holo shade of orange -->
+    <color name="holo_orange_light">#ffffbb33</color>
+    <!-- A dark Holo shade of orange -->
+    <color name="holo_orange_dark">#ffff8800</color>
+    <!-- A really bright Holo shade of blue -->
+    <color name="holo_blue_bright">#ff00ddff</color>
 
 </resources>
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a8b7b75..1f2b7fb 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3,16 +3,16 @@
 /*
 ** Copyright 2009, 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 
+** 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 
+**     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 
+** 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.
 */
 -->
@@ -54,25 +54,25 @@
          connected.  If you use the ims apn DCT will block
          any other apn from connecting until ims apn is connected-->
     <bool name="ImsConnectedDefaultValue">false</bool>
-    
+
     <!-- Flag indicating whether the surface flinger is inefficient
          at performing a blur.  Used by parts of the UI to turn off
          the blur effect where it isn't worth the performance hit. -->
     <bool name="config_sf_slowBlur">false</bool>
-    
+
     <!-- The duration (in milliseconds) of a short animation. -->
     <integer name="config_shortAnimTime">200</integer>
-    
+
     <!-- The duration (in milliseconds) of a medium-length animation. -->
     <integer name="config_mediumAnimTime">400</integer>
-    
+
     <!-- The duration (in milliseconds) of a long animation. -->
     <integer name="config_longAnimTime">500</integer>
 
     <!-- The duration (in milliseconds) of the activity open/close and fragment open/close animations. -->
     <integer name="config_activityShortDur">150</integer>
     <integer name="config_activityDefaultDur">220</integer>
-    
+
     <!-- Duration for the dim animation behind a dialog.  This may be either
          a percentage, which is relative to the duration of the enter/open
          animation of the window being shown that is dimming behind, or it may
@@ -83,11 +83,11 @@
          maximum (let them grow as large as the screen).  Actual values are
          specified for -large and -xlarge configurations. -->
     <dimen name="config_prefDialogWidth">320dp</dimen>
-    
+
     <!-- Whether dialogs should close automatically when the user touches outside
          of them.  This should not normally be modified. -->
     <bool name="config_closeDialogWhenTouchOutside">false</bool>
-    
+
     <!-- The duration (in milliseconds) that the radio will scan for a signal
          when there's no network connection. If the scan doesn't timeout, use zero -->
     <integer name="config_radioScanningTimeout">0</integer>
@@ -115,6 +115,14 @@
         <item>"mobile_cbs,12,0,2,60000,true"</item>
     </string-array>
 
+    <!-- Array of ConnectivityManager.TYPE_xxxx constants for networks that may only
+         be controlled by systemOrSignature apps.  -->
+    <integer-array translatable="false" name="config_protectedNetworks">
+        <item>10</item>
+        <item>11</item>
+        <item>12</item>
+    </integer-array>
+
     <!-- This string array should be overridden by the device to present a list of radio
          attributes.  This is used by the connectivity manager to decide which networks can coexist
          based on the hardware -->
@@ -194,7 +202,7 @@
          the slider is open.  This can be set or unset depending how easily
          the slider can be opened (for example, in a pocket or purse). -->
     <bool name="config_bypass_keyguard_if_slider_open">true</bool>
-    
+
     <!-- Flag indicating whether the we should enable the automatic brightness in Settings.
          Software implementation will be used if config_hardware_auto_brightness_available is not set -->
     <bool name="config_automatic_brightness_available">false</bool>
@@ -204,10 +212,10 @@
 
     <!-- If this is true, the screen will come on when you unplug usb/power/whatever. -->
     <bool name="config_unplugTurnsOnScreen">false</bool>
-    
+
     <!-- If this is true, the screen will fade off. -->
     <bool name="config_animateScreenLights">true</bool>
-    
+
     <!-- XXXXXX END OF RESOURCES USING WRONG NAMING CONVENTION -->
 
     <!-- If true, the screen can be rotated via the accelerometer in all 4
@@ -292,7 +300,7 @@
         <item>20</item>
         <item>21</item>
     </integer-array>
-    
+
     <!-- Vibrator pattern for feedback about touching a virtual key -->
     <integer-array name="config_virtualKeyVibePattern">
         <item>0</item>
@@ -372,8 +380,8 @@
     <!-- Allow the menu hard key to be disabled in LockScreen on some devices -->
     <bool name="config_disableMenuKeyInLockScreen">false</bool>
 
-    <!-- Show sliding tab before lockscreen -->
-    <bool name="config_enableSlidingTabFirst">true</bool>
+    <!-- Don't show lock screen before unlock screen (PIN/pattern/password) -->
+    <bool name="config_enableLockBeforeUnlockScreen">false</bool>
 
     <!-- Diable lockscreen rotation by default -->
     <bool name="config_enableLockScreenRotation">false</bool>
@@ -433,18 +441,6 @@
     <!-- Enables swipe versus poly-finger touch disambiguation in the KeyboardView -->
     <bool name="config_swipeDisambiguation">true</bool>
 
-    <!-- Enables special filtering code in the framework for raw touch events
-         from the touch driver.  This code exists for one particular device,
-         and should not be enabled for any others.  Hopefully in the future
-         it will be removed when the lower-level touch driver generates better
-         data. -->
-    <bool name="config_filterTouchEvents">false</bool>
-
-    <!-- Enables special filtering code in the framework for raw touch events
-         from the touch driver. This code exists for one particular device,
-         and should not be enabled for any others. -->
-    <bool name="config_filterJumpyTouchEvents">false</bool>
-
     <!-- Specifies the amount of time to disable virtual keys after the screen is touched
          in order to filter out accidental virtual key presses due to swiping gestures
          or taps near the edge of the display.  May be 0 to disable the feature.
@@ -452,7 +448,7 @@
          This feature should be disabled for most devices. -->
     <integer name="config_virtualKeyQuietTimeMillis">0</integer>
 
-    <!-- Component name of the default wallpaper. This will be ImageWallpaper if not 
+    <!-- Component name of the default wallpaper. This will be ImageWallpaper if not
          specified -->
     <string name="default_wallpaper_component">@null</string>
 
@@ -650,4 +646,23 @@
          This is intended to allow packaging drivers or tools for installation on a PC. -->
     <string translatable="false" name="config_isoImagePath"></string>
 
+    <!-- Whether a software navigation bar should be shown. NOTE: in the future this may be
+         autodetected from the Configuration. -->
+    <bool name="config_showNavigationBar">false</bool>
+
+    <!-- Whether action menu items should be displayed in ALLCAPS or not.
+         Defaults to true. If this is not appropriate for specific locales
+         it should be disabled in that locale's resources. -->
+    <bool name="config_actionMenuItemAllCaps">true</bool>
+
+    <!-- Whether action menu items should obey the "withText" showAsAction
+         flag. This may be set to false for situations where space is
+         extremely limited. -->
+    <bool name="config_allowActionMenuItemTextWithIcon">false</bool>
+
+    <!-- Remote server that can provide NTP responses. -->
+    <string translatable="false" name="config_ntpServer">pool.ntp.org</string>
+    <!-- Timeout to wait for NTP server response. -->
+    <integer name="config_ntpTimeout">20000</integer>
+
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 580c204..f7701f2 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1714,10 +1714,6 @@
   <public type="attr" name="switchTextOff" />
   <public type="attr" name="switchPreferenceStyle" />
 
-  <public type="style" name="TextAppearance.SuggestionHighlight" />
-  <public type="style" name="Theme.Holo.SplitActionBarWhenNarrow" />
-  <public type="style" name="Theme.Holo.Light.SplitActionBarWhenNarrow" />
-
   <public type="attr" name="textSuggestionsWindowStyle" />
   <public type="attr" name="textEditSuggestionsBottomWindowLayout" />
   <public type="attr" name="textEditSuggestionsTopWindowLayout" />
@@ -1725,7 +1721,6 @@
 
   <public type="attr" name="layoutDirection" />
 
-  <public type="attr" name="fullBackupAgent" />
   <public type="attr" name="suggestionsEnabled" />
 
   <public type="attr" name="rowCount" />
@@ -1737,10 +1732,11 @@
 
   <public type="attr" name="layout_row" />
   <public type="attr" name="layout_rowSpan" />
+  <public type="attr" name="layout_rowFlexibility" />
 
-  <public type="attr" name="layout_rowWeight" />
   <public type="attr" name="layout_columnSpan" />
-  <public type="attr" name="layout_columnWeight" />
+  <public type="attr" name="layout_columnFlexibility" />
+
   <public type="attr" name="actionModeSelectAllDrawable" />
 
   <public type="attr" name="isAuxiliary" />
@@ -1769,13 +1765,65 @@
   <public type="attr" name="listPreferredItemHeightLarge" />
   <public type="attr" name="listPreferredItemHeightSmall" />
 
+  <public type="attr" name="paddingStart"/>
+  <public type="attr" name="paddingEnd"/>
+  <public type="attr" name="layout_marginStart"/>
+  <public type="attr" name="layout_marginEnd"/>
+
+  <public type="attr" name="actionBarSplitStyle" />
+
+  <public type="attr" name="textDirection"/>
+
+  <public type="attr" name="actionProviderClass" />
+
+  <public type="attr" name="backgroundStacked" />
+  <public type="attr" name="backgroundSplit" />
+
+  <public type="attr" name="textAllCaps" />
+
+  <public type="attr" name="colorPressedHighlight" />
+  <public type="attr" name="colorLongPressedHighlight" />
+  <public type="attr" name="colorFocusedHighlight" />
+  <public type="attr" name="colorActivatedHighlight" />
+  <public type="attr" name="colorMultiSelectHighlight" />
+
+  <public type="style" name="TextAppearance.SuggestionHighlight" />
+  <public type="style" name="Theme.Holo.SplitActionBarWhenNarrow" />
+  <public type="style" name="Theme.Holo.Light.SplitActionBarWhenNarrow" />
+
   <public type="style" name="Widget.Holo.Button.Borderless.Small" />
   <public type="style" name="Widget.Holo.Light.Button.Borderless.Small" />
+  <public type="style" name="TextAppearance.Holo.Widget.ActionBar.Title.Inverse" />
+  <public type="style" name="TextAppearance.Holo.Widget.ActionBar.Subtitle.Inverse" />
+  <public type="style" name="TextAppearance.Holo.Widget.ActionMode.Title.Inverse" />
+  <public type="style" name="TextAppearance.Holo.Widget.ActionMode.Subtitle.Inverse" />
+  <public type="style" name="TextAppearance.Holo.Widget.ActionBar.Menu" />
+  <public type="style" name="Widget.Holo.ActionBar.Solid" />
+  <public type="style" name="Widget.Holo.Light.ActionBar.Solid" />
+  <public type="style" name="Widget.Holo.Light.ActionBar.Solid.Inverse" />
+  <public type="style" name="Widget.Holo.Light.ActionBar.TabBar.Inverse" />
+  <public type="style" name="Widget.Holo.Light.ActionBar.TabView.Inverse" />
+  <public type="style" name="Widget.Holo.Light.ActionBar.TabText.Inverse" />
+  <public type="style" name="Widget.Holo.Light.ActionMode.Inverse" />
+  <public type="style" name="Theme.Holo.SolidActionBar" />
+  <public type="style" name="Theme.Holo.Light.SolidActionBar" />
+  <public type="style" name="Theme.Holo.Light.SolidActionBar.Inverse" />
+  <public type="style" name="Theme.Holo.SolidActionBar.SplitActionBarWhenNarrow" />
+  <public type="style" name="Theme.Holo.Light.SolidActionBar.SplitActionBarWhenNarrow" />
+  <public type="style" name="Theme.Holo.Light.SolidActionBar.Inverse.SplitActionBarWhenNarrow" />
 
   <public type="integer" name="status_bar_notification_info_maxnum" />
   <public type="string" name="status_bar_notification_info_overflow" />
 
-  <public type="attr" name="paddingStart"/>
-  <public type="attr" name="paddingEnd"/>
+  <public type="color" name="holo_blue_light" />
+  <public type="color" name="holo_blue_dark" />
+  <public type="color" name="holo_green_light" />
+  <public type="color" name="holo_green_dark" />
+  <public type="color" name="holo_red_light" />
+  <public type="color" name="holo_red_dark" />
+  <public type="color" name="holo_orange_light" />
+  <public type="color" name="holo_orange_dark" />
+  <public type="color" name="holo_purple" />
+  <public type="color" name="holo_blue_bright" />
 
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b5f4084..97a8c0b 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1443,6 +1443,11 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_manageNetworkPolicy">Allows an application to manage network policies and define application-specific rules.</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_modifyNetworkAccounting">modify network usage accounting</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_modifyNetworkAccounting">Allows modification of how network usage is accounted against applications. Not for use by normal applications.</string>
+
     <!-- Policy administration -->
 
     <!-- Title of policy access to limiting the user's password choices -->
@@ -2068,6 +2073,22 @@
     <!-- Do not translate. Regex used by AutoFill. -->
     <string name="autofill_fax_re">fax<!-- fr-FR -->|télécopie|telecopie<!-- ja-JP -->|ファックス<!-- ru -->|факс<!-- zh-CN -->|传真<!-- zh-TW -->|傳真</string>
 
+    <!-- Do not translate. Regex used by AutoFill. -->
+    <string name="autofill_country_code_re">country.*code|ccode|_cc</string>
+
+    <!-- Do not translate. Regex used by AutoFill. -->
+    <string name="autofill_area_code_notext_re">^\($</string>
+
+    <!-- Do not translate. Regex used by AutoFill. -->
+    <string name="autofill_phone_prefix_separator_re">^-$|^\)$</string>
+
+    <!-- Do not translate. Regex used by AutoFill. -->
+    <string name="autofill_phone_suffix_separator_re">^-$</string>
+
+    <!-- Do not translate. Regex used by AutoFill. -->
+    <!-- Ex: ************1234 -->
+    <string name="credit_card_number_preview_format">$1</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_readHistoryBookmarks">read Browser\'s history and bookmarks</string>
@@ -2608,10 +2629,14 @@
     <!-- USB_STORAGE_ERROR dialog  ok button-->
     <string name="dlg_ok">OK</string>
 
-    <!-- USB_PREFERENCES: When the user connects the phone to a computer via USB, we show a notification asking if he wants to share files across.  This is the title -->
-    <string name="usb_preferences_notification_title">USB connected</string>
+    <!-- USB_PREFERENCES: Notification for wehen the user connects the phone to a computer via USB in MTP mode.  This is the title -->
+    <string name="usb_mtp_notification_title">Connected as a media device</string>
+    <!-- USB_PREFERENCES: Notification for wehen the user connects the phone to a computer via USB in PTP mode.  This is the title -->
+    <string name="usb_ptp_notification_title">Connected as a camera</string>
+    <!-- USB_PREFERENCES: Notification for wehen the user connects the phone to a computer via USB in mass storage mode (for installer CD image).  This is the title -->
+    <string name="usb_cd_installer_notification_title">Connected as an installer</string>
     <!-- See USB_PREFERENCES. This is the message. -->
-    <string name="usb_preferece_notification_message">Select to configure USB file transfer.</string>
+    <string name="usb_notification_message">Touch for other USB options</string>
 
     <!-- External media format dialog strings -->
     <!-- This is the label for the activity, and should never be visible to the user. -->
@@ -2778,15 +2803,10 @@
     <!-- Do Not Translate: Alternate eri.xml -->
     <string name="alternate_eri_file">/data/eri.xml</string>
 
-    <string name="pptp_vpn_description">Point-to-Point Tunneling Protocol</string>
-    <string name="l2tp_vpn_description">Layer 2 Tunneling Protocol</string>
-    <string name="l2tp_ipsec_psk_vpn_description">Pre-shared key based L2TP/IPSec VPN</string>
-    <string name="l2tp_ipsec_crt_vpn_description">Certificate based L2TP/IPSec VPN</string>
-
-    <!-- Ticker text to show when VPN is active. -->
-    <string name="vpn_ticker"><xliff:g id="app" example="FooVPN client">%s</xliff:g> is activating VPN...</string>
     <!-- The title of the notification when VPN is active. -->
-    <string name="vpn_title">VPN is activated by <xliff:g id="app" example="FooVPN client">%s</xliff:g></string>
+    <string name="vpn_title">VPN is activated.</string>
+    <!-- The title of the notification when VPN is active with an application name. -->
+    <string name="vpn_title_long">VPN is activated by <xliff:g id="app" example="FooVPN client">%s</xliff:g></string>
     <!-- The text of the notification when VPN is active. -->
     <string name="vpn_text">Tap to manage the network.</string>
     <!-- The text of the notification when VPN is active with a session name. -->
@@ -2910,13 +2930,6 @@
     <!-- Dialog action for when there are too many deletes that would take place and we want user confirmation, and the user wants to do nothing for now -->
     <string name="sync_do_nothing">Do nothing for now.</string>
 
-    <!-- Title of the VPN service notification: VPN connected [CHAR LIMIT=NONE] -->
-    <string name="vpn_notification_title_connected"><xliff:g id="profilename" example="Home PPTP">%s</xliff:g> VPN connected</string>
-    <!-- Title of the VPN service notification: VPN disconnected [CHAR LIMIT=NONE] -->
-    <string name="vpn_notification_title_disconnected"><xliff:g id="profilename" example="Home PPTP">%s</xliff:g> VPN disconnected</string>
-    <!-- Message of the VPN service notification: Hint to reconnect VPN [CHAR LIMIT=NONE] -->
-    <string name="vpn_notification_hint_disconnected">Touch to reconnect to a VPN.</string>
-
     <!-- Choose Account Activity label -->
     <string name="choose_account_label">Select an account</string>
 
@@ -2959,4 +2972,41 @@
     <!-- Notification body when data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
     <string name="data_usage_limit_body">tap to enable</string>
 
+    <!-- SSL Certificate dialogs -->
+    <!-- Title for an SSL Certificate dialog -->
+    <string name="ssl_certificate">Security certificate</string>
+    <!-- Message on an SSL Certificate dialog -->
+    <string name="ssl_certificate_is_valid">This certificate is valid.</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="issued_to">Issued to:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="common_name">Common name:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="org_name">Organization:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="org_unit">Organizational unit:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="issued_by">Issued by:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="validity_period">Validity:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="issued_on">Issued on:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="expires_on">Expires on:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="serial_number">Serial number:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="fingerprints">Fingerprints:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="sha256_fingerprint">SHA-256 fingerprint:</string>
+    <!-- Label for an information field on an SSL Certificate Dialog -->
+    <string name="sha1_fingerprint">SHA-1 fingerprint:</string>
+
+    <!-- Title for a button to expand the list of activities in ActivityChooserView [CHAR LIMIT=25] -->
+    <string name="activity_chooser_view_see_all">See all...</string>
+    <!-- Title for a message that there are no activities in ActivityChooserView [CHAR LIMIT=25] -->
+    <string name="activity_chooser_view_no_activities">No activities</string>
+    <!-- Title for a message that prompts selection of a default share handler in ActivityChooserView [CHAR LIMIT=25] -->
+    <string name="activity_chooser_view_select_default">Select default</string>
+
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 5244b74..a5cd6e3 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1304,13 +1304,45 @@
         <item name="android:textSize">@android:dimen/action_bar_subtitle_text_size</item>
     </style>
 
+    <style name="TextAppearance.Holo.Widget.ActionBar.Title.Inverse"
+           parent="TextAppearance.Holo.Medium.Inverse">
+        <item name="android:textSize">@android:dimen/action_bar_title_text_size</item>
+    </style>
+
+    <style name="TextAppearance.Holo.Widget.ActionBar.Subtitle.Inverse"
+           parent="TextAppearance.Holo.Small.Inverse">
+        <item name="android:textSize">@android:dimen/action_bar_subtitle_text_size</item>
+    </style>
+
+    <style name="TextAppearance.Holo.Widget.ActionBar.Menu"
+           parent="TextAppearance.Holo.Small">
+        <item name="android:textSize">12sp</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:textColor">?android:attr/actionMenuTextColor</item>
+        <item name="android:textAllCaps">true</item>
+    </style>
+
     <style name="TextAppearance.Holo.Widget.ActionMode">
     </style>
 
-    <style name="TextAppearance.Holo.Widget.ActionMode.Title" parent="TextAppearance.Widget.ActionMode.Title">
+    <style name="TextAppearance.Holo.Widget.ActionMode.Title"
+           parent="TextAppearance.Holo.Medium">
+        <item name="android:textSize">@android:dimen/action_bar_title_text_size</item>
     </style>
 
-    <style name="TextAppearance.Holo.Widget.ActionMode.Subtitle" parent="TextAppearance.Widget.ActionMode.Subtitle">
+    <style name="TextAppearance.Holo.Widget.ActionMode.Subtitle"
+           parent="TextAppearance.Holo.Small">
+        <item name="android:textSize">@android:dimen/action_bar_subtitle_text_size</item>
+    </style>
+
+    <style name="TextAppearance.Holo.Widget.ActionMode.Title.Inverse"
+           parent="TextAppearance.Holo.Medium.Inverse">
+        <item name="android:textSize">@android:dimen/action_bar_title_text_size</item>
+    </style>
+
+    <style name="TextAppearance.Holo.Widget.ActionMode.Subtitle.Inverse"
+           parent="TextAppearance.Holo.Small.Inverse">
+        <item name="android:textSize">@android:dimen/action_bar_subtitle_text_size</item>
     </style>
 
     <style name="TextAppearance.Holo.Widget.Switch" parent="TextAppearance.Holo.Small">
@@ -1324,7 +1356,7 @@
 
     <style name="TextAppearance.Holo.DialogWindowTitle">
         <item name="android:textSize">22sp</item>
-        <item name="android:textColor">@android:color/holo_blue</item>
+        <item name="android:textColor">@android:color/holo_blue_light</item>
     </style>
 
     <style name="TextAppearance.Holo.CalendarViewWeekDayView" parent="TextAppearance.Small.CalendarViewWeekDayView">
@@ -1423,7 +1455,7 @@
 
     <style name="TextAppearance.Holo.Light.DialogWindowTitle">
         <item name="android:textSize">22sp</item>
-        <item name="android:textColor">@android:color/holo_blue</item>
+        <item name="android:textColor">@android:color/holo_blue_light</item>
     </style>
 
     <style name="TextAppearance.Holo.Light.CalendarViewWeekDayView" parent="TextAppearance.Small.CalendarViewWeekDayView">
@@ -1824,7 +1856,9 @@
     <style name="Widget.Holo.ActionBar.TabText" parent="Widget.ActionBar.TabText">
         <item name="android:textAppearance">@style/TextAppearance.Holo.Medium</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
-        <item name="android:textSize">18sp</item>
+        <item name="android:textSize">12sp</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:textAllCaps">true</item>
     </style>
 
     <style name="Widget.Holo.ActionMode" parent="Widget.ActionMode">
@@ -1839,7 +1873,22 @@
     <style name="Widget.Holo.ActionBar" parent="Widget.ActionBar">
         <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Title</item>
         <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle</item>
-        <item name="android:background">@null</item>
+        <item name="android:background">@android:drawable/ab_transparent_dark_holo</item>
+        <item name="android:backgroundStacked">@android:drawable/ab_stacked_transparent_dark_holo</item>
+        <item name="android:backgroundSplit">@android:drawable/ab_bottom_transparent_dark_holo</item>
+        <item name="android:divider">?android:attr/dividerVertical</item>
+        <item name="android:progressBarStyle">@android:style/Widget.Holo.ProgressBar.Horizontal</item>
+        <item name="android:indeterminateProgressStyle">@android:style/Widget.Holo.ProgressBar</item>
+        <item name="android:progressBarPadding">32dip</item>
+        <item name="android:itemPadding">8dip</item>
+    </style>
+
+    <style name="Widget.Holo.ActionBar.Solid">
+        <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Title</item>
+        <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle</item>
+        <item name="android:background">@android:drawable/ab_solid_dark_holo</item>
+        <item name="android:backgroundStacked">@android:drawable/ab_stacked_solid_dark_holo</item>
+        <item name="android:backgroundSplit">@android:drawable/ab_bottom_solid_dark_holo</item>
         <item name="android:divider">?android:attr/dividerVertical</item>
         <item name="android:progressBarStyle">@android:style/Widget.Holo.ProgressBar.Horizontal</item>
         <item name="android:indeterminateProgressStyle">@android:style/Widget.Holo.ProgressBar</item>
@@ -2157,23 +2206,66 @@
     <style name="Widget.Holo.Light.ActionBar.TabText" parent="Widget.Holo.ActionBar.TabText">
     </style>
 
+    <style name="Widget.Holo.Light.ActionBar.TabView.Inverse">
+    </style>
+
+    <style name="Widget.Holo.Light.ActionBar.TabBar.Inverse">
+    </style>
+
+    <style name="Widget.Holo.Light.ActionBar.TabText.Inverse">
+        <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
+    </style>
+
     <style name="Widget.Holo.Light.ActionMode" parent="Widget.Holo.ActionMode">
         <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionMode.Title</item>
         <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionMode.Subtitle</item>
     </style>
 
+    <style name="Widget.Holo.Light.ActionMode.Inverse" parent="Widget.ActionMode">
+        <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionMode.Title.Inverse</item>
+        <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionMode.Subtitle.Inverse</item>
+    </style>
+
     <style name="Widget.Holo.Light.ActionButton.CloseMode">
     </style>
 
     <style name="Widget.Holo.Light.ActionBar" parent="Widget.Holo.ActionBar">
         <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Title</item>
         <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle</item>
-        <item name="android:background">@null</item>
+        <item name="android:background">@android:drawable/ab_transparent_light_holo</item>
+        <item name="android:backgroundStacked">@android:drawable/ab_stacked_transparent_light_holo</item>
+        <item name="android:backgroundSplit">@android:drawable/ab_bottom_transparent_light_holo</item>
         <item name="android:homeAsUpIndicator">@android:drawable/ic_ab_back_holo_light</item>
         <item name="android:progressBarStyle">@android:style/Widget.Holo.Light.ProgressBar.Horizontal</item>
         <item name="android:indeterminateProgressStyle">@android:style/Widget.Holo.Light.ProgressBar</item>
     </style>
 
+    <style name="Widget.Holo.Light.ActionBar.Solid">
+        <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Title</item>
+        <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle</item>
+        <item name="android:background">@android:drawable/ab_solid_light_holo</item>
+        <item name="android:backgroundStacked">@android:drawable/ab_stacked_solid_light_holo</item>
+        <item name="android:backgroundSplit">@android:drawable/ab_bottom_solid_light_holo</item>
+        <item name="android:divider">?android:attr/dividerVertical</item>
+        <item name="android:progressBarStyle">@android:style/Widget.Holo.Light.ProgressBar.Horizontal</item>
+        <item name="android:indeterminateProgressStyle">@android:style/Widget.Holo.Light.ProgressBar</item>
+        <item name="android:progressBarPadding">32dip</item>
+        <item name="android:itemPadding">8dip</item>
+    </style>
+
+    <style name="Widget.Holo.Light.ActionBar.Solid.Inverse">
+        <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Title.Inverse</item>
+        <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle.Inverse</item>
+        <item name="android:background">@android:drawable/ab_solid_dark_holo</item>
+        <item name="android:backgroundStacked">@android:drawable/ab_stacked_solid_dark_holo</item>
+        <item name="android:backgroundSplit">@android:drawable/ab_bottom_solid_inverse_holo</item>
+        <item name="android:divider">@android:drawable/list_divider_holo_dark</item>
+        <item name="android:progressBarStyle">@android:style/Widget.Holo.ProgressBar.Horizontal</item>
+        <item name="android:indeterminateProgressStyle">@android:style/Widget.Holo.ProgressBar</item>
+        <item name="android:progressBarPadding">32dip</item>
+        <item name="android:itemPadding">8dip</item>
+    </style>
+
     <!-- Animation Styles -->
 
     <style name="Animation.Holo" parent="Animation">
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 1fe4804..90f3602 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -31,6 +31,13 @@
         <item name="colorForegroundInverse">@android:color/bright_foreground_dark_inverse</item>
         <item name="colorBackground">@android:color/background_dark</item>
         <item name="colorBackgroundCacheHint">?android:attr/colorBackground</item>
+
+        <item name="colorPressedHighlight">@color/legacy_pressed_highlight</item>
+        <item name="colorLongPressedHighlight">@color/legacy_long_pressed_highlight</item>
+        <item name="colorFocusedHighlight">@color/legacy_selected_highlight</item>
+        <item name="colorMultiSelectHighlight">@color/legacy_selected_highlight</item>
+        <item name="colorActivatedHighlight">@color/legacy_selected_highlight</item>
+
         <item name="disabledAlpha">0.5</item>
         <item name="backgroundDimAmount">0.6</item>
 
@@ -280,9 +287,10 @@
         <item name="actionModeStyle">@style/Widget.ActionMode</item>
         <item name="actionModeCloseButtonStyle">@style/Widget.ActionButton.CloseMode</item>
         <item name="actionBarStyle">@android:style/Widget.ActionBar</item>
+        <item name="actionBarSplitStyle">?android:attr/actionBarStyle</item>
         <item name="actionBarSize">@dimen/action_bar_default_height</item>
         <item name="actionModePopupWindowStyle">?android:attr/popupWindowStyle</item>
-        <item name="actionMenuTextAppearance">?android:attr/textAppearanceMedium</item>
+        <item name="actionMenuTextAppearance">@android:style/TextAppearance.Holo.Widget.ActionBar.Menu</item>
         <item name="actionMenuTextColor">?android:attr/textColorPrimary</item>
 
         <item name="dividerVertical">@drawable/divider_vertical_dark</item>
@@ -798,6 +806,12 @@
         <item name="disabledAlpha">0.5</item>
         <item name="backgroundDimAmount">0.6</item>
 
+        <item name="colorPressedHighlight">@color/holo_blue_light</item>
+        <item name="colorLongPressedHighlight">@color/holo_blue_bright</item>
+        <item name="colorFocusedHighlight">@color/holo_blue_dark</item>
+        <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
+        <item name="colorActivatedHighlight">@color/holo_blue_dark</item>
+
         <!-- Text styles -->
         <item name="textAppearance">@android:style/TextAppearance.Holo</item>
         <item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Inverse</item>
@@ -1089,6 +1103,11 @@
         <item name="disabledAlpha">0.5</item>
         <item name="backgroundDimAmount">0.6</item>
 
+        <item name="colorPressedHighlight">@color/holo_blue_light</item>
+        <item name="colorLongPressedHighlight">@color/holo_blue_bright</item>
+        <item name="colorFocusedHighlight">@color/holo_blue_dark</item>
+        <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
+        <item name="colorActivatedHighlight">@color/holo_blue_dark</item>
 
         <!-- Text styles -->
         <item name="textAppearance">@android:style/TextAppearance.Holo.Light</item>
@@ -1364,6 +1383,72 @@
 
     </style>
 
+    <!-- Variant of the holographic (dark) theme that has a solid (opaque) action bar. -->
+    <style name="Theme.Holo.SolidActionBar">
+        <item name="android:actionBarStyle">@android:style/Widget.Holo.ActionBar.Solid</item>
+        <item name="android:windowContentOverlay">@android:drawable/ab_solid_shadow_holo</item>
+    </style>
+
+    <!-- Variant of the holographic (light) theme that has a solid (opaque) action bar. -->
+    <style name="Theme.Holo.Light.SolidActionBar">
+        <item name="android:actionBarStyle">@android:style/Widget.Holo.Light.ActionBar.Solid</item>
+        <item name="android:windowContentOverlay">@android:drawable/ab_solid_shadow_holo</item>
+    </style>
+
+    <!-- Variant of the holographic (light) theme that has a solid (opaque) action bar
+         with an inverse color profile. The dark action bar sharply stands out against
+         the light content. -->
+    <style name="Theme.Holo.Light.SolidActionBar.Inverse">
+        <item name="android:windowContentOverlay">@android:drawable/title_bar_shadow</item>
+        <item name="android:actionBarStyle">@android:style/Widget.Holo.Light.ActionBar.Solid.Inverse</item>
+
+        <item name="actionDropDownStyle">@android:style/Widget.Holo.Spinner.DropDown.ActionBar</item>
+        <item name="actionButtonStyle">@android:style/Widget.Holo.ActionButton</item>
+        <item name="actionOverflowButtonStyle">@android:style/Widget.Holo.ActionButton.Overflow</item>
+        <item name="actionModeBackground">@android:drawable/cab_background_holo_dark</item>
+        <item name="actionModeCloseDrawable">@android:drawable/cab_ic_close_holo</item>
+        <item name="homeAsUpIndicator">@android:drawable/ic_ab_back_holo_dark</item>
+        <item name="actionBarTabStyle">@style/Widget.Holo.Light.ActionBar.TabView.Inverse</item>
+        <item name="actionBarTabBarStyle">@style/Widget.Holo.Light.ActionBar.TabBar.Inverse</item>
+        <item name="actionBarTabTextStyle">@style/Widget.Holo.Light.ActionBar.TabText.Inverse</item>
+        <item name="actionMenuTextColor">?android:attr/textColorPrimaryInverse</item>
+        <item name="actionModeStyle">@style/Widget.Holo.Light.ActionMode.Inverse</item>
+        <item name="actionModeCloseButtonStyle">@style/Widget.Holo.ActionButton.CloseMode</item>
+        <item name="actionModePopupWindowStyle">@android:style/Widget.Holo.PopupWindow.ActionMode</item>
+
+        <item name="actionModeCutDrawable">@android:drawable/ic_menu_cut_holo_dark</item>
+        <item name="actionModeCopyDrawable">@android:drawable/ic_menu_copy_holo_dark</item>
+        <item name="actionModePasteDrawable">@android:drawable/ic_menu_paste_holo_dark</item>
+        <item name="actionModeSelectAllDrawable">@android:drawable/ic_menu_selectall_holo_dark</item>
+        <item name="actionModeShareDrawable">@android:drawable/ic_menu_share_holo_dark</item>
+        <item name="actionModeFindDrawable">@android:drawable/ic_menu_find_holo_dark</item>
+        <item name="actionModeWebSearchDrawable">@android:drawable/ic_menu_search_holo_dark</item>
+    </style>
+
+    <!-- Variant of the holographic (dark) theme that has a solid
+         (opaque) action bar. The action bar will split across both
+         the top and bottom of the screen when the screen is
+         especially constrained for horizontal space. -->
+    <style name="Theme.Holo.SolidActionBar.SplitActionBarWhenNarrow">
+        <item name="android:windowSplitActionBar">@android:bool/split_action_bar_is_narrow</item>
+    </style>
+
+    <!-- Variant of the holographic (light) theme that has a solid
+         (opaque) action bar. The action bar will split across both
+         the top and bottom of the screen when the screen is
+         especially constrained for horizontal space. -->
+    <style name="Theme.Holo.Light.SolidActionBar.SplitActionBarWhenNarrow">
+        <item name="android:windowSplitActionBar">@android:bool/split_action_bar_is_narrow</item>
+    </style>
+
+    <!-- Variant of the holographic (light) theme that has a solid (opaque) action bar
+         with an inverse color profile. The dark action bar sharply stands out against
+         the light content. The action bar will split across both the top and bottom of
+         the screen when the screen is especially constrained for horizontal space. -->
+    <style name="Theme.Holo.Light.SolidActionBar.Inverse.SplitActionBarWhenNarrow">
+        <item name="android:windowSplitActionBar">@android:bool/split_action_bar_is_narrow</item>
+    </style>
+
     <!-- Variant of the holographic (dark) theme with no action bar. -->
     <style name="Theme.Holo.NoActionBar">
         <item name="android:windowActionBar">false</item>
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 8e2d925..40fa552 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1051,6 +1051,13 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.widget.TextViewTestActivity" android:label="TextViewTestActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
 
 
         <!-- Activity-level metadata -->
diff --git a/core/tests/coretests/res/layout/textview_test.xml b/core/tests/coretests/res/layout/textview_test.xml
new file mode 100644
index 0000000..f0c7b9e
--- /dev/null
+++ b/core/tests/coretests/res/layout/textview_test.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:id="@+id/textviewtest_layout"
+              android:layout_width="fill_parent"
+              android:layout_height="fill_parent">
+
+    <TextView android:id="@+id/textviewtest_textview"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"
+              android:text="@string/textview_hebrew_text"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/core/tests/coretests/res/values/strings.xml b/core/tests/coretests/res/values/strings.xml
index f51b08e..71f3520 100644
--- a/core/tests/coretests/res/values/strings.xml
+++ b/core/tests/coretests/res/values/strings.xml
@@ -129,4 +129,6 @@
     <string name="button8">Button8</string>
     <string name="button9">Button9</string>
 
+    <string name="textview_hebrew_text">&#x05DD;&#x05DE;ab?!</string>
+
 </resources>
diff --git a/core/tests/coretests/src/android/pim/EventRecurrenceTest.java b/core/tests/coretests/src/android/pim/EventRecurrenceTest.java
deleted file mode 100644
index 05000f1..0000000
--- a/core/tests/coretests/src/android/pim/EventRecurrenceTest.java
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.pim;
-
-import android.pim.EventRecurrence.InvalidFormatException;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.Suppress;
-
-import junit.framework.TestCase;
-
-import java.util.Arrays;
-
-/**
- * Test android.pim.EventRecurrence.
- *
- * adb shell am instrument -w -e class android.pim.EventRecurrenceTest \
- *   com.android.frameworks.coretests/android.test.InstrumentationTestRunner
- */
-public class EventRecurrenceTest extends TestCase {
-
-    @SmallTest
-    public void test0() throws Exception {
-        verifyRecurType("FREQ=SECONDLY",
-                /* int freq */         EventRecurrence.SECONDLY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      null,
-                /* int[] bydayNum */   null,
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    @SmallTest
-    public void test1() throws Exception {
-        verifyRecurType("FREQ=MINUTELY",
-                /* int freq */         EventRecurrence.MINUTELY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      null,
-                /* int[] bydayNum */   null,
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    @SmallTest
-    public void test2() throws Exception {
-        verifyRecurType("FREQ=HOURLY",
-                /* int freq */         EventRecurrence.HOURLY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      null,
-                /* int[] bydayNum */   null,
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    @SmallTest
-    public void test3() throws Exception {
-        verifyRecurType("FREQ=DAILY",
-                /* int freq */         EventRecurrence.DAILY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      null,
-                /* int[] bydayNum */   null,
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    @SmallTest
-    public void test4() throws Exception {
-        verifyRecurType("FREQ=WEEKLY",
-                /* int freq */         EventRecurrence.WEEKLY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      null,
-                /* int[] bydayNum */   null,
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    @SmallTest
-    public void test5() throws Exception {
-        verifyRecurType("FREQ=MONTHLY",
-                /* int freq */         EventRecurrence.MONTHLY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      null,
-                /* int[] bydayNum */   null,
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    @SmallTest
-    public void test6() throws Exception {
-        verifyRecurType("FREQ=YEARLY",
-                /* int freq */         EventRecurrence.YEARLY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      null,
-                /* int[] bydayNum */   null,
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    @SmallTest
-    public void test7() throws Exception {
-        // with an until
-        verifyRecurType("FREQ=DAILY;UNTIL=112233T223344Z",
-                /* int freq */         EventRecurrence.DAILY,
-                /* String until */     "112233T223344Z",
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      null,
-                /* int[] bydayNum */   null,
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    @SmallTest
-    public void test8() throws Exception {
-        // with a count
-        verifyRecurType("FREQ=DAILY;COUNT=334",
-                /* int freq */         EventRecurrence.DAILY,
-                /* String until */     null,
-                /* int count */        334,
-                /* int interval */     0,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      null,
-                /* int[] bydayNum */   null,
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    @SmallTest
-    public void test9() throws Exception {
-        // with a count
-        verifyRecurType("FREQ=DAILY;INTERVAL=5000",
-                /* int freq */         EventRecurrence.DAILY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     5000,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      null,
-                /* int[] bydayNum */   null,
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    @SmallTest
-    public void test10() throws Exception {
-        // verifyRecurType all of the BY* ones with one element
-        verifyRecurType("FREQ=DAILY"
-                + ";BYSECOND=0"
-                + ";BYMINUTE=1"
-                + ";BYHOUR=2"
-                + ";BYMONTHDAY=30"
-                + ";BYYEARDAY=300"
-                + ";BYWEEKNO=53"
-                + ";BYMONTH=12"
-                + ";BYSETPOS=-15"
-                + ";WKST=SU",
-                /* int freq */         EventRecurrence.DAILY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   new int[]{0},
-                /* int[] byminute */   new int[]{1},
-                /* int[] byhour */     new int[]{2},
-                /* int[] byday */      null,
-                /* int[] bydayNum */   null,
-                /* int[] bymonthday */ new int[]{30},
-                /* int[] byyearday */  new int[]{300},
-                /* int[] byweekno */   new int[]{53},
-                /* int[] bymonth */    new int[]{12},
-                /* int[] bysetpos */   new int[]{-15},
-                /* int wkst */         EventRecurrence.SU
-        );
-    }
-
-    @SmallTest
-    public void test11() throws Exception {
-        // verifyRecurType all of the BY* ones with one element
-        verifyRecurType("FREQ=DAILY"
-                + ";BYSECOND=0,30,59"
-                + ";BYMINUTE=0,41,59"
-                + ";BYHOUR=0,4,23"
-                + ";BYMONTHDAY=-31,-1,1,31"
-                + ";BYYEARDAY=-366,-1,1,366"
-                + ";BYWEEKNO=-53,-1,1,53"
-                + ";BYMONTH=1,12"
-                + ";BYSETPOS=1,2,3,4,500,10000"
-                + ";WKST=SU",
-                /* int freq */         EventRecurrence.DAILY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   new int[]{0, 30, 59},
-                /* int[] byminute */   new int[]{0, 41, 59},
-                /* int[] byhour */     new int[]{0, 4, 23},
-                /* int[] byday */      null,
-                /* int[] bydayNum */   null,
-                /* int[] bymonthday */ new int[]{-31, -1, 1, 31},
-                /* int[] byyearday */  new int[]{-366, -1, 1, 366},
-                /* int[] byweekno */   new int[]{-53, -1, 1, 53},
-                /* int[] bymonth */    new int[]{1, 12},
-                /* int[] bysetpos */   new int[]{1, 2, 3, 4, 500, 10000},
-                /* int wkst */         EventRecurrence.SU
-        );
-    }
-
-    private static class Check {
-        Check(String k, int... v) {
-            key = k;
-            values = v;
-        }
-
-        String key;
-        int[] values;
-    }
-
-    // this is a negative verifyRecurType case to verifyRecurType the range of the numbers accepted
-    @SmallTest
-    public void test12() throws Exception {
-        Check[] checks = new Check[]{
-                new Check("BYSECOND", -100, -1, 60, 100),
-                new Check("BYMINUTE", -100, -1, 60, 100),
-                new Check("BYHOUR", -100, -1, 24, 100),
-                new Check("BYMONTHDAY", -100, -32, 0, 32, 100),
-                new Check("BYYEARDAY", -400, -367, 0, 367, 400),
-                new Check("BYWEEKNO", -100, -54, 0, 54, 100),
-                new Check("BYMONTH", -100, -5, 0, 13, 100)
-        };
-
-        for (Check ck : checks) {
-            for (int n : ck.values) {
-                String recur = "FREQ=DAILY;" + ck.key + "=" + n;
-                try {
-                    EventRecurrence er = new EventRecurrence();
-                    er.parse(recur);
-                    fail("Negative verifyRecurType failed. "
-                            + " parse failed to throw an exception for '"
-                            + recur + "'");
-                } catch (EventRecurrence.InvalidFormatException e) {
-                    // expected
-                }
-            }
-        }
-    }
-
-    // verifyRecurType BYDAY
-    @SmallTest
-    public void test13() throws Exception {
-        verifyRecurType("FREQ=DAILY;BYDAY=1SU,-2MO,+33TU,WE,TH,FR,SA",
-                /* int freq */         EventRecurrence.DAILY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      new int[] {
-                        EventRecurrence.SU,
-                        EventRecurrence.MO,
-                        EventRecurrence.TU,
-                        EventRecurrence.WE,
-                        EventRecurrence.TH,
-                        EventRecurrence.FR,
-                        EventRecurrence.SA
-                },
-                /* int[] bydayNum */   new int[]{1, -2, 33, 0, 0, 0, 0},
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    @Suppress
-    // Repro bug #2331761 - this should fail because of the last comma into BYDAY
-    public void test14() throws Exception {
-        verifyRecurType("FREQ=WEEKLY;WKST=MO;UNTIL=20100129T130000Z;INTERVAL=1;BYDAY=MO,TU,WE,",
-                /* int freq */         EventRecurrence.WEEKLY,
-                /* String until */     "20100129T130000Z",
-                /* int count */        0,
-                /* int interval */     1,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      new int[] {
-                        EventRecurrence.MO,
-                        EventRecurrence.TU,
-                        EventRecurrence.WE,
-                },
-                /* int[] bydayNum */   new int[]{0, 0, 0},
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    // This test should pass
-    public void test15() throws Exception {
-        verifyRecurType("FREQ=WEEKLY;WKST=MO;UNTIL=20100129T130000Z;INTERVAL=1;"
-                + "BYDAY=MO,TU,WE,TH,FR,SA,SU",
-                /* int freq */         EventRecurrence.WEEKLY,
-                /* String until */     "20100129T130000Z",
-                /* int count */        0,
-                /* int interval */     1,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      new int[] {
-                        EventRecurrence.MO,
-                        EventRecurrence.TU,
-                        EventRecurrence.WE,
-                        EventRecurrence.TH,
-                        EventRecurrence.FR,
-                        EventRecurrence.SA,
-                        EventRecurrence.SU
-                },
-                /* int[] bydayNum */   new int[]{0, 0, 0, 0, 0, 0, 0},
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    // Sample coming from RFC2445
-    public void test16() throws Exception {
-        verifyRecurType("FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1",
-                /* int freq */         EventRecurrence.MONTHLY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      new int[] {
-                        EventRecurrence.MO,
-                        EventRecurrence.TU,
-                        EventRecurrence.WE,
-                        EventRecurrence.TH,
-                        EventRecurrence.FR
-                },
-                /* int[] bydayNum */   new int[] {0, 0, 0, 0, 0},
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   new int[] { -1 },
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    // Sample coming from RFC2445
-    public void test17() throws Exception {
-        verifyRecurType("FREQ=DAILY;COUNT=10;INTERVAL=2",
-                /* int freq */         EventRecurrence.DAILY,
-                /* String until */     null,
-                /* int count */        10,
-                /* int interval */     2,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      null,
-                /* int[] bydayNum */   null,
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    // Sample coming from RFC2445
-    public void test18() throws Exception {
-        verifyRecurType("FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10",
-                /* int freq */         EventRecurrence.YEARLY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      new int[] {
-                        EventRecurrence.SU
-                },
-                /* int[] bydayNum */   new int[] { -1 },
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    new int[] { 10 },
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    // Sample coming from bug #1640517
-    public void test19() throws Exception {
-        verifyRecurType("FREQ=YEARLY;BYMONTH=3;BYDAY=TH",
-                /* int freq */         EventRecurrence.YEARLY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      new int[] {
-                        EventRecurrence.TH
-                },
-                /* int[] bydayNum */   new int[] { 0 },
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    new int[] { 3 },
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    // for your copying pleasure
-    public void fakeTestXX() throws Exception {
-        verifyRecurType("FREQ=DAILY;",
-                /* int freq */         EventRecurrence.DAILY,
-                /* String until */     null,
-                /* int count */        0,
-                /* int interval */     0,
-                /* int[] bysecond */   null,
-                /* int[] byminute */   null,
-                /* int[] byhour */     null,
-                /* int[] byday */      null,
-                /* int[] bydayNum */   null,
-                /* int[] bymonthday */ null,
-                /* int[] byyearday */  null,
-                /* int[] byweekno */   null,
-                /* int[] bymonth */    null,
-                /* int[] bysetpos */   null,
-                /* int wkst */         EventRecurrence.MO
-        );
-    }
-
-    private static void cmp(int vlen, int[] v, int[] correct, String name) {
-        if ((correct == null && v != null)
-                || (correct != null && v == null)) {
-            throw new RuntimeException("One is null, one isn't for " + name
-                    + ": correct=" + Arrays.toString(correct)
-                    + " actual=" + Arrays.toString(v));
-        }
-        if ((correct == null && vlen != 0)
-                || (vlen != (correct == null ? 0 : correct.length))) {
-            throw new RuntimeException("Reported length mismatch for " + name
-                    + ": correct=" + ((correct == null) ? "null" : correct.length)
-                    + " actual=" + vlen);
-        }
-        if (correct == null) {
-            return;
-        }
-        if (v.length < correct.length) {
-            throw new RuntimeException("Array length mismatch for " + name
-                    + ": correct=" + Arrays.toString(correct)
-                    + " actual=" + Arrays.toString(v));
-        }
-        for (int i = 0; i < correct.length; i++) {
-            if (v[i] != correct[i]) {
-                throw new RuntimeException("Array value mismatch for " + name
-                        + ": correct=" + Arrays.toString(correct)
-                        + " actual=" + Arrays.toString(v));
-            }
-        }
-    }
-
-    private static boolean eq(String a, String b) {
-        if ((a == null && b != null) || (a != null && b == null)) {
-            return false;
-        } else {
-            return a == b || a.equals(b);
-        }
-    }
-
-    private static void verifyRecurType(String recur,
-            int freq, String until, int count, int interval,
-            int[] bysecond, int[] byminute, int[] byhour,
-            int[] byday, int[] bydayNum, int[] bymonthday,
-            int[] byyearday, int[] byweekno, int[] bymonth,
-            int[] bysetpos, int wkst) {
-        EventRecurrence eventRecurrence = new EventRecurrence();
-        eventRecurrence.parse(recur);
-        if (eventRecurrence.freq != freq
-                || !eq(eventRecurrence.until, until)
-                || eventRecurrence.count != count
-                || eventRecurrence.interval != interval
-                || eventRecurrence.wkst != wkst) {
-            System.out.println("Error... got:");
-            print(eventRecurrence);
-            System.out.println("expected:");
-            System.out.println("{");
-            System.out.println("    freq=" + freq);
-            System.out.println("    until=" + until);
-            System.out.println("    count=" + count);
-            System.out.println("    interval=" + interval);
-            System.out.println("    wkst=" + wkst);
-            System.out.println("    bysecond=" + Arrays.toString(bysecond));
-            System.out.println("    byminute=" + Arrays.toString(byminute));
-            System.out.println("    byhour=" + Arrays.toString(byhour));
-            System.out.println("    byday=" + Arrays.toString(byday));
-            System.out.println("    bydayNum=" + Arrays.toString(bydayNum));
-            System.out.println("    bymonthday=" + Arrays.toString(bymonthday));
-            System.out.println("    byyearday=" + Arrays.toString(byyearday));
-            System.out.println("    byweekno=" + Arrays.toString(byweekno));
-            System.out.println("    bymonth=" + Arrays.toString(bymonth));
-            System.out.println("    bysetpos=" + Arrays.toString(bysetpos));
-            System.out.println("}");
-            throw new RuntimeException("Mismatch in fields");
-        }
-        cmp(eventRecurrence.bysecondCount, eventRecurrence.bysecond, bysecond, "bysecond");
-        cmp(eventRecurrence.byminuteCount, eventRecurrence.byminute, byminute, "byminute");
-        cmp(eventRecurrence.byhourCount, eventRecurrence.byhour, byhour, "byhour");
-        cmp(eventRecurrence.bydayCount, eventRecurrence.byday, byday, "byday");
-        cmp(eventRecurrence.bydayCount, eventRecurrence.bydayNum, bydayNum, "bydayNum");
-        cmp(eventRecurrence.bymonthdayCount, eventRecurrence.bymonthday, bymonthday, "bymonthday");
-        cmp(eventRecurrence.byyeardayCount, eventRecurrence.byyearday, byyearday, "byyearday");
-        cmp(eventRecurrence.byweeknoCount, eventRecurrence.byweekno, byweekno, "byweekno");
-        cmp(eventRecurrence.bymonthCount, eventRecurrence.bymonth, bymonth, "bymonth");
-        cmp(eventRecurrence.bysetposCount, eventRecurrence.bysetpos, bysetpos, "bysetpos");
-    }
-
-    private static void print(EventRecurrence er) {
-        System.out.println("{");
-        System.out.println("    freq=" + er.freq);
-        System.out.println("    until=" + er.until);
-        System.out.println("    count=" + er.count);
-        System.out.println("    interval=" + er.interval);
-        System.out.println("    wkst=" + er.wkst);
-        System.out.println("    bysecond=" + Arrays.toString(er.bysecond));
-        System.out.println("    bysecondCount=" + er.bysecondCount);
-        System.out.println("    byminute=" + Arrays.toString(er.byminute));
-        System.out.println("    byminuteCount=" + er.byminuteCount);
-        System.out.println("    byhour=" + Arrays.toString(er.byhour));
-        System.out.println("    byhourCount=" + er.byhourCount);
-        System.out.println("    byday=" + Arrays.toString(er.byday));
-        System.out.println("    bydayNum=" + Arrays.toString(er.bydayNum));
-        System.out.println("    bydayCount=" + er.bydayCount);
-        System.out.println("    bymonthday=" + Arrays.toString(er.bymonthday));
-        System.out.println("    bymonthdayCount=" + er.bymonthdayCount);
-        System.out.println("    byyearday=" + Arrays.toString(er.byyearday));
-        System.out.println("    byyeardayCount=" + er.byyeardayCount);
-        System.out.println("    byweekno=" + Arrays.toString(er.byweekno));
-        System.out.println("    byweeknoCount=" + er.byweeknoCount);
-        System.out.println("    bymonth=" + Arrays.toString(er.bymonth));
-        System.out.println("    bymonthCount=" + er.bymonthCount);
-        System.out.println("    bysetpos=" + Arrays.toString(er.bysetpos));
-        System.out.println("    bysetposCount=" + er.bysetposCount);
-        System.out.println("}");
-    }
-
-
-    /** A list of valid rules.  The parser must accept these. */
-    private static final String[] GOOD_RRULES = {
-        /* extracted wholesale from from RFC 2445 section 4.8.5.4 */
-        "FREQ=DAILY;COUNT=10",
-        "FREQ=DAILY;UNTIL=19971224T000000Z",
-        "FREQ=DAILY;INTERVAL=2",
-        "FREQ=DAILY;INTERVAL=10;COUNT=5",
-        "FREQ=YEARLY;UNTIL=20000131T090000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA",
-        "FREQ=DAILY;UNTIL=20000131T090000Z;BYMONTH=1",
-        "FREQ=WEEKLY;COUNT=10",
-        "FREQ=WEEKLY;UNTIL=19971224T000000Z",
-        "FREQ=WEEKLY;INTERVAL=2;WKST=SU",
-        "FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH",
-        "FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH",
-        "FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;BYDAY=MO,WE,FR",
-        "FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH",
-        "FREQ=MONTHLY;COUNT=10;BYDAY=1FR",
-        "FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR",
-        "FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU",
-        "FREQ=MONTHLY;COUNT=6;BYDAY=-2MO",
-        "FREQ=MONTHLY;BYMONTHDAY=-3",
-        "FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15",
-        "FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1",
-        "FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15",
-        "FREQ=MONTHLY;INTERVAL=2;BYDAY=TU",
-        "FREQ=YEARLY;COUNT=10;BYMONTH=6,7",
-        "FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3",
-        "FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200",
-        "FREQ=YEARLY;BYDAY=20MO",
-        "FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO",
-        "FREQ=YEARLY;BYMONTH=3;BYDAY=TH",
-        "FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8",
-        "FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13",
-        "FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13",
-        "FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8",
-        "FREQ=MONTHLY;COUNT=3;BYDAY=TU,WE,TH;BYSETPOS=3",
-        "FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-2",
-        "FREQ=HOURLY;INTERVAL=3;UNTIL=19970902T170000Z",
-        "FREQ=MINUTELY;INTERVAL=15;COUNT=6",
-        "FREQ=MINUTELY;INTERVAL=90;COUNT=4",
-        "FREQ=DAILY;BYHOUR=9,10,11,12,13,14,15,16;BYMINUTE=0,20,40",
-        "FREQ=MINUTELY;INTERVAL=20;BYHOUR=9,10,11,12,13,14,15,16",
-        "FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=MO",
-        "FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=SU",
-        /* a few more */
-        "FREQ=SECONDLY;BYSECOND=0,15,59",
-        "FREQ=MINUTELY;BYMINUTE=0,15,59",
-        "FREQ=HOURLY;BYHOUR=+0,+15,+23",
-        "FREQ=DAILY;X-WHATEVER=blah",                       // fails on old parser
-        //"freq=daily;wkst=su",                               // fails on old parser
-    };
-
-    /** The parser must reject these. */
-    private static final String[] BAD_RRULES = {
-        "INTERVAL=4;FREQ=YEARLY",                           // FREQ must come first
-        "FREQ=MONTHLY;FREQ=MONTHLY",                        // can't specify twice
-        "FREQ=MONTHLY;COUNT=1;COUNT=1",                     // can't specify twice
-        "FREQ=SECONDLY;BYSECOND=60",                        // range
-        "FREQ=MINUTELY;BYMINUTE=-1",                        // range
-        "FREQ=HOURLY;BYHOUR=24",                            // range
-        "FREQ=YEARLY;BYMONTHDAY=0",                         // zero not valid
-        //"FREQ=YEARLY;COUNT=1;UNTIL=12345",                  // can't have both COUNT and UNTIL
-        //"FREQ=DAILY;UNTIL=19970829T021400e",                // invalid date
-    };
-
-    /**
-     * Simple test of good/bad rules.
-     */
-    @SmallTest
-    public void testBasicParse() {
-        for (String rule : GOOD_RRULES) {
-            EventRecurrence recur = new EventRecurrence();
-            recur.parse(rule);
-        }
-
-        for (String rule : BAD_RRULES) {
-            EventRecurrence recur = new EventRecurrence();
-            boolean didThrow = false;
-
-            try {
-                recur.parse(rule);
-            } catch (InvalidFormatException ife) {
-                didThrow = true;
-            }
-
-            assertTrue("Expected throw on " + rule, didThrow);
-        }
-    }
-}
diff --git a/core/tests/coretests/src/android/pim/RecurrenceSetTest.java b/core/tests/coretests/src/android/pim/RecurrenceSetTest.java
deleted file mode 100644
index e5ab179..0000000
--- a/core/tests/coretests/src/android/pim/RecurrenceSetTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2009 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.pim;
-
-import android.content.ContentValues;
-import android.pim.ICalendar;
-import android.pim.RecurrenceSet;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-import android.provider.CalendarContract;
-import junit.framework.TestCase;
-
-/**
- * Test some pim.RecurrenceSet functionality.
- */
-public class RecurrenceSetTest extends TestCase {
-
-    // Test a recurrence
-    @SmallTest
-    public void testRecurrenceSet0() throws Exception {
-        String recurrence = "DTSTART;TZID=America/New_York:20080221T070000\n"
-                + "DTEND;TZID=America/New_York:20080221T190000\n"
-                + "RRULE:FREQ=DAILY;UNTIL=20080222T000000Z\n"
-                + "EXDATE:20080222T120000Z";
-        verifyPopulateContentValues(recurrence, "FREQ=DAILY;UNTIL=20080222T000000Z", null,
-                null, "20080222T120000Z", 1203595200000L, "America/New_York", "P43200S", 0);
-    }
-
-    // Test 1 day all-day event
-    @SmallTest
-    public void testRecurrenceSet1() throws Exception {
-        String recurrence = "DTSTART;VALUE=DATE:20090821\nDTEND;VALUE=DATE:20090822\n"
-                + "RRULE:FREQ=YEARLY;WKST=SU";
-        verifyPopulateContentValues(recurrence, "FREQ=YEARLY;WKST=SU", null,
-                null, null, 1250812800000L, "UTC", "P1D", 1);
-    }
-
-    // Test 2 day all-day event
-    @SmallTest
-    public void testRecurrenceSet2() throws Exception {
-        String recurrence = "DTSTART;VALUE=DATE:20090821\nDTEND;VALUE=DATE:20090823\n"
-                + "RRULE:FREQ=YEARLY;WKST=SU";
-        verifyPopulateContentValues(recurrence, "FREQ=YEARLY;WKST=SU", null,
-                null, null, 1250812800000L, "UTC",  "P2D", 1);
-    }
-
-    // run populateContentValues and verify the results
-    private void verifyPopulateContentValues(String recurrence, String rrule, String rdate,
-            String exrule, String exdate, long dtstart, String tzid, String duration, int allDay)
-            throws ICalendar.FormatException {
-        ICalendar.Component recurrenceComponent =
-                new ICalendar.Component("DUMMY", null /* parent */);
-        ICalendar.parseComponent(recurrenceComponent, recurrence);
-        ContentValues values = new ContentValues();
-        RecurrenceSet.populateContentValues(recurrenceComponent, values);
-        Log.d("KS", "values " + values);
-
-        assertEquals(rrule, values.get(android.provider.CalendarContract.Events.RRULE));
-        assertEquals(rdate, values.get(android.provider.CalendarContract.Events.RDATE));
-        assertEquals(exrule, values.get(android.provider.CalendarContract.Events.EXRULE));
-        assertEquals(exdate, values.get(android.provider.CalendarContract.Events.EXDATE));
-        assertEquals(dtstart, (long) values.getAsLong(CalendarContract.Events.DTSTART));
-        assertEquals(tzid, values.get(android.provider.CalendarContract.Events.EVENT_TIMEZONE));
-        assertEquals(duration, values.get(android.provider.CalendarContract.Events.DURATION));
-        assertEquals(allDay,
-                (int) values.getAsInteger(android.provider.CalendarContract.Events.ALL_DAY));
-    }
-}
diff --git a/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java b/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
index aedfbad..2ed7c52 100644
--- a/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
+++ b/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
@@ -95,7 +95,7 @@
     private WebView mWebView;
 
     /** Used for caching the default bindings so they can be restored. */
-    private String mDefaultKeyBindings;
+    private static String sDefaultKeyBindings;
 
     /** The received selection string for assertion checking. */
     private static String sReceivedSelectionString = SELECTION_STRING_UNKNOWN;
@@ -1696,7 +1696,7 @@
      */
     private void injectTestWebContentKeyBindings() {
         ContentResolver contentResolver = getActivity().getContentResolver();
-        mDefaultKeyBindings = Settings.Secure.getString(contentResolver,
+        sDefaultKeyBindings = Settings.Secure.getString(contentResolver,
                 Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS);
         Settings.Secure.putString(contentResolver,
                 Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS, TEST_KEY_DINDINGS);
@@ -1708,7 +1708,7 @@
     private void restoreDefaultWebContentKeyBindings() {
         Settings.Secure.putString(getActivity().getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS,
-                mDefaultKeyBindings);
+                sDefaultKeyBindings);
     }
 
     /**
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index d8d145c..c54e4a1 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -16,22 +16,25 @@
 
 package android.widget;
 
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
+import com.android.frameworks.coretests.R;
 
-import android.test.AndroidTestCase;
+import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.GetChars;
-import android.widget.TextView;
+import android.view.View;
 
 /**
  * TextViewTest tests {@link TextView}.
  */
-public class TextViewTest extends AndroidTestCase {
+public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewTestActivity> {
+
+    public TextViewTest() {
+        super(TextViewTestActivity.class);
+    }
 
     @SmallTest
     public void testArray() throws Exception {
-        TextView tv = new TextView(mContext);
+        TextView tv = new TextView(getActivity());
 
         char[] c = new char[] { 'H', 'e', 'l', 'l', 'o', ' ',
                                 'W', 'o', 'r', 'l', 'd', '!' };
@@ -58,4 +61,192 @@
         assertEquals('o', c2[4]);
         assertEquals('\0', c2[5]);
     }
+
+    @SmallTest
+    public void testTextDirectionDefault() {
+        TextView tv = new TextView(getActivity());
+        assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getTextDirection());
+    }
+
+    @SmallTest
+    public void testSetGetTextDirection() {
+        TextView tv = new TextView(getActivity());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
+    }
+
+    @SmallTest
+    public void testGetResolvedTextDirectionLtr() {
+        TextView tv = new TextView(getActivity());
+        tv.setText("this is a test");
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+    }
+
+    @SmallTest
+    public void testGetResolvedTextDirectionLtrWithInheritance() {
+        LinearLayout ll = new LinearLayout(getActivity());
+        ll.setTextDirection(View.TEXT_DIRECTION_RTL);
+
+        TextView tv = new TextView(getActivity());
+        tv.setText("this is a test");
+        ll.addView(tv);
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+    }
+
+    @SmallTest
+    public void testGetResolvedTextDirectionRtl() {
+        TextView tv = new TextView(getActivity());
+        tv.setText("\u05DD\u05DE"); // hebrew
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+    }
+
+    @SmallTest
+    public void testGetResolvedTextDirectionRtlWithInheritance() {
+        LinearLayout ll = new LinearLayout(getActivity());
+
+        TextView tv = new TextView(getActivity());
+        tv.setText("\u05DD\u05DE"); // hebrew
+        ll.addView(tv);
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        // Force to RTL text direction on the layout
+        ll.setTextDirection(View.TEXT_DIRECTION_RTL);
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+    }
+
+    @SmallTest
+    public void testCharCountHeuristic() {
+        LinearLayout ll = new LinearLayout(getActivity());
+        ll.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
+
+        TextView tv = new TextView(getActivity());
+        ll.addView(tv);
+
+        tv.setTextDirection(View.TEXT_DIRECTION_CHAR_COUNT);
+        tv.setText("this is a test");
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+         // resetResolvedTextDirection is not part of the public API so simply use setTextDirection
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        tv.setTextDirection(View.TEXT_DIRECTION_CHAR_COUNT);
+        tv.setText("\u05DD\u05DE"); // hebrew
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        tv.setTextDirection(View.TEXT_DIRECTION_CHAR_COUNT);
+        tv.setText("this is a test \u05DD\u05DE"); // latin more than 60% + hebrew
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        tv.setTextDirection(View.TEXT_DIRECTION_CHAR_COUNT);
+        tv.setText("t \u05DD\u05DE"); // latin + hebrew more than 60%
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        tv.setTextDirection(View.TEXT_DIRECTION_CHAR_COUNT);
+        tv.setText("ab \u05DD\u05DE"); // latin + hebrew at 50% each
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+    }
+
+    @SmallTest
+    public void testResetTextDirection() {
+        final TextViewTestActivity activity = getActivity();
+
+        final LinearLayout ll = (LinearLayout) activity.findViewById(R.id.textviewtest_layout);
+        final TextView tv = (TextView) activity.findViewById(R.id.textviewtest_textview);
+
+        getActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+                assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+                assertEquals(true, tv.isResolvedTextDirection());
+
+                ll.removeView(tv);
+                assertEquals(false, tv.isResolvedTextDirection());
+            }
+        });
+    }
 }
diff --git a/core/tests/coretests/src/android/widget/TextViewTestActivity.java b/core/tests/coretests/src/android/widget/TextViewTestActivity.java
new file mode 100644
index 0000000..1bb4d24
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/TextViewTestActivity.java
@@ -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.
+ */
+package android.widget;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.frameworks.coretests.R;
+
+public class TextViewTestActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.textview_test);
+    }
+}
diff --git a/core/tests/notificationtests/Android.mk b/core/tests/notificationtests/Android.mk
new file mode 100644
index 0000000..be2e6bf
--- /dev/null
+++ b/core/tests/notificationtests/Android.mk
@@ -0,0 +1,16 @@
+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 := NotificationStressTests
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/tests/notificationtests/AndroidManifest.xml b/core/tests/notificationtests/AndroidManifest.xml
new file mode 100644
index 0000000..51e530a
--- /dev/null
+++ b/core/tests/notificationtests/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?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.notification.tests" >
+
+    <application >
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.notification.tests"
+        android:label="Notification Stress Tests" />
+
+</manifest>
diff --git a/core/tests/notificationtests/src/android/app/NotificationStressTest.java b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
new file mode 100644
index 0000000..52ea1c4
--- /dev/null
+++ b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.app;
+
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.test.InstrumentationTestCase;
+import android.test.RepetitiveTest;
+import android.test.TimedTest;
+
+import java.util.Random;
+
+/**
+ * Test which spams notification manager with a large number of notifications, for both stress and
+ * performance testing.
+ */
+public class NotificationStressTest extends InstrumentationTestCase {
+
+    private static final int NUM_ITERATIONS = 200;
+    private static final int[] ICONS = new int[] {
+        android.R.drawable.stat_notify_call_mute,
+        android.R.drawable.stat_notify_chat,
+        android.R.drawable.stat_notify_error,
+        android.R.drawable.stat_notify_missed_call,
+        android.R.drawable.stat_notify_more,
+        android.R.drawable.stat_notify_sdcard,
+        android.R.drawable.stat_notify_sdcard_prepare,
+        android.R.drawable.stat_notify_sdcard_usb,
+        android.R.drawable.stat_notify_sync,
+        android.R.drawable.stat_notify_sync_noanim,
+        android.R.drawable.stat_notify_voicemail,
+    };
+
+    private final Random mRandom = new Random();
+    private Context mContext;
+    private NotificationManager mNotificationManager;
+    private int notifyId = 0;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getInstrumentation().getContext();
+        mNotificationManager = (NotificationManager) mContext.getSystemService(
+                Context.NOTIFICATION_SERVICE);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        mNotificationManager.cancelAll();
+    }
+
+    @RepetitiveTest(numIterations=NUM_ITERATIONS)
+    public void testNotificationStress() {
+        // Cancel one of every five notifications to vary load on notification manager
+        if (notifyId % 5 == 4) {
+            mNotificationManager.cancel(notifyId - 4);
+        }
+        sendNotification(notifyId++, "testNotificationStressNotify");
+    }
+
+    private void sendNotification(int id, CharSequence text) {
+        // Create "typical" notification with random icon
+        Notification notification = new Notification(ICONS[mRandom.nextInt(ICONS.length)], text,
+                System.currentTimeMillis());
+        // Fill in arbitrary content
+        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
+        PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
+        CharSequence title = text + " " + id;
+        CharSequence subtitle = String.valueOf(System.currentTimeMillis());
+        notification.setLatestEventInfo(mContext, title, subtitle, pendingIntent);
+        mNotificationManager.notify(id, notification);
+        SystemClock.sleep(10);
+    }
+}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index b9c0d80..0b8d40f 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -84,6 +84,16 @@
         <group gid="diag" />
     </permission>
 
+    <!-- Group that can read detailed network usage statistics -->
+    <permission name="android.permission.READ_NETWORK_USAGE_HISTORY">
+        <group gid="net_bw_stats" />
+    </permission>
+
+    <!-- Group that can modify how network statistics are accounted -->
+    <permission name="android.permission.MODIFY_NETWORK_ACCOUNTING">
+        <group gid="net_bw_acct" />
+    </permission>
+
     <!-- ================================================================== -->
     <!-- ================================================================== -->
     <!-- ================================================================== -->
diff --git a/data/fonts/DroidSansEthiopic-Bold.ttf b/data/fonts/DroidSansEthiopic-Bold.ttf
index 0d4500c..e06cac2 100644
--- a/data/fonts/DroidSansEthiopic-Bold.ttf
+++ b/data/fonts/DroidSansEthiopic-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidSansEthiopic-Regular.ttf b/data/fonts/DroidSansEthiopic-Regular.ttf
index dd88aa1..0adcbbe 100644
--- a/data/fonts/DroidSansEthiopic-Regular.ttf
+++ b/data/fonts/DroidSansEthiopic-Regular.ttf
Binary files differ
diff --git a/data/fonts/DroidSansHebrew-Bold.ttf b/data/fonts/DroidSansHebrew-Bold.ttf
new file mode 100644
index 0000000..c1acb38
--- /dev/null
+++ b/data/fonts/DroidSansHebrew-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidSansHebrew-Regular.ttf b/data/fonts/DroidSansHebrew-Regular.ttf
new file mode 100644
index 0000000..af6a58d
--- /dev/null
+++ b/data/fonts/DroidSansHebrew-Regular.ttf
Binary files differ
diff --git a/data/fonts/DroidSansHebrew.ttf b/data/fonts/DroidSansHebrew.ttf
deleted file mode 100644
index 8d77e3e..0000000
--- a/data/fonts/DroidSansHebrew.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index 692ce34..d222c0b 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -18,7 +18,8 @@
     frameworks/base/data/fonts/DroidSans.ttf:system/fonts/DroidSans.ttf \
     frameworks/base/data/fonts/DroidSans-Bold.ttf:system/fonts/DroidSans-Bold.ttf \
     frameworks/base/data/fonts/DroidSansArabic.ttf:system/fonts/DroidSansArabic.ttf \
-    frameworks/base/data/fonts/DroidSansHebrew.ttf:system/fonts/DroidSansHebrew.ttf \
+    frameworks/base/data/fonts/DroidSansHebrew-Regular.ttf:system/fonts/DroidSansHebrew-Regular.ttf \
+    frameworks/base/data/fonts/DroidSansHebrew-Bold.ttf:system/fonts/DroidSansHebrew-Bold.ttf \
     frameworks/base/data/fonts/DroidSansThai.ttf:system/fonts/DroidSansThai.ttf \
     frameworks/base/data/fonts/DroidSerif-Regular.ttf:system/fonts/DroidSerif-Regular.ttf \
     frameworks/base/data/fonts/DroidSerif-Bold.ttf:system/fonts/DroidSerif-Bold.ttf \
diff --git a/docs/html/guide/developing/device.jd b/docs/html/guide/developing/device.jd
index 3127e10..cb5a0b6 100644
--- a/docs/html/guide/developing/device.jd
+++ b/docs/html/guide/developing/device.jd
@@ -145,6 +145,9 @@
     <td>Kyocera</td>
     <td><code>0482</code></td></tr>
   <tr>
+    <td>Lenevo</td>
+    <td><code>17EF</code></td></tr>
+  <tr>
     <td>LG</td>
     <td><code>1004</code></td></tr>
   <tr>
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index abea85b..3ec174e 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -222,7 +222,8 @@
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/service-element.html">&lt;service&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-gl-texture-element.html">&lt;supports-gl-texture&gt;</a></li> 
-          <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></li>  <!-- ##api level 4## -->
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a>
+              <span class="new">updated</span></li>  <!-- ##api level 4## -->
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a></li> <!-- ##api level 4## -->
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></li>
@@ -256,7 +257,7 @@
 	        <div><a href="<?cs var:toroot ?>guide/topics/renderscript/index.html">
 	            <span class="en">RenderScript</span>
 	          </a>
-	          <span class="new-child">new!</span></div>
+	          <span class="new">new!</span></div>
 	        <ul>
 	          <li><a href="<?cs var:toroot ?>guide/topics/renderscript/graphics.html">
 	                <span class="en">3D Graphics</span>
diff --git a/docs/html/guide/publishing/publishing.jd b/docs/html/guide/publishing/publishing.jd
index 0cbba53..95d89fa 100644
--- a/docs/html/guide/publishing/publishing.jd
+++ b/docs/html/guide/publishing/publishing.jd
@@ -23,6 +23,7 @@
   <ol>
     <li><a href="#OpeningDetails">Opening an app's details page</a></li>
     <li><a href="#PerformingSearch">Performing a search</a></li>
+    <li><a href="#BuildaButton">Build an Android Market button</a></li>
     <li><a href="#UriSummary">Summary of URI formats</a></li>
   </ol>  
 </li>
@@ -317,6 +318,205 @@
 
 
 
+<h3 id="BuildaButton">Build an Android Market button</h3>
+
+<p>Use the following form to input either your application's package name or your publisher name
+and generate a button that you can use on your web site. The button will take users to Android
+Market to view your application details or view a list of all applications you've published.</p>
+
+<p>This form offers four versions of the official "Available in Android Market" badge at
+recommended sizes. If you would like to create a different size, you can download an EPS file for
+the badges from the <a href="http://www.android.com/branding.html">Android Brand Guidelines</a>.</p>
+
+<style type="text/css">
+  
+form.button-form {
+  margin-top:2em;
+}
+
+/* the label and input elements are blocks that float left in order to
+   keep the left edgets of the input aligned, and IE 6/7 do not fully support "inline-block" */
+label.block {
+  display: block;
+  float: left;
+  width: 100px;
+  padding-right: 10px;
+}
+
+input.text {
+  display: block;
+  float: left;
+  width: 250px;
+}
+
+div.button-row {
+  white-space:nowrap;
+  min-height:80px;
+}
+
+div.button-row input {
+  vertical-align:120%;
+}
+
+#jd-content div.button-row img {
+  margin: 0;
+}
+
+</style>
+
+<script type="text/javascript">
+
+// variables for creating 'try it out' demo button
+var imagePath = "http://www.android.com/images/brand/"
+var linkStart = "<a href=\"http://market.android.com/";
+var imageStart = "\">\n"
+        + "  <img src=\"" + imagePath;
+var imageEnd = ".png\"\n"
+        + "       alt=\"Available in Android Market\" />\n</a>";
+
+// variables for creating code snippet
+var linkStartCode = "&lt;a href=\"http://market.android.com/";
+var imageStartCode = "\"&gt;\n"
+        + "  &lt;img src=\"" + imagePath;
+var imageEndCode = ".png\"\n"
+        + "       alt=\"Available in Android Market\" />\n&lt;/a>";
+
+/** Generate the HTML snippet and demo based on form values */
+function buildButton(form) {
+  if (form["package"].value != "com.android.example") {
+    $("#preview").show();
+    $("#snippet").show().html(linkStartCode + "details?id=" + form["package"].value
+            + imageStartCode + $('form input[type=radio]:checked').val() + imageEndCode);
+    $("#button-preview").html(linkStart + "details?id=" + form["package"].value
+            + imageStart + $('form input[type=radio]:checked').val() + imageEnd);
+  } else if (form["publisher"].value != "Example, Inc.") {
+    $("#preview").show();
+    $("#snippet").show().html(linkStartCode + "search?q=pub:" + form["publisher"].value
+            + imageStartCode + $('form input[type=radio]:checked').val() + imageEndCode);
+    $("#button-preview").html(linkStart + "search?q=pub:" + form["publisher"].value + imageStart +
+    $('form input[type=radio]:checked').val() + imageEnd);
+  } else {
+    alert("Please enter your package name or publisher name");
+  }
+  return false;
+}
+
+/** Listen for Enter key */
+function onTextEntered(event, form, me) {
+  // 13 = enter
+  if (event.keyCode == 13) {
+    buildButton(form);
+  }
+}
+
+/** When input is focused, remove example text and disable other input */
+function onInputFocus(object, example) {
+  if (object.value == example) {
+    $(object).val('').css({'color' : '#000'});
+  }
+  $('input[type="text"]:not(input[name='+object.name+'])',
+          object.parentNode).attr('disabled','true');
+  $('#'+object.name+'-clear').show();
+}
+
+/** When input is blured, restore example text if appropriate and enable other input */
+function onInputBlur(object, example) {
+  if (object.value.length < 1) {
+    $(object).attr('value',example).css({'color':'#ccc'});
+    $('input[type="text"]', object.parentNode).removeAttr('disabled');
+    $('#'+object.name+'-clear').hide();
+  }
+}
+
+/** Clear the form to start over */
+function clearLabel(id, example) {
+  $("#preview").hide();
+  $('#'+id+'').html('').attr('value',example).css({'color':'#ccc'});
+  $('input[type="text"]', $('#'+id+'').parent()).removeAttr('disabled');
+  $('#'+id+'-clear').hide();
+  return false;
+}
+
+/** When the doc is ready, find the inputs and color the input grey if the value is the example
+    text. This is necessary to handle back-navigation, which can auto-fill the form with previous
+    values (and text should not be grey) */
+$(document).ready(function() {
+  $(".button-form input.text").each(function(index) {
+    if ($(this).val() == $(this).attr("default")) {
+      $(this).css("color","#ccc");
+    } else {
+      /* This is necessary to handle back-navigation to the page after form was filled */
+      $('input[type="text"]:not(input[name='+this.name+'])',
+              this.parentNode).attr('disabled','true');
+      $('#'+this.name+'-clear').show();
+    }
+  });
+});
+
+</script>
+
+<form class="button-form">
+  <label class="block" for="package">Package name:</label>
+  <input class="text" type="text" id="package" name="package"
+         value="com.android.example"
+         default="com.android.example"
+         onfocus="onInputFocus(this, 'com.android.example')"
+         onblur="onInputBlur(this, 'com.android.example')"
+         onkeyup="return onTextEntered(event, this.parentNode, this)"/>&nbsp;
+         <a id="package-clear" style="display:none" href="#"
+            onclick="return clearLabel('package','com.android.example');">clear</a>
+  <p style="clear:both;margin:0">&nbsp;<em>or</em></p>
+  <label class="block" style="margin-top:5px" for="publisher">Publisher name:</label>
+  <input class="text" type="text" id="publisher" name="publisher"
+         value="Example, Inc."
+         default="Example, Inc."
+         onfocus="onInputFocus(this, 'Example, Inc.')"
+         onblur="onInputBlur(this, 'Example, Inc.')"
+         onkeyup="return onTextEntered(event, this.parentNode, this)"/>&nbsp;
+         <a id="publisher-clear" style="display:none" href="#"
+            onclick="return clearLabel('publisher','Example, Inc.');">clear</a>
+         <br/><br/>
+
+<div class="button-row">
+  <input type="radio" name="buttonStyle" value="45_avail_market_logo1" id="ns" checked="checked" />
+    <label for="ns"><img src="http://www.android.com/images/brand/45_avail_market_logo1.png"
+alt="narrow and small logo" /></label>
+    &nbsp;&nbsp;&nbsp;&nbsp;
+  <input type="radio" name="buttonStyle" value="60_avail_market_logo1" id="nm" />
+    <label for="nm"><img src="http://www.android.com/images/brand/60_avail_market_logo1.png"
+alt="narrow and large logo" /></label>
+</div>
+
+<div class="button-row">
+  <input type="radio" name="buttonStyle" value="45_avail_market_logo2" id="ws" />
+    <label for="ws"><img src="http://www.android.com/images/brand/45_avail_market_logo2.png"
+alt="wide and small logo" /></label>
+    &nbsp;&nbsp;&nbsp;&nbsp;
+  <input type="radio" name="buttonStyle" value="60_avail_market_logo2" id="wm" />
+    <label for="wm"><img src="http://www.android.com/images/brand/60_avail_market_logo2.png"
+alt="wide and large logo" /></label>
+</div>
+
+  <input type="button" onclick="return buildButton(this.parentNode)" value="Build my button"
+style="padding:5px" />
+  <br/>
+</form>
+
+<div id="preview" style="display:none">
+  <p>Copy and paste this HTML into your web site:</p>
+  <textarea id="snippet" cols="80" rows="4" onclick="this.select()"
+style="font-family:monospace;background-color:#efefef;padding:5px;display:none;margin-bottom:1em">
+  </textarea >
+
+<p>Try it out:</p>
+<div id="button-preview" style="margin-top:1em"></div>
+</div>
+
+
+
+
+
+
 <h3 id="UriSummary">Summary of URI formats</h3>
 
 <p>The table below provides a summary of the URIs currently supported by the Android Market (both on
diff --git a/docs/html/guide/topics/graphics/index.jd b/docs/html/guide/topics/graphics/index.jd
index be1b0fc..2490e39 100644
--- a/docs/html/guide/topics/graphics/index.jd
+++ b/docs/html/guide/topics/graphics/index.jd
@@ -14,13 +14,20 @@
     </ol>
     </li>
   </ol>
+  <h2>See also</h2>
+  <ol>
+    <li><a href="{@docRoot}guide/topics/graphics/opengl.html">3D with OpenGL</a></li>
+    <li><a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a></li>
+  </ol>
   </div>
 </div>
-<p>Android graphics are powered by a custom 2D graphics library and OpenGL ES 1.0
-for high performance 3D graphics. The most common 2D graphics APIs can be found in the 
-{@link android.graphics.drawable drawable package}. OpenGL APIs are available
-from the Khronos {@link javax.microedition.khronos.opengles OpenGL ES package},
-plus some Android {@link android.opengl OpenGL utilities}.</p>
+
+<p>Android graphics are powered by a custom 2D graphics library, and the framework provides
+support for high performance 3D graphics in the form of OpenGL ES and RenderScript. The most
+common 2D graphics APIs can be found in the {@link android.graphics.drawable drawable package}.
+OpenGL APIs are available from the Khronos {@link javax.microedition.khronos.opengles OpenGL ES} and
+the {@link android.opengl} packages. The RenderScript APIs are available in the 
+{@link android.renderscript} package.</p>
 
 <p>When starting a project, it's important to consider exactly what your graphical demands will be. 
 Varying graphical tasks are best accomplished with varying techniques. For example, graphics and animations
@@ -32,10 +39,10 @@
 
 <p>If you're specifically looking for information on drawing 3D graphics, this page won't
 help a lot. However, the information below about how to <a href="#draw-with-canvas">Draw with a
-Canvas</a> (and the section on SurfaceView), 
-will give you a quick idea of how you should draw to the View hierarchy. For more information
-on Android's 3D graphic utilities (provided by the OpenGL ES API), 
-read <a href="opengl.html">3D with OpenGL</a> and refer to other OpenGL documentation.</p>
+Canvas</a> (and the section on SurfaceView), will give you a quick idea of how you should draw to
+the View hierarchy. For more information on Android's 3D graphics APIs, see
+the <a href="opengl.html">3D with OpenGL</a> and  
+<a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> documents.</p>
 
 
 <h2 id="options">Consider your Options</h2>
diff --git a/docs/html/guide/topics/graphics/opengl.jd b/docs/html/guide/topics/graphics/opengl.jd
index 9f88954..cc467f2 100644
--- a/docs/html/guide/topics/graphics/opengl.jd
+++ b/docs/html/guide/topics/graphics/opengl.jd
@@ -3,51 +3,215 @@
 parent.link=index.html
 @jd:body
 
+<div id="qv-wrapper">
+  <div id="qv">
+    <h2>In this document</h2>
+    
+    <ol>
+      <li><a href="#basics">The Basics</a></li>
+      <li><a href="#compatibility">OpenGL Versions and Device Compatibility</a>
+        <ol>
+          <li><a href="#textures">Texture Compression Support</a></li>
+          <li><a href="#declare-compression">Declaring Use of Compressed Textures</a></li>
+        </ol>
+      </li>
+    </ol>
+    <h2>Key classes</h2>
+    <ol>
+      <li>{@link android.opengl.GLSurfaceView}</li>
+      <li>{@link android.opengl.GLSurfaceView.Renderer}</li>
+      <li>{@link javax.microedition.khronos.opengles}</li>
+      <li>{@link android.opengl}</li>
+    </ol>
+    <h2>Related Samples</h2>
+    <ol>
+      <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/
+GLSurfaceViewActivity.html">GLSurfaceViewActivity</a></li>
+      <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/
+GLES20Activity.html">GLES20Activity</a></li>
+      <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/
+TouchRotateActivity.html">TouchRotateActivity</a></li>
+      <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/
+CompressedTextureActivity.html">Compressed Textures</a></li>
+    </ol>
+    <h2>See also</h2>
+    <ol>
+      <li><a href="{@docRoot}resources/articles/glsurfaceview.html">Introducing
+GLSurfaceView</a></li>
+      <li><a href="http://www.khronos.org/opengles/">OpenGL ES</a></li>
+      <li><a href="http://www.khronos.org/opengles/1_X/">OpenGL ES 1.x Specification</a></li>
+      <li><a href="http://www.khronos.org/opengles/2_X/">OpenGL ES 2.x specification</a></li>
+    </ol>
+  </div>
+</div>
 
-<p>Android includes support for high performance 3D graphics 
-via the OpenGL API&mdash;specifically, the OpenGL ES API.</p>
+<p>Android includes support for high performance 2D and 3D graphics with the Open Graphics Library
+(OpenGL) API&mdash;specifically, the OpenGL ES API. OpenGL is a cross-platform graphics API that
+specifies a standard software interface for 3D graphics processing hardware. OpenGL ES is a flavor
+of the OpenGL specification intended for embedded devices. The OpenGL ES 1.0 and 1.1 API
+specifications have been supported since Android 1.0. Beginning with Android 2.2 (API
+Level 8), the framework supports the OpenGL ES 2.0 API specification.</p>
 
-<p>OpenGL ES is a flavor of the OpenGL specification intended for embedded devices. Versions of <a
-href="http://www.khronos.org/opengles/">OpenGL ES</a> are loosely peered to versions of the primary
-OpenGL standard. Beginning with Android 2.2, the platform supports OpenGL ES 2.0 (with
-backward compatibility support for OpenGL ES 1.1). For information about the relative number of
-Android-powered devices that support a given version of OpenGL ES, see the <a
-href="http://developer.android.com/resources/dashboard/opengl.html">OpenGL ES Versions</a>
-dashboard.</p>
+<p class="note"><b>Note:</b> The specific API provided by the Android framework is similar to the
+  J2ME JSR239 OpenGL ES  API, but is not identical. If you are familiar with J2ME JSR239
+  specification, be alert for variations.</p>
 
-<p>The specific API provided by Android is similar to the J2ME JSR239 OpenGL
-ES API. However, it may not be identical, so watch out for deviations.</p>
 
-<h2>Using the API</h2>
+<h2 id="basics">The Basics</h2>
 
-<p>Here's how to use the API at an extremely high level:</p>
+<p>Android supports OpenGL both through its framework API and the Native Development
+Kit (NDK). This topic focuses on the Android framework interfaces. For more information about the
+NDK, see the <a href="{@docRoot}sdk/ndk/index.html">Android NDK</a>.
 
-<ol>
-<li>Write a custom {@link android.view.View} subclass.</li>
-<li>Obtain a handle to an OpenGLContext, which provides access to the OpenGL functionality.</li>
-<li>In your View's {@link android.view.View#onDraw onDraw()} method, get a handle to a GL object,
-and use its methods to perform GL operations.</li>
-</ol>
-
-<p>Several samples using OpenGL ES are available in the <a
-href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/index.html">API
-Demos</a> sample application.
+<p>
+  There are two foundational classes in the Android framework that let you create and manipulate
+graphics with the OpenGL ES API: {@link android.opengl.GLSurfaceView} and {@link
+android.opengl.GLSurfaceView.Renderer}. If your goal is to use OpenGL in your Android application,
+understanding how to implement these classes in an activity should be your first objective.
 </p>
 
-<p>A summary of how to actually write 3D applications using OpenGL is
-beyond the scope of this text and is left as an exercise for the reader.</p>
+<dl>
+  <dt>{@link android.opengl.GLSurfaceView}</dt>
+  <dd>This class is a container on which you can draw and manipulate objects using OpenGL API calls.
+    This class is similar in function to a {@link android.view.SurfaceView}, except that it is
+    specifically for use with OpenGL. You can use this class by simply creating an instance of 
+    {@link android.opengl.GLSurfaceView} and adding your 
+    {@link android.opengl.GLSurfaceView.Renderer Renderer} to it. However, if you want to capture
+    touch screen events, you should extend the {@link android.opengl.GLSurfaceView} class to
+    implement the touch listeners, as shown in the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity
+.html">TouchRotateActivity</a> sample.</dd>
+  
+  <dt>{@link android.opengl.GLSurfaceView.Renderer}</dt>
+  <dd>This interface defines the methods required for drawing graphics in an OpenGL {@link
+    android.opengl.GLSurfaceView}. You must provide an implementation of this interface as a
+    separate class and attach it to your {@link android.opengl.GLSurfaceView} instance using
+    {@link android.opengl.GLSurfaceView#setRenderer(android.opengl.GLSurfaceView.Renderer)
+    GLSurfaceView.setRenderer()}.
+    
+    <p>The {@link android.opengl.GLSurfaceView.Renderer} interface requires that you implement the
+      following methods:</p>
+    <ul>
+      <li>
+        {@link
+    android.opengl.GLSurfaceView.Renderer#onSurfaceCreated(javax.microedition.khronos.opengles.GL10,
+    javax.microedition.khronos.egl.EGLConfig) onSurfaceCreated()}: The system calls this
+    method once, when creating the {@link android.opengl.GLSurfaceView}. Use this method to perform
+    actions that need to happen only once, such as setting OpenGL environment parameters or
+    initializing OpenGL graphic objects.
+      </li>
+      <li>
+        {@link
+        android.opengl.GLSurfaceView.Renderer#onDrawFrame(javax.microedition.khronos.opengles.GL10)
+        onDrawFrame()}: The system calls this method on each redraw of the {@link
+        android.opengl.GLSurfaceView}. Use this method as the primary execution point for
+        drawing (and re-drawing) graphic objects.</li>
+      <li>
+        {@link
+    android.opengl.GLSurfaceView.Renderer#onSurfaceChanged(javax.microedition.khronos.opengles.GL10,
+    int, int) onSurfaceChanged()}: The system calls this method when the {@link
+    android.opengl.GLSurfaceView} geometry changes, including changes in size of the {@link
+    android.opengl.GLSurfaceView} or orientation of the device screen. For example, the system calls
+    this method when the device changes from portrait to landscape orientation. Use this method to
+    respond to changes in the {@link android.opengl.GLSurfaceView} container. 
+      </li>
+    </ul>
+    </dd>
+</dl>
 
-<h2>Links to Additional Information</h2>
+<p>Once you have established a container view for OpenGL using {@link
+android.opengl.GLSurfaceView} and {@link android.opengl.GLSurfaceView.Renderer}, you can begin
+calling OpenGL APIs using the following classes:</p>
 
-<p>Information about OpenGL ES can be
-found at <a title="http://www.khronos.org/opengles/"
-href="http://www.khronos.org/opengles/">http://www.khronos.org/opengles/</a>.</p> 
+<ul>
+  <li>OpenGL ES 1.0/1.1 API Packages
+    <ul>
+      <li>{@link javax.microedition.khronos.opengles} - This package provides the standard
+implementation of OpenGL ES 1.0 and 1.1.
+          <ul>
+            <li>{@link javax.microedition.khronos.opengles.GL10}</li>
+            <li>{@link javax.microedition.khronos.opengles.GL10Ext}</li>
+            <li>{@link javax.microedition.khronos.opengles.GL11}</li>
+            <li>{@link javax.microedition.khronos.opengles.GL11Ext}</li>
+            <li>{@link javax.microedition.khronos.opengles.GL11ExtensionPack}</li>
+          </ul>
+        </li>
+        <li>{@link android.opengl} - This package provides a static interface to the OpenGL classes
+          above. These interfaces were added with Android 1.6 (API Level 4).
+          <ul>
+            <li>{@link android.opengl.GLES10}</li>
+            <li>{@link android.opengl.GLES10Ext}</li>
+            <li>{@link android.opengl.GLES11}</li>
+            <li>{@link android.opengl.GLES10Ext}</li>
+          </ul>
+        </li>
+      </ul>
+  </li>
+  <li>OpenGL ES 2.0 API Class
+    <ul>
+      <li>{@link android.opengl.GLES20 android.opengl.GLES20}</li>
+    </ul>
+  </li>
+</ul>
 
-<p>Information specifically
-about OpenGL ES 1.0 (including a detailed specification) can be found
-at <a title="http://www.khronos.org/opengles/1_X/"
-href="http://www.khronos.org/opengles/1_X/">http://www.khronos.org/opengles/1_X/</a>.</p>
+<h2 id="compatibility">OpenGL Versions and Device Compatibility</h2>
 
-<p>The documentation for the Android OpenGL ES implementations are available in {@link
-android.opengl} and {@link javax.microedition.khronos.opengles}.</p>
+<p>
+  The OpenGL ES 1.0 and 1.1 API specifications have been supported since Android 1.0.
+Beginning with Android 2.2 (API Level 8), the framework supports the OpenGL ES 2.0 API
+specification. OpenGL ES 2.0 is supported by most Android devices and is recommended for new
+applications being developed with OpenGL. For information about the relative number of
+Android-powered devices that support a given version of OpenGL ES, see the <a
+href="{@docRoot}resources/dashboard/opengl.html">OpenGL ES Versions Dashboard</a>.</p>
 
+<h3 id="textures">Texture compression support</h3>
+<p>Texture compression can significantly increase the performance of your OpenGL application by
+reducing memory requirements and making more efficient use of memory bandwidth. The Android
+framework provides support for the ETC1 compression format as a standard feature, including a {@link
+android.opengl.ETC1Util} utility class and the {@code etc1tool} compression tool (located in your
+Android SDK at {@code &lt;sdk&gt;/tools/}).</p>
+
+<p>For an example of an Android application that uses texture compression, see the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/
+CompressedTextureActivity.html">CompressedTextureActivity</a> code sample.
+</p>
+
+<p>To check if the ETC1 format is supported on a device, call the {@link
+android.opengl.ETC1Util#isETC1Supported() ETC1Util.isETC1Supported()} method.</p>
+
+<p class="note"><b>Note:</b> The ETC1 texture compression format does not support textures with an
+alpha channel. If your application requires textures with an alpha channel, you should
+investigate other texture compression formats available on your target devices.</p>
+
+<p>Beyond the ETC1 format, Android devices have varied support for texture compression based on
+their GPU chipsets. You should investigate texture compression support on the the devices you are
+are targeting to determine what compression types your application should support.</p>
+
+<p>To determine if texture compression formats other than ETC1 are supported on a particular
+device:</p>
+<ol>
+  <li>Run the following code on your target devices to determine what texture compression
+formats are supported:
+<pre>
+  String extensions = javax.microedition.khronos.opengles.GL10.glGetString(GL10.GL_EXTENSIONS);
+</pre>
+  <p class="warning"><b>Warning:</b> The results of this call vary by device! You must run this
+call on several target devices to determine what compression types are commonly supported on
+your target devices.</p>
+  </li>
+  <li>Review the output of this method to determine what extensions are supported on the
+device.</li> 
+</ol>
+
+
+<h3 id="declare-compression">Declaring compressed textures</h3>
+<p>Once you have decided which texture compression types your application will support, you
+must declare them in your manifest file using <a
+href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">
+&lt;supports-gl-texture&gt;</a>. Declaring this information in your manifest file hides your
+application from users with devices that do not support at least one of your declared
+compression types. For more information on how Android Market filtering works for texture
+compressions, see the <a
+href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html#market-texture-filtering">
+Android Market and texture compression filtering</a> section of the {@code
+&lt;supports-gl-texture&gt;} documentation.
diff --git a/docs/html/guide/topics/manifest/supports-screens-element.jd b/docs/html/guide/topics/manifest/supports-screens-element.jd
index ee99a37..605a2bb 100644
--- a/docs/html/guide/topics/manifest/supports-screens-element.jd
+++ b/docs/html/guide/topics/manifest/supports-screens-element.jd
@@ -8,12 +8,15 @@
 <dt>syntax:</dt>
 <dd>
 <pre class="stx">
-&lt;supports-screens android:<a href="#resizeable">resizeable</a>=["true" | "false"]
-                  android:<a href="#small">smallScreens</a>=["true" | "false"] 
-                  android:<a href="#normal">normalScreens</a>=["true" | "false"] 
-                  android:<a href="#large">largeScreens</a>=["true" | "false"] 
+&lt;supports-screens android:<a href="#requiresSmallest">requiresSmallestWidthDp</a>="<em>integer</em>"
+                  android:<a href="#compatibleWidth">compatibleWidthLimitDp</a>="<em>integer</em>"
+                  android:<a href="#largestWidth">largestWidthLimitDp</a>="<em>integer</em>"
+                  android:<a href="#resizeable">resizeable</a>=["true"| "false"]
+                  android:<a href="#small">smallScreens</a>=["true" | "false"]
+                  android:<a href="#normal">normalScreens</a>=["true" | "false"]
+                  android:<a href="#large">largeScreens</a>=["true" | "false"]
                   android:<a href="#xlarge">xlargeScreens</a>=["true" | "false"]
-                  android:<a href="#any">anyDensity</a>=["true" | "false"] /&gt;
+                  android:<a href="#any">anyDensity</a>=["true" | "false"]  /&gt;
 </pre>
 </dd>
 
@@ -21,36 +24,37 @@
 <dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
 
 <dt>description:</dt>
-<dd>Lets you specify the screen dimensions the
-application supports.  By default, a modern application (using API Level 4 or higher) supports all
-screen sizes; older applications are assumed to support only the "normal" screen size. Screen
-size is determined as the available pixels to an application after density scaling has been
-applied. (Note that screen size is a separate axis from screen density.)
+<dd>Lets you specify the screen sizes your application supports and enable screen
+compatibility mode for screens larger than what your application supports. By default, a modern
+application (using API Level 4 or higher) supports all screen sizes; older applications are assumed
+to support only the "normal" screen size. Screen size is determined by the number of pixels on the
+screen after the system accounts for screen density scaling.
 
-<p>An application "supports" a given screen size if it fills the entire screen and works as
-expected. By default, the system will resize your application to fill the screen, if you have set
+<p>An application "supports" a given screen size if it resizes properly to fill the entire screen.
+By default, the system resizes your application UI to fill the screen if you have set
 either <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
 minSdkVersion}</a> or <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-targetSdkVersion}</a> to {@code "4"} or higher. Resizing works well for most applications and
-you don't have to do any extra work to make your application work on larger screens.</p>
+targetSdkVersion}</a> to {@code "4"} or higher. Normal resizing works well for most applications and
+you don't have to do any extra work to make your application work on screens larger than a
+handset device.</p>
 
-<p>In addition to allowing the system to resize your application, you can add additional support
-for different screen sizes by providing <a
+<p>In addition to allowing the system to resize your application to fit the current screen, you can
+optimize your UI for different screen sizes by providing <a
 href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">alternative
 layout resources</a> for different sizes. For instance, you might want to modify the layout
 of an activity when it is on a tablet or similar device that has an <em>xlarge</em> screen.</p>
 
-<p>If your application does not support <em>large</em> or <em>xlarge</em> screens, then you should
-declare that it is not resizeable by setting <a href="#resizeable">{@code android:resizeable}</a> to
-{@code "false"}, so that the system will not resize your application on larger screens.</p>
+<p>However, if your application does not work well when resized to fit different screen sizes,
+you can use the attributes of the {@code &lt;supports-screens&gt;} element to control whether
+your application should be distributed to smaller screens or have its UI scaled up to fit larger
+screens using the system's screen compatibility mode. When you have not designed for larger screen
+sizes and the normal resizing does not achieve the appropriate results, <em>screen compatibility
+mode</em> will scale your UI by emulating a <em>normal</em> size screen and then zooming in on it so
+that it fills the entire screen&mdash;thus achieving the same layout as a normal handset device on
+the large screen (but this usually causes pixelation and blurring of your UI).</p>
 
-<p>If your application does not support <em>small</em> screens, then
-there isn't much the system can do to make the application work well on a smaller screen, so
-external services (such as Android Market) should not allow users to install the application on such
-screens.</p>
-
-
-<p>For more information, see 
+<p>For more information about how to properly support different screen sizes so that you can avoid
+using screen compatibility mode, read
 <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p>
 
 
@@ -59,6 +63,74 @@
 <dd>
 <dl class="attr">
   
+  <dt id="requiresSmallest">{@code android:requiresSmallestWidthDp}</dt>
+  <dd>This attribute specifies the minimum "smallest screen width" with which your
+application is compatible. In order for a device to be considered compatible with your
+application, the shortest side of the available screen space must be equal to or greater than this
+value.
+<p>The width against which your value is compared takes into account screen decorations and system
+UI. For example, if the device has some persistent UI elements on the left or right edge of the
+display, the system declares the device's available width as one that is smaller than the actual
+screen size, accounting for these UI elements because those are screen pixels not available for your
+UI. Thus, the value you use should be the actual smallest width required by your layout.</p>
+<p>If your application properly resizes for smaller screen sizes (down to the
+<em>small</em> size or a minimum width of 320dp), you do
+not need to use this attribute. Otherwise, you should use a value for this attribute that
+matches the smallest value used by your application for the <a
+href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">
+smallest screen width qualifier</a> ({@code sw&lt;N&gt;dp}).</p>
+
+<p>For example, a typical handset screen has a minimum width of 320dp, a 7" tablet has a minimum
+width of 600dp, and a 10" tablet has a minimum width of 720dp. If the smallest available screen
+width on a device is less than the value you supply here, then the application is considered
+incompatible with that
+device. External services such as Android Market use this to determine whether a device
+is compatible with your application and prevent incompatible devices from installing it.</p>
+<p>Beginning with Android 3.2 (API level 13), using this attribute is the preferred way to
+specify the minimum screen size your application requires, instead of using the other attributes
+for small, normal, large, and xlarge screens. The advantage of using this attribute is that you
+have more control over exactly how much screen space your application needs at a minimum in order
+to properly display its UI, rather than relying on the generalized size groups.</p>
+<p>This attribute has no default value. If this attribute is not specified, then any of the old
+<code><a href="#small">smallScreens</a></code>, <code><a href="#normal">normalScreens</a></code>,
+<code><a href="#large">largeScreens</a></code>, or <code><a href="#xlarge">xlargeScreens</a></code>
+attributes are used instead to determine the smallest screen required.</p>
+     <p>This attribute was introduced in API level 13.</p>
+  </dd>
+
+  <dt id="compatibleWidth">{@code android:compatibleWidthLimitDp}</dt>
+  <dd>This attribute allows you to enable screen compatibility mode as a user-optional feature by
+specifying the maximum "smallest screen width" for which your application is designed. If the value
+you supply here is less than the shortest side of the available screen space, users can still
+install your application, but are offered to run it in screen compatibility mode. By default, screen
+compatibility mode is disabled and your layout is resized to fit the screen as usual, but a
+button is available in the system bar that allows the user to toggle screen compatibility mode on
+and off.
+  <p>If your application is compatible with all screen sizes and its layout properly resizes, you do
+not need to use this attribute.</p>
+  <p class="note"><strong>Note:</strong> Currently, screen compatibility mode only emulates handset
+screens with a 320dp width, so screen compatibility mode is not applied if your value for {@code
+android:compatibleWidthLimitDp} is larger than 320.</p>
+     <p>This attribute was introduced in API level 13.</p>
+  </dd>
+
+  <dt id="largestWidth">{@code android:largestWidthLimitDp}</dt>
+  <dd>This attribute allows you to force enable screen compatibility mode by specifying the maximum
+"smallest screen width" for which your application is designed. If the value you supply here is less
+than the shortest side of the available screen space, the application runs in screen
+compatibility mode with no way for the user to disable it.
+  <p>If your application is compatible with all screen sizes and its layout properly resizes, you do
+not need to use this attribute. Otherwise, you should first consider using the <a
+href="#compatibleWidth">{@code android:compatibleWidthLimitDp}</a> attribute. You should use the
+{@code android:largestWidthLimitDp} attribute only when your application is functionally broken when
+resized for larger screens and screen compatibility mode is the only way that users should use
+your application.</p>
+  <p class="note"><strong>Note:</strong> Currently, screen compatibility mode only emulates handset
+screens with a 320dp width, so screen compatibility mode is not applied if your value for {@code
+android:largestWidthLimitDp} is larger than 320.</p>
+     <p>This attribute was introduced in API level 13.</p>
+  </dd>
+
   <dt><a name="resizeable"></a>{@code android:resizeable}</dt>
   <dd>Indicates whether the application is resizeable for different screen sizes. This attribute is
 true, by default, if you have set either <a
@@ -75,6 +147,7 @@
 application does not work well on larger screens, follow the guide to <a
 href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> to enable
 additional screen support.</p>
+  <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
   </dd>
   
   
@@ -91,6 +164,7 @@
 {@code "4"} or higher,
 the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
 {@code "false"}.
+  <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
   </dd>
   
   <dt><a name="normal"></a>{@code android:normalScreens}</dt>
@@ -99,12 +173,13 @@
      screen, but WQVGA low density and WVGA high density are also
      considered to be normal.  This attribute is "true" by default,
      and applications currently should leave it that way.
+  <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
   </dd>
   
   <dt><a name="large"></a>{@code android:largeScreens}</dt>
   <dd>Indicates whether the application supports larger screen form-factors.
      A large screen is defined as a screen that is significantly larger
-     than a "normal" phone screen, and thus might require some special care
+     than a "normal" handset screen, and thus might require some special care
      on the application's part to make good use of it, though it may rely on resizing by the
 system to fill the screen. If the application has set either <a
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> or <a
@@ -112,6 +187,7 @@
 {@code "4"} or higher,
 the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
 {@code "false"}.
+  <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
   </dd>
 
   <dt><a name="xlarge"></a>{@code android:xlargeScreens}</dt>
@@ -125,7 +201,8 @@
 {@code "4"} or higher,
 the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
 {@code "false"}.
-     <p>This attribute was introduced in API Level 9.</p>
+     <p>This attribute was introduced in API level 9.</p>
+  <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
   </dd>
   
   <dt><a name="any"></a>{@code android:anyDensity}</dt>
@@ -142,6 +219,7 @@
 down application assets by a factor of 0.75 (low dpi screens) or scale them up by a factor of 1.5
 (high dpi screens), when you don't provide alternative resources for a specifc screen density. The
 screen density is expressed as dots-per-inch (dpi).</p>
+  <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
   </dd>
   
 
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index a996ccc..ea778c1 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -335,80 +335,101 @@
     </tr>
     <tr id="SmallestScreenWidthQualifier">
       <td>Smallest screen width</td>
-      <td>Examples:<br/>
+      <td><code>sw&lt;N&gt;dp</code><br/><br/>
+        Examples:<br/>
         <code>sw320dp</code><br/>
         <code>sw600dp</code><br/>
         <code>sw720dp</code><br/>
         etc.
       </td>
       <td>
-        <p>Specifies a minimum "smallest screen width," in "dp" units, at which the resource
-          should be used.  This configuration value represents the base screen size
-          of the device, regardless of the orientation of the display.  It is based
-          on the smallest width the application will have in which to perform its
-          UI layout (in dp units) regardless of the orientation of the screen.  The
-          value here takes into account screen decorations so if the device has some
-          persistent UI elements on the left or right edge of the display it must
-          present a value here that is smaller than the real screen size, accounting
-          for these UI elements reducing the application's available space.</p>
-        <p>Some values you may use here for common screen sizes:</p>
+        <p>Specifies the "smallest width" in {@code dp} units that must be available to your
+        application in order for the resources to be used, regardless of the screen's current
+        orientation. For example, if your layout requires that its shortest side be at least 600
+        dp in length at all times, then you can use this to create the layout resources, {@code
+        res/layout-sw600dp/}, and the system will use them only when the shortest side of
+        available screen space it at least 600dp.</p>
+        <p>The width against which the system compares your value takes into account screen
+        decorations and system UI. For example, if the device has some persistent UI elements on the
+        left or right edge of the display, the system declares its own available width as one that
+        is smaller than the actual screen size, accounting for these UI elements because those are
+        screen pixels not available for your UI. Thus, the value you use should be the actual
+        smallest width required by your layout.</p>
+        <p>Some values you might use here for common screen sizes:</p>
         <ul>
-          <li>240x320 ldpi (QVGA phone): 320
-          <li>320x480 mdpi (phone): 320
-          <li>480x800 hdpi (high density phone): 320
-          <li>480x800 mdpi (tablet/phone): 480
-          <li>600x1024 mdpi (7" tablet): 600
-          <li>720x1280 mdpi (10" tablet): 720
+          <li>320, for devices with screen configurations such as:
+            <ul>
+              <li>240x320 ldpi (QVGA handset)</li>
+              <li>320x480 mdpi (handset)</li>
+              <li>480x800 hdpi (high density handset)</li>
+            </ul>
+          </li>
+          <li>480, for screens such as 480x800 mdpi (tablet/handset).</li>
+          <li>600, for screens such as 600x1024 mdpi (7" tablet).</li>
+          <li>720, for screens such as 720x1280 mdpi (10" tablet).</li>
         </ul>
-        <p><em>Added in API Level 13.</em></p>
-        <p>Also see the {@link android.content.res.Configuration#smallestScreenWidthDp}
-          configuration field, which holds the current smallest screen width.</p>
+        <p>When your application provides multiple resource directories with different values for
+        this qualifier, the system uses the one closest to (without exceeding) the smallest width
+        for the available space. </p>
+        <p><em>Added in API level 13.</em></p>
+        <p>Also see the <a
+        href="{@docRoot}guide/topics/manifest/supports-screens-element.html#requiresSmallest">{@code
+        android:requiresSmallestWidthDp}</a> attribute, which declares the smallest available width
+        with which your application is compatible, and the {@link
+        android.content.res.Configuration#smallestScreenWidthDp} configuration field, which holds
+        the current smallest screen width for the device.</p>
       </td>
     </tr>
     <tr id="ScreenWidthQualifier">
       <td>Screen width</td>
-      <td>Examples:<br/>
+      <td><code>w&lt;N&gt;dp</code><br/><br/>
+        Examples:<br/>
         <code>w720dp</code><br/>
         <code>w1024dp</code><br/>
         etc.
       </td>
       <td>
-        <p>Specifies a minimum screen width, in "dp" units, at which the resource
-          should be used.  This configuration value will change when the orientation
-          changes between landscape and portrait to match the current actual width.
-          When multiple screen width configurations are available, the closest to
-          the current screen width will be used.  The
-          value here takes into account screen decorations so if the device has some
-          persistent UI elements on the left or right edge of the display it must
-          present a value here that is smaller than the real screen size, accounting
-          for these UI elements reducing the application's available space.</p>
-        <p><em>Added in API Level 13.</em></p>
+        <p>Specifies a minimum screen width, in {@code dp} units at which the resource
+          should be used&mdash;defined by the <code>&lt;N&gt;</code> value.  This
+          configuration value will change when the orientation
+          changes between landscape and portrait to match the current actual width.</p>
+        <p>When your application provides multiple resource directories with different values
+          for this configuration, the system uses the one closest to (without exceeding)
+          the device's current screen width.  The
+          value here takes into account screen decorations, so if the device has some
+          persistent UI elements on the left or right edge of the display, it
+          uses a value for the width that is smaller than the real screen size, accounting
+          for these UI elements and reducing the application's available space.</p>
+        <p><em>Added in API level 13.</em></p>
         <p>Also see the {@link android.content.res.Configuration#screenWidthDp}
           configuration field, which holds the current screen width.</p>
       </td>
     </tr>
     <tr id="ScreenHeightQualifier">
       <td>Screen height</td>
-      <td>Examples:<br/>
+      <td><code>h&lt;N&gt;dp</code><br/><br/>
+        Examples:<br/>
         <code>h720dp</code><br/>
         <code>h1024dp</code><br/>
         etc.
       </td>
       <td>
-        <p>Specifies a minimum screen height, in "dp" units, at which the resource
-          should be used.  This configuration value will change when the orientation
-          changes between landscape and portrait to match the current actual height.
-          When multiple screen height configurations are available, the closest to
-          the current screen height will be used.  The
-          value here takes into account screen decorations so if the device has some
-          persistent UI elements on the left or right edge of the display it must
-          present a value here that is smaller than the real screen size, accounting
-          for these UI elements reducing the application's available space.  Screen
+        <p>Specifies a minimum screen height, in "dp" units at which the resource
+          should be used&mdash;defined by the <code>&lt;N&gt;</code> value.  This
+          configuration value will change when the orientation
+          changes between landscape and portrait to match the current actual height.</p>
+        <p>When your application provides multiple resource directories with different values
+          for this configuration, the system uses the one closest to (without exceeding)
+          the device's current screen height.  The
+          value here takes into account screen decorations, so if the device has some
+          persistent UI elements on the top or bottom edge of the display, it uses
+          a value for the height that is smaller than the real screen size, accounting
+          for these UI elements and reducing the application's available space.  Screen
           decorations that are not fixed (such as a phone status bar that can be
           hidden when full screen) are <em>not</em> accounted for here, nor are
-          window decorations like title bar, so applications must be prepared to
+          window decorations like the title bar or action bar, so applications must be prepared to
           deal with a somewhat smaller space than they specify.
-        <p><em>Added in API Level 13.</em></p>
+        <p><em>Added in API level 13.</em></p>
         <p>Also see the {@link android.content.res.Configuration#screenHeightDp}
           configuration field, which holds the current screen width.</p>
       </td>
@@ -444,9 +465,9 @@
         medium-density HVGA screen. The minimum layout size for this screen configuration
         is approximately 720x960 dp units.  In most cases, devices with extra large
         screens would be too large to carry in a pocket and would most likely
-        be tablet-style devices. <em>Added in API Level 9.</em></li>
+        be tablet-style devices. <em>Added in API level 9.</em></li>
         </ul>
-        <p><em>Added in API Level 4.</em></p>
+        <p><em>Added in API level 4.</em></p>
         <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
 Screens</a> for more information.</p>
         <p>Also see the {@link android.content.res.Configuration#screenLayout} configuration field,
@@ -465,7 +486,7 @@
           <li>{@code long}: Long screens, such as WQVGA, WVGA, FWVGA</li>
           <li>{@code notlong}: Not long screens, such as QVGA, HVGA, and VGA</li>
         </ul>
-        <p><em>Added in API Level 4.</em></p>
+        <p><em>Added in API level 4.</em></p>
         <p>This is based purely on the aspect ratio of the screen (a "long" screen is wider). This
 is not related to the screen orientation.</p>
         <p>Also see the {@link android.content.res.Configuration#screenLayout} configuration field,
@@ -503,7 +524,7 @@
           <li>{@code car}: Device is in a car dock</li>
           <li>{@code desk}: Device is in a desk dock</li>
         </ul>
-        <p><em>Added in API Level 8.</em></p>
+        <p><em>Added in API level 8.</em></p>
         <p>This can change during the life of your application if the user places the device in a
 dock. You can enable or disable this mode using {@link
 android.app.UiModeManager}. See <a href="runtime-changes.html">Handling Runtime Changes</a> for
@@ -521,7 +542,7 @@
           <li>{@code night}: Night time</li>
           <li>{@code notnight}: Day time</li>
         </ul>
-        <p><em>Added in API Level 8.</em></p>
+        <p><em>Added in API level 8.</em></p>
         <p>This can change during the life of your application if night mode is left in
 auto mode (default), in which case the mode changes based on the time of day.  You can enable
 or disable this mode using {@link android.app.UiModeManager}. See <a
@@ -549,7 +570,7 @@
           <li>{@code nodpi}: This can be used for bitmap resources that you do not want to be scaled
 to match the device density.</li>
         </ul>
-        <p><em>Added in API Level 4.</em></p>
+        <p><em>Added in API level 4.</em></p>
         <p>There is thus a 3:4:6:8 scaling ratio between the four densities, so a 9x9 bitmap
          in ldpi is 12x12 in mdpi, 18x18 in hdpi and 24x24 in xhdpi.</p>
         <p>When Android selects which resource files to use,
@@ -689,17 +710,17 @@
     </tr>
 -->
     <tr id="VersionQualifier">
-      <td>Platform Version (API Level)</td>
+      <td>Platform Version (API level)</td>
       <td>Examples:<br/>
         <code>v3</code><br/>
         <code>v4</code><br/>
         <code>v7</code><br/>
         etc.</td>
       <td>
-        <p>The API Level supported by the device. For example, <code>v1</code> for API Level
-1 (devices with Android 1.0 or higher) and <code>v4</code> for API Level 4 (devices with Android
+        <p>The API level supported by the device. For example, <code>v1</code> for API level
+1 (devices with Android 1.0 or higher) and <code>v4</code> for API level 4 (devices with Android
 1.6 or higher). See the <a
-href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a> document for more information
+href="{@docRoot}guide/appendix/api-levels.html">Android API levels</a> document for more information
 about these values.</p>
         <p class="caution"><strong>Caution:</strong> Android 1.5 and 1.6 only match resources
 with this qualifier when it exactly matches the platform version. See the section below about <a
@@ -863,7 +884,7 @@
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
 minSdkVersion}</a> is set to 4, and you qualify all of your drawable resources using <a
 href="#NightQualifier">night mode</a> ({@code night} or {@code notnight}, which were added in API
-Level 8), then an API Level 4 device cannot access your drawable resources and will crash. In this
+Level 8), then an API level 4 device cannot access your drawable resources and will crash. In this
 case, you probably want {@code notnight} to be your default resources, so you should exclude that
 qualifier so your drawable resources are in either {@code drawable/} or {@code drawable-night/}.</p>
 
@@ -896,7 +917,7 @@
     <dd>{@code long} and {@code notlong}</dd>
 </dl>
 
-<p>These configuration qualifiers were introduced in Android 1.6, so Android 1.5 (API Level 3) and
+<p>These configuration qualifiers were introduced in Android 1.6, so Android 1.5 (API level 3) and
 lower does not support them. If you use these configuration qualifiers and do not provide
 corresponding default resources, then an Android 1.5 device might use any one of the resource
 directories named with the above screen configuration qualifiers, because it ignores these
@@ -926,9 +947,9 @@
     <p>You need SDK Tools, Revision 6 (or greater), because it includes a new packaging tool that
 automatically applies an appropriate <a href="#VersionQualifier">version qualifier</a> to any
 resource directory named with a qualifier that does not exist in Android 1.0. For example, because
-the density qualifier was introduced in Android 1.6 (API Level 4), when the packaging tool
+the density qualifier was introduced in Android 1.6 (API level 4), when the packaging tool
 encounters a resource directory using the density qualifier, it adds {@code v4} to the directory
-name to ensure that older versions do not use those resources (only API Level 4 and higher support
+name to ensure that older versions do not use those resources (only API level 4 and higher support
 that qualifier). Thus, by putting your medium-density resources in a directory <em>without</em> the
 {@code mdpi} qualifier, they are still accessible by Android 1.5, and any device that supports the
 density qualifer and has a medium-density screen also uses the default resources (which are mdpi)
@@ -937,7 +958,7 @@
 </li>
 </ol>
 
-<p class="note"><strong>Note:</strong> Later versions of Android, such as API Level 8,
+<p class="note"><strong>Note:</strong> Later versions of Android, such as API level 8,
 introduce other configuration qualifiers that older version do not support. To provide the best
 compatibility, you should always include a set of default resources for each type of resource
 that your application uses, as discussed above to provide the best device compatibility.</p>
@@ -1068,7 +1089,7 @@
 
 <p>The correct behavior is for the system to match resources marked with a <a
 href="#VersionQualifier">version qualifier</a> equal
-to or less than the platform version on the device, but on Android 1.5 and 1.6, (API Level 3 and 4),
+to or less than the platform version on the device, but on Android 1.5 and 1.6, (API level 3 and 4),
 there is a bug that causes the system to match resources marked with the version qualifier
 only when it exactly matches the version on the device.</p>
 
diff --git a/docs/html/guide/topics/search/index.jd b/docs/html/guide/topics/search/index.jd
index 7ac5ff1..218511b 100644
--- a/docs/html/guide/topics/search/index.jd
+++ b/docs/html/guide/topics/search/index.jd
@@ -52,7 +52,13 @@
 <p class="note"><strong>Note</strong>: The search framework does <em>not</em> provide APIs to
 search your data. To perform a search, you need to use APIs appropriate for your data. For example,
 if your data is stored in an SQLite database, you should use the {@link android.database.sqlite}
-APIs to perform searches.</p>
+APIs to perform searches.
+<br/><br/>
+Also, there is no guarantee that every device provides a dedicated SEARCH button to invoke the
+search interface in your application. When using the search dialog or a custom interface, you
+must always provide a search button in your UI that activates the search interface. For more
+information, see <a href="search-dialog.html#InvokingTheSearchDialog">Invoking the search
+dialog</a>.</p>
 
 <p>The following documents show you how to use Android's framework to implement search:</p>
 
diff --git a/docs/html/guide/topics/search/search-dialog.jd b/docs/html/guide/topics/search/search-dialog.jd
index af6c8f2..d869a44 100644
--- a/docs/html/guide/topics/search/search-dialog.jd
+++ b/docs/html/guide/topics/search/search-dialog.jd
@@ -17,29 +17,30 @@
 
 <h2>In this document</h2>
 <ol>
-<li><a href="#TheBasics">The Basics</a></li>
-<li><a href="#SearchableConfiguration">Creating a Searchable Configuration</a></li>
-<li><a href="#SearchableActivity">Creating a Searchable Activity</a>
-  <ol>
-    <li><a href="#DeclaringSearchableActivity">Declaring a searchable activity</a></li>
-    <li><a href="#EnableSearch">Enabling the search dialog and search widget</a></li>
-    <li><a href="#PerformingSearch">Performing a search</a></li>
-  </ol>
-</li>
-<li><a href="#UsingTheSearchDialog">Using the Search Dialog</a>
-  <ol>
-    <li><a href="#LifeCycle">The impact of the search dialog on your activity lifecycle</a></li>
-    <li><a href="#SearchContextData">Passing search context data</a></li>
-  </ol>
-</li>
-<li><a href="#UsingSearchWidget">Using the Search Widget</a>
-  <ol>
-    <li><a href="#ConfiguringWidget">Configuring the search widget</a></li>
-    <li><a href="#WidgetFeatures">Other search widget features</a></li>
-  </ol>
-</li>
-<li><a href="#VoiceSearch">Adding Voice Search</a></li>
-<li><a href="#SearchSuggestions">Adding Search Suggestions</a></li>
+  <li><a href="#TheBasics">The Basics</a></li>
+  <li><a href="#SearchableConfiguration">Creating a Searchable Configuration</a></li>
+  <li><a href="#SearchableActivity">Creating a Searchable Activity</a>
+    <ol>
+      <li><a href="#DeclaringSearchableActivity">Declaring a searchable activity</a></li>
+      <li><a href="#PerformingSearch">Performing a search</a></li>
+    </ol>
+  </li>
+  <li><a href="#SearchDialog">Using the Search Dialog</a>
+    <ol>
+      <li><a href="#InvokingTheSearchDialog">Invoking the search dialog</a></li>
+      <li><a href="#LifeCycle">The impact of the search dialog on your activity lifecycle</a></li>
+      <li><a href="#SearchContextData">Passing search context data</a></li>
+    </ol>
+  </li>
+  <li><a href="#UsingSearchWidget">Using the Search Widget</a>
+    <ol>
+      <li><a href="#ConfiguringWidget">Configuring the search widget</a></li>
+      <li><a href="#WidgetFeatures">Other search widget features</a></li>
+      <li><a href="#UsingBoth">Using both the widget and the dialog</a></li>
+    </ol>
+  </li>
+  <li><a href="#VoiceSearch">Adding Voice Search</a></li>
+  <li><a href="#SearchSuggestions">Adding Search Suggestions</a></li>
 </ol>
 
 <h2>Key classes</h2>
@@ -494,13 +495,13 @@
 
 <h3 id="InvokingTheSearchDialog">Invoking the search dialog</h3>
 
-<p>As mentioned above, the device SEARCH button and {@link android.app.Activity#onSearchRequested
-onSearchRequested()} method will open the search dialog, as long as the current activity
-has declared the searchable activity to use, as shown in the previous section.</p>
+<p>As mentioned above, the device SEARCH button will open the search dialog as long as the current
+activity has declared in the manifest the searchable activity to use.</p>
 
-<p>However, you should not assume that a SEARCH button is available on the user's device. You
-should always provide another search button in your UI that activates the search dialog by calling
-{@link android.app.Activity#onSearchRequested()}.</p>
+<p>However, some devices do not include a dedicated SEARCH button, so you should not assume that
+it's always available. When using the search dialog, you must <strong>always provide another search
+button in your UI</strong> that activates the search dialog by calling {@link
+android.app.Activity#onSearchRequested()}.</p>
 
 <p>For instance, you should either provide a menu item in your <a
 href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> or a button in your
@@ -510,12 +511,6 @@
 medium and high density screens, which you can use for your search menu item or button (low-density
 screens scale-down the hdpi image by one half). </p>
 
-<!-- ... maybe this should go into the Creating Menus document ....
-<p>If you chose to provide a shortcut key for the menu item,  using {@link
-android.view.MenuItem#setAlphabeticShortcut(char)}, then SearchManager.MENU_KEY is the recommended
-key character, representing the default search key.</p>
--->
-
 <p>You can also enable "type-to-search" functionality, which activates the search dialog when the
 user starts typing on the keyboard&mdash;the keystrokes are inserted into the search dialog. You can
 enable type-to-search in your activity by calling
diff --git a/docs/html/guide/topics/usb/adk.jd b/docs/html/guide/topics/usb/adk.jd
index 2e172f5..b5a3f30 100644
--- a/docs/html/guide/topics/usb/adk.jd
+++ b/docs/html/guide/topics/usb/adk.jd
@@ -326,7 +326,7 @@
     <li>To open the firmware code (a sketch), click <strong>File &gt; Open</strong> and select
     <code>firmware/demokit/demokit.pde</code>.</li>
 
-    <li>Click <strong>Sketch &gt; Compile/Verify</strong> to ensure that the sketch has no
+    <li>Click <strong>Sketch &gt; Verify/Compile</strong> to ensure that the sketch has no
     errors.</li>
 
     <li>Select <strong>File &gt; Upload to I/O Board</strong>. When Arduino outputs <strong>Done
@@ -356,7 +356,8 @@
     <li>In the <strong>Project name:</strong> field, type DemoKit.</li>
 
     <li>Choose <strong>Create project from existing source</strong>, click <strong>Browse</strong>,
-    select the <code>app</code> directory, and click <strong>Finish</strong>.</li>
+    select the <code>app</code> directory, click <strong>Open</strong> to close that dialog and then
+    click <strong>Finish</strong>.</li>
 
     <li>For Build Target, select <strong>Google APIs</strong> (Platform 2.3.3, API Level 10).
 
diff --git a/docs/html/index.jd b/docs/html/index.jd
index eeeedd0..dce46f9 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -148,19 +148,18 @@
 
     'tv': {
       'layout':"imgLeft",
-      'icon':"tv_s.png",
+      'icon':"GTV_icon_small.png",
       'name':"Google TV",
-      'img':"tv_l.png",
-      'title':"Announcing Google TV!",
-      'desc': "<p><a href='http://www.google.com/tv/'>Google TV</a> is a new platform "
-               + "for television built on Android. Google "
-               + "has partnered with Sony and Logitech to integrate "
-               + "this platform into TVs, blu-ray players, and companion "
-               + "boxes. </p>"
-               + "<p><a href='http://www.google.com/tv/'>Learn more about "
-               + "Google TV &raquo;</a></p>"
+      'img':"GTV_icon_large.png",
+      'title':"Google TV!",
+      'desc': "<p>Build something big. By big, we mean <em>worthy-of-the-living-room</em> big.</p>"
+	        +  " <p>Use <a href='http://code.google.com/tv'>Google TV</a> to bring the power of Android" 
+	        +  " and Google Chrome to television."
+			+  " The average American watches five hours of TV per day. Give them the web and apps"
+			+  " to update their status, listen to music, watch web videos, and much more...</p>"
     },
 
+
     'devphone': {
       'layout':"imgLeft",
       'icon':"devphone-small.png",
diff --git a/docs/html/resources/dashboard/opengl.jd b/docs/html/resources/dashboard/opengl.jd
index dac8ce5..3fcfa89 100644
--- a/docs/html/resources/dashboard/opengl.jd
+++ b/docs/html/resources/dashboard/opengl.jd
@@ -57,7 +57,7 @@
 <div class="dashboard-panel">
 
 <img alt="" width="400" height="250"
-src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=GL%20ES%201.1|GL%20ES%202.0&chd=t%3A8.9,91.1" />
+src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=GL%201.1|GL%202.0%20%26%201.1&chd=t%3A8.9,91" />
 
 <table>
 <tr>
@@ -66,11 +66,11 @@
 </tr>
 <tr>
 <td>1.1</th>
-<td>8.9%</td>
+<td>9%</td>
 </tr>
 <tr>
 <td>2.0</th>
-<td>91.1%</td>
+<td>91%</td>
 </tr>
 </table>
 
diff --git a/docs/html/resources/dashboard/platform-versions.jd b/docs/html/resources/dashboard/platform-versions.jd
index 368164d..d9adb36 100644
--- a/docs/html/resources/dashboard/platform-versions.jd
+++ b/docs/html/resources/dashboard/platform-versions.jd
@@ -51,8 +51,8 @@
 
 <div class="dashboard-panel">
 
-<img alt="" height="250" width="460"
-src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:2.3,3.0,24.5,65.9,1.0,3.0,0.3&chl=Android%201.5|Android%201.6|Android%202.1|Android%202.2|Android%202.3|Android%202.3.3|Android%203.0&chco=c4df9b,6fad0c" />
+<img alt="" height="250" width="470"
+src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:1.4,2.2,17.5,59.4,1.0,17.6,0.4,0.5&chl=Android%201.5|Android%201.6|Android%202.1|Android%202.2|Android%202.3%20-%202.3.2|Android%202.3.3%20-%202.3.4|Android%203.0|Android%203.1&chco=c4df9b,6fad0c" />
 
 <table>
 <tr>
@@ -60,16 +60,19 @@
   <th>API Level</th>
   <th>Distribution</th>
 </tr>
-<tr><td>Android 1.5</td><td>3</td><td>2.3%</td></tr> 
-<tr><td>Android 1.6</td><td>4</td><td>3.0%</td></tr> 
-<tr><td>Android 2.1</td><td>7</td><td>24.5%</td></tr> 
-<tr><td>Android 2.2</td><td>8</td><td>65.9%</td></tr> 
-<tr><td>Android 2.3</td><td>9</td><td>1.0%</td></tr> 
-<tr><td>Android 2.3.3</td><td>10</td><td>3.0%</td></tr> 
-<tr><td>Android 3.0</td><td>11</td><td>0.3%</td></tr> 
+<tr><td>Android 1.5</td><td>3</td><td>1.4%</td></tr>
+<tr><td>Android 1.6</td><td>4</td><td>2.2%</td></tr>
+<tr><td>Android 2.1</td><td>7</td><td>17.5%</td></tr>
+<tr><td>Android 2.2</td><td>8</td><td>59.4%</td></tr>
+<tr><td>Android 2.3 -<br/>
+        Android 2.3.2</td><td>9</td><td>1%</td></tr>
+<tr><td>Android 2.3.3 -<br/>
+        Android 2.3.4</td><td>10</td><td>17.6%</td></tr>
+<tr><td>Android 3.0</td><td>11</td><td>0.4%</td></tr>
+<tr><td>Android 3.1</td><td>12</td><td>0.5%</td></tr>
 </table>
 
-<p><em>Data collected during two weeks ending on May 2, 2011</em></p>
+<p><em>Data collected during a 14-day period ending on July 5, 2011</em></p>
 <!--
 <p style="font-size:.9em">* <em>Other: 0.1% of devices running obsolete versions</em></p>
 -->
@@ -98,9 +101,9 @@
 <div class="dashboard-panel">
 
 <img alt="" height="250" width="660" style="padding:5px;background:#fff"
-src="http://chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,x,y,r&chxr=0,0,12|1,0,12|2,0,100|3,0,100&chxl=0%3A%7C11/01%7C11/15%7C12/01%7C12/15%7C01/01%7C01/15%7C02/01%7C02/15%7C03/01%7C03/15%7C04/01%7C04/15%7C05/01%7C1%3A%7C2010%7C%7C%7C%7C2011%7C%7C%7C%7C%7C%7C%7C%7C2011%7C2%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25%7C3%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&chxtc=0,5&chd=t:100.0,99.9,99.8,99.7,100.0,99.9,99.9,99.9,100.0,99.8,99.7,99.6,99.6|92.0,92.7,93.4,94.1,95.2,95.6,96.0,96.3,96.7,96.8,97.0,97.1,97.3|77.4,79.6,82.2,84.4,87.2,88.3,89.7,90.5,91.5,92.0,93.5,93.9,94.3|37.1,40.5,44.3,47.7,51.8,54.3,58.3,59.7,61.5,63.0,66.4,68.0,69.8|0.0,0.0,0.0,0.0,0.4,0.6,0.7,0.8,1.1,1.7,2.5,3.1,4.0|0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,1.7,2.2,3.0&chm=b,c3df9b,0,1,0|tAndroid 1.6,689326,1,0,15,,t::-5|b,b4db77,1,2,0|tAndroid 2.1,547a19,2,0,15,,t::-5|b,a5db51,2,3,0|tAndroid 2.2,3f5e0e,3,0,15,,t::-5|b,96dd28,3,4,0|b,83c916,4,5,0|B,6fad0c,5,6,0&chg=7,25&chdl=Android 1.5|Android 1.6|Android 2.1|Android 2.2|Android 2.3|Android 2.3.3&chco=add274,9dd14f,8ece2a,7ab61c,659b11,507d08" />
+src="http://chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,x,y,r&chxr=0,0,12|1,0,12|2,0,100|3,0,100&chxl=0%3A%7C01/01%7C01/15%7C02/01%7C02/15%7C03/01%7C03/15%7C04/01%7C04/15%7C05/01%7C05/15%7C06/01%7C06/15%7C07/01%7C1%3A%7C2011%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C2011%7C2%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25%7C3%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&chxtc=0,5&chd=t:100.0,99.9,99.9,99.9,100.0,99.8,99.7,99.6,99.6,99.5,99.4,99.3,99.2|95.2,95.6,96.0,96.3,96.7,96.8,97.0,97.1,97.3,97.5,97.5,97.5,97.7|87.2,88.3,89.7,90.5,91.5,92.0,93.5,93.9,94.3,94.8,95.0,95.2,95.5|51.8,54.3,58.3,59.7,61.5,63.0,66.4,68.0,69.8,71.5,73.9,75.4,77.6|0.4,0.6,0.7,0.8,1.1,1.7,2.5,3.1,4.0,6.1,9.5,13.6,17.8|0.0,0.0,0.0,0.0,0.0,1.0,1.7,2.2,3.0,5.1,8.4,12.6,16.8&chm=b,c3df9b,0,1,0|b,b4db77,1,2,0|tAndroid 2.1,547a19,2,0,15,,t::-5|b,a5db51,2,3,0|tAndroid2.2,3f5e0e,3,0,15,,t::-5|b,96dd28,3,4,0|b,83c916,4,5,0|tAndroid2.3.3,131d02,5,11,15,,t::-5|B,6fad0c,5,6,0&chg=7,25&chdl=Android 1.5|Android 1.6|Android 2.1|Android2.2|Android 2.3|Android 2.3.3&chco=add274,9dd14f,8ece2a,7ab61c,659b11,507d08" />
 
-<p><em>Last historical dataset collected during two weeks ending on May 2, 2011</em></p>
+<p><em>Last historical dataset collected during a 14-day period ending on July 5, 2011</em></p>
 
 
 </div><!-- end dashboard-panel -->
diff --git a/docs/html/resources/dashboard/screens.jd b/docs/html/resources/dashboard/screens.jd
index bdaae0d..e61e799 100644
--- a/docs/html/resources/dashboard/screens.jd
+++ b/docs/html/resources/dashboard/screens.jd
@@ -60,7 +60,7 @@
 <div class="dashboard-panel">
 
 <img alt="" width="400" height="250"
-src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=xlarge%20/%20mdpi|large%20/%20mdpi|normal%20/%20hdpi|normal%20/%20ldpi|normal%20/%20mdpi|small%20/%20hdpi&chd=t%3A0.5,2.6,75.5,1.2,17.1,3.2" />
+src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=Xlarge%20/%20mdpi|Large%20/%20mdpi|Normal%20/%20hdpi|Normal%20/%20ldpi|Normal%20/%20mdpi|Small%20/%20hdpi&chd=t%3A0.9,2.8,75,1.0,17,3.3" />
 
 <table>
 <tr>
@@ -71,31 +71,31 @@
 <th scope="col">xhdpi</th>
 </tr>
 <tr><th scope="row">small</th> 
-<td></td> <!-- ldpi -->
-<td></td> <!-- mdpi -->
-<td>3.2%</td> <!-- hdpi -->
-<td></td> <!-- xhdpi -->
+<td></td>     <!-- small/ldpi -->
+<td></td>     <!-- small/mdpi -->
+<td>3.3%</td> <!-- small/hdpi -->
+<td></td>     <!-- small/xhdpi -->
 </tr> 
 <tr><th scope="row">normal</th> 
-<td>1.2%</td> <!-- ldpi -->
-<td>17.1%</td> <!-- mdpi -->
-<td>75.5%</td> <!-- hdpi -->
-<td></td> <!-- xhdpi -->
+<td>1%</td>  <!-- normal/ldpi -->
+<td>17%</td> <!-- normal/mdpi -->
+<td>75%</td> <!-- normal/hdpi -->
+<td></td>      <!-- normal/xhdpi -->
 </tr> 
 <tr><th scope="row">large</th> 
-<td></td> <!-- ldpi -->
-<td>2.6%</td> <!-- mdpi -->
-<td></td> <!-- hdpi -->
-<td></td> <!-- xhdpi -->
+<td></td>     <!-- large/ldpi -->
+<td>2.8%</td> <!-- large/mdpi -->
+<td></td>     <!-- large/hdpi -->
+<td></td>     <!-- large/xhdpi -->
 </tr> 
 <tr><th scope="row">xlarge</th> 
-<td></td> <!-- ldpi -->
-<td>0.5%</td> <!-- mdpi -->
-<td></td> <!-- hdpi -->
-<td></td> <!-- xhdpi -->
+<td></td>     <!-- xlarge/ldpi -->
+<td>0.9%</td> <!-- xlarge/mdpi -->
+<td></td>     <!-- xlarge/hdpi -->
+<td></td>     <!-- xlarge/xhdpi -->
 </tr> 
 </table>
 
-<p><em>Data collected during a 7-day period ending on May 6, 2011</em></p>
+<p><em>Data collected during a 7-day period ending on July 1, 2011</em></p>
 </div>
 
diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js
index e8c9ae7..0fc10bf 100644
--- a/docs/html/resources/resources-data.js
+++ b/docs/html/resources/resources-data.js
@@ -726,6 +726,16 @@
       en: 'Binding data to views using XML Adapters examples.'
     }
   },
+  {
+    tags: ['sample', 'new', 'accessibility'],
+    path: 'samples/TtsEngine/index.html',
+    title: {
+      en: 'Text To Speech Engine'
+    },
+    description: {
+      en: 'An example Text To Speech engine written using the android text to speech engine API.'
+    }
+  },
 
 /////////////////
 /// TUTORIALS ///
diff --git a/docs/html/resources/tutorials/views/hello-spinner.jd b/docs/html/resources/tutorials/views/hello-spinner.jd
index 7a3a9c3..e9dc20f 100644
--- a/docs/html/resources/tutorials/views/hello-spinner.jd
+++ b/docs/html/resources/tutorials/views/hello-spinner.jd
@@ -105,7 +105,7 @@
 
     public void onItemSelected(AdapterView&lt;?> parent,
         View view, int pos, long id) {
-      Toast.makeText(parent.getContext()), "The planet is " +
+      Toast.makeText(parent.getContext(), "The planet is " +
           parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
     }
 
diff --git a/docs/html/sdk/android-3.1-highlights.jd b/docs/html/sdk/android-3.1-highlights.jd
index 3d132a3..88bc1ee 100644
--- a/docs/html/sdk/android-3.1-highlights.jd
+++ b/docs/html/sdk/android-3.1-highlights.jd
@@ -143,8 +143,8 @@
 <p>To make the platform even better for gaming, Android 3.1 adds support for
 most PC joysticks and gamepads that are connected over USB or Bluetooth HID.</p>
 
-<p>For example, users can connect Sony Playstation&trade; 3 and XBox 360&trade; game
-controllers over USB (but not Bluetooth), Logitech Dual Action&trade; gamepads and
+<p>For example, users can connect PlayStation<sup>&reg;</sup>3 and Xbox 360<sup>&reg;</sup>
+game controllers over USB (but not Bluetooth), Logitech Dual Action&trade; gamepads and
 flight sticks, or a car racing controller. Game controllers that use proprietary
 networking or pairing are not supported by default, but in general, the platform
 supports most PC-connectible joysticks and gamepads.</p>
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index 935bf63..18f47a6 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -1,8 +1,8 @@
 page.title=ADT Plugin for Eclipse
-adt.zip.version=11.0.0
-adt.zip.download=ADT-11.0.0.zip
-adt.zip.bytes=TODO
-adt.zip.checksum=TODO
+adt.zip.version=12.0.0
+adt.zip.download=ADT-12.0.0.zip
+adt.zip.bytes=5651973
+adt.zip.checksum=8ad85d0f3da4a2b8dadfddcc2d66dbcb
 
 @jd:body
 
@@ -95,13 +95,64 @@
 </style>
 
 
-
 <div class="toggleable opened">
   <a href="#" onclick="return toggleDiv(this)">
         <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px"
 width="9px" />
+ADT 12.0.0</a> <em>(July 2011)</em>
+  <div class="toggleme">
+<dl>
+
+<dt>Dependencies:</dt>
+
+<dd>ADT 12.0.0 is designed for use with <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r12</a>. If you haven't
+already installed SDK Tools r12 into your SDK, use
+the Android SDK and AVD Manager to do so.</dd>
+
+<dt>Visual Layout Editor:</dt>
+<dd>
+<ul>
+  <li>New RelativeLayout drop support with guideline suggestions for
+   attachments and cycle prevention
+   (<a href="http://tools.android.com/recent/revampedrelativelayoutsupport">more info</a>).</li>
+  <li>Resize support in most layouts along with
+  guideline snapping to the sizes dictated by <code>wrap_content</code> and <code>match_parent</code>.
+  In LinearLayout, sizes are mapped to weights instead of pixel widths.
+  (<a href="http://tools.android.com/recent/resizesupport">more info</a>).</li>
+  <li>Previews of drawables and colors in the resource chooser dialogs
+  (<a href="http://tools.android.com/recent/imageandcolorpreviews">more info</a>).</li>
+  <li>Improved error messages and links for rendering errors including
+  detection of misspelled class names
+  (<a href="http://tools.android.com/recent/improvedrenderingerrordiagnostics">more info</a>).</li>
+</ul>
+</dd>
+
+<dt>Build system</dt>
+<dd>
+<ul>
+  <li>A new option lets you disable the packaging step in the automatic
+  builders. This improves performance when saving files by not
+  performing a full build, which can take a long time for large projects.
+  If the option is enabled, the APK is packaged when the
+  application is deployed to a device or emulator or when the
+  release APK is exported (<a href="http://tools.android.com/recent/finercontroloveradtbuildprocess">more info</a>).</li>
+</ul>
+</dd>
+
+<dt>Bug fixes</dt>
+<dd>Many bug fixes are part of this release
+(<a href="http://tools.android.com/recent/adt12bugfixroundup">more info</a>).</dd>
+
+</div>
+</div>
+
+
+<div class="toggleable closed">
+  <a href="#" onclick="return toggleDiv(this)">
+        <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px"
+width="9px" />
 ADT 11.0.0</a> <em>(June 2011)</em>
-  <dd class="toggleme">
+  <div class="toggleme">
 
 <dl>
 
@@ -229,6 +280,9 @@
 </div>
 
 
+
+
+
 <div class="toggleable closed">
   <a href="#" onclick="return toggleDiv(this)">
         <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px"
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index e7b8fbb..5cf37c1 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -1,21 +1,21 @@
 page.title=Android SDK
 sdk.redirect=0
 
-sdk.win_installer=installer_r11-windows.exe
-sdk.win_installer_bytes=32883649
-sdk.win_installer_checksum=3dc8a29ae5afed97b40910ef153caa2b
+sdk.win_installer=installer_r12-windows.exe
+sdk.win_installer_bytes=36531492
+sdk.win_installer_checksum=367f0ed4ecd70aefc290d1f7dcb578ab
 
-sdk.win_download=android-sdk_r11-windows.zip
-sdk.win_bytes=32837554
-sdk.win_checksum=0a2c52b8f8d97a4871ce8b3eb38e3072
+sdk.win_download=android-sdk_r12-windows.zip
+sdk.win_bytes=36486190
+sdk.win_checksum=8d6c104a34cd2577c5506c55d981aebf
 
-sdk.mac_download=android-sdk_r11-mac_x86.zip
-sdk.mac_bytes=28844968
-sdk.mac_checksum=85bed5ed25aea51f6a447a674d637d1e
+sdk.mac_download=android-sdk_r12-mac_x86.zip
+sdk.mac_bytes=30231118
+sdk.mac_checksum=341544e4572b4b1afab123ab817086e7
 
-sdk.linux_download=android-sdk_r11-linux_x86.tgz
-sdk.linux_bytes=26984929
-sdk.linux_checksum=026c67f82627a3a70efb197ca3360d0a
+sdk.linux_download=android-sdk_r12-linux_x86.tgz
+sdk.linux_bytes=30034243
+sdk.linux_checksum=f8485275a8dee3d1929936ed538ee99a
 
 @jd:body
 
diff --git a/docs/html/sdk/oem-usb.jd b/docs/html/sdk/oem-usb.jd
index 27e742a..3c2ba8b 100644
--- a/docs/html/sdk/oem-usb.jd
+++ b/docs/html/sdk/oem-usb.jd
@@ -80,6 +80,12 @@
     <td><a href="http://www.kyocera-wireless.com/support/phone_drivers.htm">http://www.kyocera-wireless.com/support/phone_drivers.htm</a>
     </td>
   </tr>
+  <tr>
+    <td>Lenevo</td>
+    <td><a href="http://developer.lenovomm.com/developer/download.jsp"
+        >http://developer.lenovomm.com/developer/download.jsp</a>
+    </td>
+  </tr>
   <tr><td>LGE</td>	<td><a
 href="http://www.lg.com/us/mobile-phones/mobile-support/mobile-lg-mobile-phone-support.jsp">http://www.lg.com/us/mobile-phones/mobile-support/mobile-lg-mobile-phone-support.jsp</a></td>
 </tr><tr><td>Motorola</td>	<td><a
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index d02c13d..0607aad 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -134,7 +134,7 @@
       </li>
     </ul>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r11</a> <span
+      <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r12</a> <span
 class="new">new!</span></li>
       <li><a href="<?cs var:toroot ?>sdk/win-usb.html">Google USB Driver, r4</a></li>
       <li><a href="<?cs var:toroot ?>sdk/compatibility-library.html">Compatibility Library, r2</a> <span
@@ -153,7 +153,7 @@
       <span style="display:none" class="zh-TW"></span>
       </h2>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 11.0.0
+      <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 12.0.0
       <span style="display:none" class="de"></span>
       <span style="display:none" class="es"></span>
       <span style="display:none" class="fr"></span>
diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd
index 64c8f2a..8c4d037 100644
--- a/docs/html/sdk/tools-notes.jd
+++ b/docs/html/sdk/tools-notes.jd
@@ -62,9 +62,36 @@
 }
 </style>
 
+
 <div class="toggleable opened">
   <a href="#" onclick="return toggleDiv(this)">
         <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" />
+SDK Tools, Revision 12</a> <em>(July 2011)</em>
+  <div class="toggleme">
+  <dl>
+<dt>Dependencies:</dt>
+<dd>
+<p>If you are developing in Eclipse with ADT, note that the SDK Tools r12 is designed for use with
+ADT 12.0.0 and later. If you haven't already, we highly recommend updating your <a
+href="{@docRoot}sdk/eclipse-adt.html">ADT Plugin</a> to 12.0.0.</p>
+
+<p>If you are developing outside Eclipse, you must have <a href="http://ant.apache.org/">Apache
+Ant</a> 1.8 or later.</p>
+
+<dt>General notes:</dt>
+<dd>
+  <ul>
+    <li>The AVD manager and emulator can now use system images
+    compiled for ARM v7 and x86 CPUs.</li>
+  </ul>
+</dd>
+</dl>
+</div>
+</div>
+
+<div class="toggleable closed">
+  <a href="#" onclick="return toggleDiv(this)">
+        <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px" />
 SDK Tools, Revision 11</a> <em>(May 2011)</em>
   <div class="toggleme">
   <dl>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 12dc93c..40d54bb 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -681,7 +681,8 @@
      */
     public enum CompressFormat {
         JPEG    (0),
-        PNG     (1);
+        PNG     (1),
+        WEBP    (2);
 
         CompressFormat(int nativeInt) {
             this.nativeInt = nativeInt;
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 0b488c9..5b50f8f 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -73,7 +73,11 @@
      * @hide
      */
     public static final int DIRECTION_RTL = 1;
-    
+
+    // Maximum bitmap size as defined in Skia's native code
+    // (see SkCanvas.cpp, SkDraw.cpp)
+    private static final int MAXMIMUM_BITMAP_SIZE = 32766;
+
     // This field is used to finalize the native Canvas properly
     @SuppressWarnings({"UnusedDeclaration"})
     private final CanvasFinalizer mFinalizer;
@@ -259,7 +263,29 @@
     public void setScreenDensity(int density) {
         mScreenDensity = density;
     }
+
+    /**
+     * Returns the maximum allowed width for bitmaps drawn with this canvas.
+     * Attempting to draw with a bitmap wider than this value will result
+     * in an error.
+     * 
+     * @see #getMaximumBitmapHeight() 
+     */
+    public int getMaximumBitmapWidth() {
+        return MAXMIMUM_BITMAP_SIZE;
+    }
     
+    /**
+     * Returns the maximum allowed height for bitmaps drawn with this canvas.
+     * Attempting to draw with a bitmap taller than this value will result
+     * in an error.
+     * 
+     * @see #getMaximumBitmapWidth() 
+     */
+    public int getMaximumBitmapHeight() {
+        return MAXMIMUM_BITMAP_SIZE;
+    }
+
     // the SAVE_FLAG constants must match their native equivalents
 
     /** restore the current matrix when restore() is called */
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 1324431..c5d7500 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -40,6 +40,7 @@
      */
     public Region rects;
     private boolean mDetectSimplePaths;
+    private Direction mLastDirection = null;
 
     /**
      * Create an empty path
@@ -70,6 +71,7 @@
     public void reset() {
         isSimplePath = true;
         if (mDetectSimplePaths) {
+            mLastDirection = null;
             if (rects != null) rects.setEmpty();
         }
         native_reset(mNativePath);
@@ -82,6 +84,7 @@
     public void rewind() {
         isSimplePath = true;
         if (mDetectSimplePaths) {
+            mLastDirection = null;
             if (rects != null) rects.setEmpty();
         }
         native_rewind(mNativePath);
@@ -378,6 +381,20 @@
         final int nativeInt;
     }
     
+    private void detectSimplePath(float left, float top, float right, float bottom, Direction dir) {
+        if (mDetectSimplePaths) {
+            if (mLastDirection == null) {
+                mLastDirection = dir;
+            }
+            if (mLastDirection != dir) {
+                isSimplePath = false;
+            } else {
+                if (rects == null) rects = new Region();
+                rects.op((int) left, (int) top, (int) right, (int) bottom, Region.Op.UNION);
+            }
+        }
+    }
+
     /**
      * Add a closed rectangle contour to the path
      *
@@ -388,11 +405,7 @@
         if (rect == null) {
             throw new NullPointerException("need rect parameter");
         }
-        if (mDetectSimplePaths) {
-            if (rects == null) rects = new Region();
-            rects.op((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom,
-                    Region.Op.UNION);
-        }
+        detectSimplePath(rect.left, rect.top, rect.right, rect.bottom, dir);
         native_addRect(mNativePath, rect, dir.nativeInt);
     }
 
@@ -406,10 +419,7 @@
      * @param dir    The direction to wind the rectangle's contour
      */
     public void addRect(float left, float top, float right, float bottom, Direction dir) {
-        if (mDetectSimplePaths) {
-            if (rects == null) rects = new Region();
-            rects.op((int) left, (int) top, (int) right, (int) bottom, Region.Op.UNION);
-        }
+        detectSimplePath(left, top, right, bottom, dir);
         native_addRect(mNativePath, left, top, right, bottom, dir.nativeInt);
     }
 
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index adb6eac..1647ff3 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -144,10 +144,6 @@
      */
     public void updateTexImage() {
         nativeUpdateTexImage();
-        if (nativeGetQueuedCount() > 0) {
-            Message m = mEventHandler.obtainMessage();
-            mEventHandler.sendMessage(m);
-        }
     }
 
     /**
@@ -178,12 +174,15 @@
      * Retrieve the timestamp associated with the texture image set by the most recent call to
      * updateTexImage.
      *
-     * This timestamp is in nanoseconds, and is guaranteed to be monotonically increasing. The
+     * This timestamp is in nanoseconds, and is normally monotonically increasing. The timestamp
+     * should be unaffected by time-of-day adjustments, and for a camera should be strictly
+     * monotonic but for a MediaPlayer may be reset when the position is set.  The
      * specific meaning and zero point of the timestamp depends on the source providing images to
      * the SurfaceTexture. Unless otherwise specified by the image source, timestamps cannot
      * generally be compared across SurfaceTexture instances, or across multiple program
      * invocations. It is mostly useful for determining time offsets between subsequent frames.
      */
+
     public long getTimestamp() {
         return nativeGetTimestamp();
     }
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index a9414e8..b0f7fd3 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -167,6 +167,7 @@
         }
         if (mCurrDrawable != null) {
             mCurrDrawable.jumpToCurrentState();
+            mCurrDrawable.setAlpha(mAlpha);
         }
         if (mExitAnimationEnd != 0) {
             mExitAnimationEnd = 0;
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index e900584..6254192 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -67,6 +67,22 @@
     Type mType;
     Bitmap mBitmap;
     int mUsage;
+    Allocation mAdaptedAllocation;
+
+    boolean mConstrainedLOD;
+    boolean mConstrainedFace;
+    boolean mConstrainedY;
+    boolean mConstrainedZ;
+    int mSelectedY;
+    int mSelectedZ;
+    int mSelectedLOD;
+    Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X;
+
+    int mCurrentDimX;
+    int mCurrentDimY;
+    int mCurrentDimZ;
+    int mCurrentCount;
+
 
     /**
      * The usage of the allocation.  These signal to renderscript
@@ -139,6 +155,19 @@
         }
     }
 
+    private void updateCacheInfo(Type t) {
+        mCurrentDimX = t.getX();
+        mCurrentDimY = t.getY();
+        mCurrentDimZ = t.getZ();
+        mCurrentCount = mCurrentDimX;
+        if (mCurrentDimY > 1) {
+            mCurrentCount *= mCurrentDimY;
+        }
+        if (mCurrentDimZ > 1) {
+            mCurrentCount *= mCurrentDimZ;
+        }
+    }
+
     Allocation(int id, RenderScript rs, Type t, int usage) {
         super(id, rs);
         if ((usage & ~(USAGE_SCRIPT |
@@ -149,6 +178,10 @@
             throw new RSIllegalArgumentException("Unknown usage specified.");
         }
         mType = t;
+
+        if (t != null) {
+            updateCacheInfo(t);
+        }
     }
 
     private void validateIsInt32() {
@@ -210,6 +243,7 @@
         if(typeID != 0) {
             mType = new Type(typeID, mRS);
             mType.updateFromNative();
+            updateCacheInfo(mType);
         }
     }
 
@@ -234,15 +268,15 @@
     public void copyFrom(BaseObj[] d) {
         mRS.validate();
         validateIsObject();
-        if (d.length != mType.getCount()) {
+        if (d.length != mCurrentCount) {
             throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " +
-                                                 mType.getCount() + ", array length = " + d.length);
+                                                 mCurrentCount + ", array length = " + d.length);
         }
         int i[] = new int[d.length];
         for (int ct=0; ct < d.length; ct++) {
             i[ct] = d[ct].getID();
         }
-        copy1DRangeFromUnchecked(0, mType.getCount(), i);
+        copy1DRangeFromUnchecked(0, mCurrentCount, i);
     }
 
     private void validateBitmapFormat(Bitmap b) {
@@ -292,8 +326,7 @@
     }
 
     private void validateBitmapSize(Bitmap b) {
-        if(mType.getX() != b.getWidth() ||
-           mType.getY() != b.getHeight()) {
+        if((mCurrentDimX != b.getWidth()) || (mCurrentDimY != b.getHeight())) {
             throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
         }
     }
@@ -307,7 +340,7 @@
      */
     public void copyFromUnchecked(int[] d) {
         mRS.validate();
-        copy1DRangeFromUnchecked(0, mType.getCount(), d);
+        copy1DRangeFromUnchecked(0, mCurrentCount, d);
     }
     /**
      * Copy an allocation from an array.  This variant is not type
@@ -318,7 +351,7 @@
      */
     public void copyFromUnchecked(short[] d) {
         mRS.validate();
-        copy1DRangeFromUnchecked(0, mType.getCount(), d);
+        copy1DRangeFromUnchecked(0, mCurrentCount, d);
     }
     /**
      * Copy an allocation from an array.  This variant is not type
@@ -329,7 +362,7 @@
      */
     public void copyFromUnchecked(byte[] d) {
         mRS.validate();
-        copy1DRangeFromUnchecked(0, mType.getCount(), d);
+        copy1DRangeFromUnchecked(0, mCurrentCount, d);
     }
     /**
      * Copy an allocation from an array.  This variant is not type
@@ -340,7 +373,7 @@
      */
     public void copyFromUnchecked(float[] d) {
         mRS.validate();
-        copy1DRangeFromUnchecked(0, mType.getCount(), d);
+        copy1DRangeFromUnchecked(0, mCurrentCount, d);
     }
 
     /**
@@ -352,7 +385,7 @@
      */
     public void copyFrom(int[] d) {
         mRS.validate();
-        copy1DRangeFrom(0, mType.getCount(), d);
+        copy1DRangeFrom(0, mCurrentCount, d);
     }
 
     /**
@@ -364,7 +397,7 @@
      */
     public void copyFrom(short[] d) {
         mRS.validate();
-        copy1DRangeFrom(0, mType.getCount(), d);
+        copy1DRangeFrom(0, mCurrentCount, d);
     }
 
     /**
@@ -376,7 +409,7 @@
      */
     public void copyFrom(byte[] d) {
         mRS.validate();
-        copy1DRangeFrom(0, mType.getCount(), d);
+        copy1DRangeFrom(0, mCurrentCount, d);
     }
 
     /**
@@ -388,7 +421,7 @@
      */
     public void copyFrom(float[] d) {
         mRS.validate();
-        copy1DRangeFrom(0, mType.getCount(), d);
+        copy1DRangeFrom(0, mCurrentCount, d);
     }
 
     /**
@@ -420,8 +453,7 @@
             throw new RSIllegalArgumentException("Field packer length " + data.length +
                                                " not divisible by element size " + eSize + ".");
         }
-        data1DChecks(xoff, count, data.length, data.length);
-        mRS.nAllocationData1D(getID(), xoff, 0, count, data, data.length);
+        copy1DRangeFromUnchecked(xoff, count, data);
     }
 
     /**
@@ -448,7 +480,8 @@
                                                " does not match component size " + eSize + ".");
         }
 
-        mRS.nAllocationElementData1D(getID(), xoff, 0, component_number, data, data.length);
+        mRS.nAllocationElementData1D(getID(), xoff, mSelectedLOD,
+                                     component_number, data, data.length);
     }
 
     private void data1DChecks(int off, int count, int len, int dataSize) {
@@ -459,11 +492,11 @@
         if(count < 1) {
             throw new RSIllegalArgumentException("Count must be >= 1.");
         }
-        if((off + count) > mType.getCount()) {
-            throw new RSIllegalArgumentException("Overflow, Available count " + mType.getCount() +
+        if((off + count) > mCurrentCount) {
+            throw new RSIllegalArgumentException("Overflow, Available count " + mCurrentCount +
                                                ", got " + count + " at offset " + off + ".");
         }
-        if((len) < dataSize) {
+        if(len < dataSize) {
             throw new RSIllegalArgumentException("Array too small for allocation type.");
         }
     }
@@ -494,7 +527,7 @@
     public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
         int dataSize = mType.mElement.getSizeBytes() * count;
         data1DChecks(off, count, d.length * 4, dataSize);
-        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
+        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
     }
     /**
      * Copy part of an allocation from an array.  This variant is
@@ -508,7 +541,7 @@
     public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
         int dataSize = mType.mElement.getSizeBytes() * count;
         data1DChecks(off, count, d.length * 2, dataSize);
-        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
+        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
     }
     /**
      * Copy part of an allocation from an array.  This variant is
@@ -522,7 +555,7 @@
     public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
         int dataSize = mType.mElement.getSizeBytes() * count;
         data1DChecks(off, count, d.length, dataSize);
-        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
+        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
     }
     /**
      * Copy part of an allocation from an array.  This variant is
@@ -536,7 +569,7 @@
     public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
         int dataSize = mType.mElement.getSizeBytes() * count;
         data1DChecks(off, count, d.length * 4, dataSize);
-        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
+        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
     }
 
     /**
@@ -606,21 +639,25 @@
      */
     public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
         mRS.nAllocationData2D(getID(), off, 0,
-                              0, Type.CubemapFace.POSITIVE_X.mID,
+                              mSelectedLOD, mSelectedFace.mID,
                               count, 1, data.getID(), dataOff, 0,
-                              0, Type.CubemapFace.POSITIVE_X.mID);
+                              data.mSelectedLOD, data.mSelectedFace.mID);
     }
 
     private void validate2DRange(int xoff, int yoff, int w, int h) {
-        if (xoff < 0 || yoff < 0) {
-            throw new RSIllegalArgumentException("Offset cannot be negative.");
-        }
-        if (h < 0 || w < 0) {
-            throw new RSIllegalArgumentException("Height or width cannot be negative.");
-        }
-        if ((xoff + w) > mType.mDimX ||
-            (yoff + h) > mType.mDimY) {
-            throw new RSIllegalArgumentException("Updated region larger than allocation.");
+        if (mAdaptedAllocation != null) {
+
+        } else {
+
+            if (xoff < 0 || yoff < 0) {
+                throw new RSIllegalArgumentException("Offset cannot be negative.");
+            }
+            if (h < 0 || w < 0) {
+                throw new RSIllegalArgumentException("Height or width cannot be negative.");
+            }
+            if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
+                throw new RSIllegalArgumentException("Updated region larger than allocation.");
+            }
         }
     }
 
@@ -637,25 +674,29 @@
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
         mRS.validate();
         validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length);
+        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+                              w, h, data, data.length);
     }
 
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
         mRS.validate();
         validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 2);
+        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+                              w, h, data, data.length * 2);
     }
 
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
         mRS.validate();
         validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4);
+        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+                              w, h, data, data.length * 4);
     }
 
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
         mRS.validate();
         validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4);
+        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
+                              w, h, data, data.length * 4);
     }
 
     /**
@@ -675,9 +716,9 @@
         mRS.validate();
         validate2DRange(xoff, yoff, w, h);
         mRS.nAllocationData2D(getID(), xoff, yoff,
-                              0, Type.CubemapFace.POSITIVE_X.mID,
+                              mSelectedLOD, mSelectedFace.mID,
                               w, h, data.getID(), dataXoff, dataYoff,
-                              0, Type.CubemapFace.POSITIVE_X.mID);
+                              data.mSelectedLOD, data.mSelectedFace.mID);
     }
 
     /**
@@ -693,7 +734,7 @@
         mRS.validate();
         validateBitmapFormat(data);
         validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
-        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, data);
+        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
     }
 
 
@@ -750,6 +791,7 @@
         int typeID = mRS.nAllocationGetType(getID());
         mType = new Type(typeID, mRS);
         mType.updateFromNative();
+        updateCacheInfo(mType);
     }
 
     /*
diff --git a/graphics/java/android/renderscript/AllocationAdapter.java b/graphics/java/android/renderscript/AllocationAdapter.java
index 77dd86a..ca5246a 100644
--- a/graphics/java/android/renderscript/AllocationAdapter.java
+++ b/graphics/java/android/renderscript/AllocationAdapter.java
@@ -17,228 +17,92 @@
 package android.renderscript;
 
 import android.content.res.Resources;
-import android.content.res.AssetManager;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.util.Log;
 import android.util.TypedValue;
 
 /**
  *
  **/
 public class AllocationAdapter extends Allocation {
-    private boolean mConstrainedLOD;
-    private boolean mConstrainedFace;
-    private boolean mConstrainedY;
-    private boolean mConstrainedZ;
-
-    private int mSelectedDimX;
-    private int mSelectedDimY;
-    private int mSelectedDimZ;
-    private int mSelectedCount;
-    private Allocation mAlloc;
-
-    private int mSelectedLOD = 0;
-    private Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X;
-
     AllocationAdapter(int id, RenderScript rs, Allocation alloc) {
-        super(id, rs, null, alloc.mUsage);
-        mAlloc = alloc;
+        super(id, rs, alloc.mType, alloc.mUsage);
+        mAdaptedAllocation = alloc;
     }
 
-
     int getID() {
-        return mAlloc.getID();
+        return mAdaptedAllocation.getID();
     }
 
-    public void copyFrom(BaseObj[] d) {
-        mRS.validate();
-        if (d.length != mSelectedCount) {
-            throw new RSIllegalArgumentException("Array size mismatch, allocation size = " +
-                                                 mSelectedCount + ", array length = " + d.length);
-        }
-        int i[] = new int[d.length];
-        for (int ct=0; ct < d.length; ct++) {
-            i[ct] = d[ct].getID();
-        }
-        subData1D(0, mAlloc.mType.getCount(), i);
-    }
-
-    void validateBitmap(Bitmap b) {
-        mRS.validate();
-        if(mSelectedDimX != b.getWidth() ||
-           mSelectedDimY != b.getHeight()) {
-            throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
-        }
-    }
-
-    public void copyFrom(int[] d) {
-        mRS.validate();
-        subData1D(0, mSelectedCount, d);
-    }
-    public void copyFrom(short[] d) {
-        mRS.validate();
-        subData1D(0, mSelectedCount, d);
-    }
-    public void copyFrom(byte[] d) {
-        mRS.validate();
-        subData1D(0, mSelectedCount, d);
-    }
-    public void copyFrom(float[] d) {
-        mRS.validate();
-        subData1D(0, mSelectedCount, d);
-    }
-    public void copyFrom(Bitmap b) {
-        validateBitmap(b);
-        mRS.nAllocationCopyFromBitmap(getID(), b);
-    }
-
-    public void copyTo(Bitmap b) {
-        validateBitmap(b);
-        mRS.nAllocationCopyToBitmap(getID(), b);
-    }
-
-
+    /**
+     * @hide
+     */
     public void subData(int xoff, FieldPacker fp) {
-        int eSize = mAlloc.mType.mElement.getSizeBytes();
-        final byte[] data = fp.getData();
-
-        int count = data.length / eSize;
-        if ((eSize * count) != data.length) {
-            throw new RSIllegalArgumentException("Field packer length " + data.length +
-                                               " not divisible by element size " + eSize + ".");
-        }
-        data1DChecks(xoff, count, data.length, data.length);
-        mRS.nAllocationData1D(getID(), xoff, mSelectedLOD, count, data, data.length);
+        super.setFromFieldPacker(xoff, fp);
     }
-
-
+    /**
+     * @hide
+     */
     public void subElementData(int xoff, int component_number, FieldPacker fp) {
-        if (component_number >= mAlloc.mType.mElement.mElements.length) {
-            throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
-        }
-        if(xoff < 0) {
-            throw new RSIllegalArgumentException("Offset must be >= 0.");
-        }
-
-        final byte[] data = fp.getData();
-        int eSize = mAlloc.mType.mElement.mElements[component_number].getSizeBytes();
-
-        if (data.length != eSize) {
-            throw new RSIllegalArgumentException("Field packer sizelength " + data.length +
-                                               " does not match component size " + eSize + ".");
-        }
-
-        mRS.nAllocationElementData1D(getID(), xoff, mSelectedLOD, component_number, data, data.length);
+        super.setFromFieldPacker(xoff, component_number, fp);
     }
-
-    void data1DChecks(int off, int count, int len, int dataSize) {
-        mRS.validate();
-        if(off < 0) {
-            throw new RSIllegalArgumentException("Offset must be >= 0.");
-        }
-        if(count < 1) {
-            throw new RSIllegalArgumentException("Count must be >= 1.");
-        }
-        if((off + count) > mSelectedCount) {
-            throw new RSIllegalArgumentException("Overflow, Available count " + mAlloc.mType.getCount() +
-                                               ", got " + count + " at offset " + off + ".");
-        }
-        if((len) < dataSize) {
-            throw new RSIllegalArgumentException("Array too small for allocation type.  len = " +
-                                                 len + ", dataSize = " + dataSize);
-        }
-    }
-
+    /**
+     * @hide
+     */
     public void subData1D(int off, int count, int[] d) {
-        int dataSize = mAlloc.mType.mElement.getSizeBytes() * count;
-        data1DChecks(off, count, d.length * 4, dataSize);
-        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+        super.copy1DRangeFrom(off, count, d);
     }
+    /**
+     * @hide
+     */
     public void subData1D(int off, int count, short[] d) {
-        int dataSize = mAlloc.mType.mElement.getSizeBytes() * count;
-        data1DChecks(off, count, d.length * 2, dataSize);
-        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+        super.copy1DRangeFrom(off, count, d);
     }
+    /**
+     * @hide
+     */
     public void subData1D(int off, int count, byte[] d) {
-        int dataSize = mAlloc.mType.mElement.getSizeBytes() * count;
-        data1DChecks(off, count, d.length, dataSize);
-        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+        super.copy1DRangeFrom(off, count, d);
     }
+    /**
+     * @hide
+     */
     public void subData1D(int off, int count, float[] d) {
-        int dataSize = mAlloc.mType.mElement.getSizeBytes() * count;
-        data1DChecks(off, count, d.length * 4, dataSize);
-        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+        super.copy1DRangeFrom(off, count, d);
     }
-
     /**
-     * Copy part of an allocation from another allocation.
-     *
-     * @param off The offset of the first element to be copied.
-     * @param count The number of elements to be copied.
-     * @param data the source data allocation.
-     * @param dataOff off The offset of the first element in data to
-     *          be copied.
+     * @hide
      */
-    public void subData1D(int off, int count, AllocationAdapter data, int dataOff) {
-        mRS.nAllocationData2D(getID(), off, 0,
-                              mSelectedLOD, mSelectedFace.mID,
-                              count, 1, data.getID(), dataOff, 0,
-                              data.mSelectedLOD, data.mSelectedFace.mID);
-    }
-
-
     public void subData2D(int xoff, int yoff, int w, int h, int[] d) {
-        mRS.validate();
-        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
-                              w, h, d, d.length * 4);
+        super.copy2DRangeFrom(xoff, yoff, w, h, d);
     }
-
-    public void subData2D(int xoff, int yoff, int w, int h, float[] d) {
-        mRS.validate();
-        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
-                              w, h, d, d.length * 4);
-    }
-
     /**
-     * Copy a rectangular region into the allocation from another
-     * allocation.
-     *
-     * @param xoff X offset of the region to update.
-     * @param yoff Y offset of the region to update.
-     * @param w Width of the incoming region to update.
-     * @param h Height of the incoming region to update.
-     * @param data source allocation.
-     * @param dataXoff X offset in data of the region to update.
-     * @param dataYoff Y offset in data of the region to update.
+     * @hide
      */
-    public void subData2D(int xoff, int yoff, int w, int h,
-                          AllocationAdapter data, int dataXoff, int dataYoff) {
-        mRS.validate();
-        mRS.nAllocationData2D(getID(), xoff, yoff,
-                              mSelectedLOD, mSelectedFace.mID,
-                              w, h, data.getID(), dataXoff, dataYoff,
-                              data.mSelectedLOD, data.mSelectedFace.mID);
+    public void subData2D(int xoff, int yoff, int w, int h, float[] d) {
+        super.copy2DRangeFrom(xoff, yoff, w, h, d);
     }
-
+    /**
+     * @hide
+     */
     public void readData(int[] d) {
-        mRS.validate();
-        mRS.nAllocationRead(getID(), d);
+        super.copyTo(d);
     }
-
+    /**
+     * @hide
+     */
     public void readData(float[] d) {
-        mRS.validate();
-        mRS.nAllocationRead(getID(), d);
+        super.copyTo(d);
     }
 
-    private void initLOD(int lod) {
+    void initLOD(int lod) {
         if (lod < 0) {
             throw new RSIllegalArgumentException("Attempting to set negative lod (" + lod + ").");
         }
 
-        int tx = mAlloc.mType.getX();
-        int ty = mAlloc.mType.getY();
-        int tz = mAlloc.mType.getZ();
+        int tx = mAdaptedAllocation.mType.getX();
+        int ty = mAdaptedAllocation.mType.getY();
+        int tz = mAdaptedAllocation.mType.getZ();
 
         for (int ct=0; ct < lod; ct++) {
             if ((tx==1) && (ty == 1) && (tz == 1)) {
@@ -250,25 +114,31 @@
             if (tz > 1) tz >>= 1;
         }
 
-        mSelectedDimX = tx;
-        mSelectedDimY = ty;
-        mSelectedCount = tx;
-        if (ty > 1) {
-            mSelectedCount *= ty;
+        mCurrentDimX = tx;
+        mCurrentDimY = ty;
+        mCurrentDimZ = tz;
+        mCurrentCount = mCurrentDimX;
+        if (mCurrentDimY > 1) {
+            mCurrentCount *= mCurrentDimY;
         }
-        if (tz > 1) {
-            mSelectedCount *= tz;
+        if (mCurrentDimZ > 1) {
+            mCurrentCount *= mCurrentDimZ;
         }
+        mSelectedY = 0;
+        mSelectedZ = 0;
     }
 
     /**
      * Set the active LOD.  The LOD must be within the range for the
-     * type being adapted.
+     * type being adapted.  The base allocation must have mipmaps.
+     *
+     * Because this changes the dimensions of the adapter the
+     * current Y and Z will be reset.
      *
      * @param lod The LOD to make active.
      */
     public void setLOD(int lod) {
-        if (!mAlloc.getType().hasMipmaps()) {
+        if (!mAdaptedAllocation.getType().hasMipmaps()) {
             throw new RSInvalidStateException("Cannot set LOD when the allocation type does not include mipmaps.");
         }
         if (!mConstrainedLOD) {
@@ -278,22 +148,81 @@
         initLOD(lod);
     }
 
+    /**
+     * Set the active Face.  The base allocation must be of a type
+     * that includes faces.
+     *
+     * @param cf The face to make active.
+     */
     public void setFace(Type.CubemapFace cf) {
+        if (!mAdaptedAllocation.getType().hasFaces()) {
+            throw new RSInvalidStateException("Cannot set Face when the allocation type does not include faces.");
+        }
+        if (!mConstrainedFace) {
+            throw new RSInvalidStateException("Cannot set LOD when the adapter includes mipmaps.");
+        }
+        if (cf == null) {
+            throw new RSIllegalArgumentException("Cannot set null face.");
+        }
+
         mSelectedFace = cf;
     }
 
+    /**
+     * Set the active Y.  The y value must be within the range for
+     * the allocation being adapted.  The base allocation must
+     * contain the Y dimension.
+     *
+     * @param y The y to make active.
+     */
     public void setY(int y) {
-        mSelectedDimY = y;
+        if (mAdaptedAllocation.getType().getY() == 0) {
+            throw new RSInvalidStateException("Cannot set Y when the allocation type does not include Y dim.");
+        }
+        if (mAdaptedAllocation.getType().getY() <= y) {
+            throw new RSInvalidStateException("Cannot set Y greater than dimension of allocation.");
+        }
+        if (!mConstrainedY) {
+            throw new RSInvalidStateException("Cannot set Y when the adapter includes Y.");
+        }
+
+        mSelectedY = y;
     }
 
+    /**
+     * Set the active Z.  The z value must be within the range for
+     * the allocation being adapted.  The base allocation must
+     * contain the Z dimension.
+     *
+     * @param z The z to make active.
+     */
     public void setZ(int z) {
+        if (mAdaptedAllocation.getType().getZ() == 0) {
+            throw new RSInvalidStateException("Cannot set Z when the allocation type does not include Z dim.");
+        }
+        if (mAdaptedAllocation.getType().getZ() <= z) {
+            throw new RSInvalidStateException("Cannot set Z greater than dimension of allocation.");
+        }
+        if (!mConstrainedZ) {
+            throw new RSInvalidStateException("Cannot set Z when the adapter includes Z.");
+        }
+
+        mSelectedZ = z;
     }
 
-    // creation
-    //static public AllocationAdapter create1D(RenderScript rs, Allocation a) {
-    //}
+    static public AllocationAdapter create1D(RenderScript rs, Allocation a) {
+        rs.validate();
+        AllocationAdapter aa = new AllocationAdapter(0, rs, a);
+        aa.mConstrainedLOD = true;
+        aa.mConstrainedFace = true;
+        aa.mConstrainedY = true;
+        aa.mConstrainedZ = true;
+        aa.initLOD(0);
+        return aa;
+    }
 
     static public AllocationAdapter create2D(RenderScript rs, Allocation a) {
+        android.util.Log.e("rs", "create2d " + a);
         rs.validate();
         AllocationAdapter aa = new AllocationAdapter(0, rs, a);
         aa.mConstrainedLOD = true;
@@ -305,6 +234,16 @@
     }
 
 
+    /**
+     * Override the Allocation resize.  Resizing adapters is not
+     * allowed and will throw a RSInvalidStateException.
+     *
+     * @param dimX ignored.
+     */
+    public synchronized void resize(int dimX) {
+        throw new RSInvalidStateException("Resize not allowed for Adapters.");
+    }
+
 }
 
 
diff --git a/graphics/java/android/renderscript/ScriptC.java b/graphics/java/android/renderscript/ScriptC.java
index f865753..90f959f 100644
--- a/graphics/java/android/renderscript/ScriptC.java
+++ b/graphics/java/android/renderscript/ScriptC.java
@@ -95,7 +95,7 @@
         // E.g, /system/apps/Fountain.apk
         //String packageName = rs.getApplicationContext().getPackageResourcePath();
         // For res/raw/fountain.bc, it wil be /com.android.fountain:raw/fountain
-        String resName = resources.getResourceName(resourceID);
+        String resName = resources.getResourceEntryName(resourceID);
         String cacheDir = rs.getApplicationContext().getCacheDir().toString();
 
         Log.v(TAG, "Create script for resource = " + resName);
diff --git a/include/binder/IMemory.h b/include/binder/IMemory.h
index 74d2cc7..2d0db00 100644
--- a/include/binder/IMemory.h
+++ b/include/binder/IMemory.h
@@ -43,6 +43,7 @@
     virtual void*       getBase() const = 0;
     virtual size_t      getSize() const = 0;
     virtual uint32_t    getFlags() const = 0;
+    virtual uint32_t    getOffset() const = 0;
 
     // these are there just for backward source compatibility
     int32_t heapID() const { return getHeapID(); }
diff --git a/include/binder/MemoryHeapBase.h b/include/binder/MemoryHeapBase.h
index 2f2e31b..bbbda9c 100644
--- a/include/binder/MemoryHeapBase.h
+++ b/include/binder/MemoryHeapBase.h
@@ -27,7 +27,7 @@
 
 // ---------------------------------------------------------------------------
 
-class MemoryHeapBase : public virtual BnMemoryHeap 
+class MemoryHeapBase : public virtual BnMemoryHeap
 {
 public:
     enum {
@@ -38,12 +38,12 @@
         NO_CACHING = 0x00000200
     };
 
-    /* 
+    /*
      * maps the memory referenced by fd. but DOESN'T take ownership
      * of the filedescriptor (it makes a copy with dup()
      */
     MemoryHeapBase(int fd, size_t size, uint32_t flags = 0, uint32_t offset = 0);
-    
+
     /*
      * maps memory from the given device
      */
@@ -61,9 +61,10 @@
     virtual void*       getBase() const;
     virtual size_t      getSize() const;
     virtual uint32_t    getFlags() const;
+    virtual uint32_t      getOffset() const;
 
     const char*         getDevice() const;
-    
+
     /* this closes this heap -- use carefully */
     void dispose();
 
@@ -74,12 +75,12 @@
             mDevice = device;
         return mDevice ? NO_ERROR : ALREADY_EXISTS;
     }
-    
+
 protected:
             MemoryHeapBase();
     // init() takes ownership of fd
     status_t init(int fd, void *base, int size,
-            int flags = 0, const char* device = NULL);    
+            int flags = 0, const char* device = NULL);
 
 private:
     status_t mapfd(int fd, size_t size, uint32_t offset = 0);
@@ -90,6 +91,7 @@
     uint32_t    mFlags;
     const char* mDevice;
     bool        mNeedUnmap;
+    uint32_t    mOffset;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/include/binder/Permission.h b/include/binder/Permission.h
deleted file mode 100644
index 9542d50..0000000
--- a/include/binder/Permission.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef BINDER_PERMISSION_H
-#define BINDER_PERMISSION_H
-
-#include <stdint.h>
-#include <unistd.h>
-
-#include <utils/SortedVector.h>
-#include <utils/String16.h>
-#include <utils/threads.h>
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-/*
- * Permission caches the result of the permission check for the given
- * permission name and the provided uid/pid. It also handles a few
- * known cases efficiently (caller is in the same process or is root).
- * The package manager does something similar but lives in dalvik world
- * and is therefore extremely slow to access.
- */
-
-class Permission
-{
-public:
-            Permission(char const* name);
-            Permission(const String16& name);
-            Permission(const Permission& rhs);
-    virtual ~Permission();
-
-    bool operator < (const Permission& rhs) const;
-
-    // checks the current binder call's caller has access to this permission
-    bool checkCalling() const;
-    
-    // checks the specified pid/uid has access to this permission
-    bool check(pid_t pid, uid_t uid) const;
-    
-protected:
-    virtual bool doCheckPermission(pid_t pid, uid_t uid) const;
-
-private:
-    Permission& operator = (const Permission& rhs) const;
-    const String16 mPermissionName;
-    mutable SortedVector<uid_t> mGranted;
-    const pid_t mPid;
-    mutable Mutex mLock;
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif /* BINDER_PERMISSION_H */
diff --git a/include/binder/PermissionCache.h b/include/binder/PermissionCache.h
new file mode 100644
index 0000000..1171d48
--- /dev/null
+++ b/include/binder/PermissionCache.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef BINDER_PERMISSION_H
+#define BINDER_PERMISSION_H
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <utils/String16.h>
+#include <utils/Singleton.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+/*
+ * PermissionCache caches permission checks for a given uid.
+ *
+ * Currently the cache is not updated when there is a permission change,
+ * for instance when an application is uninstalled.
+ *
+ * IMPORTANT: for the reason stated above, only system permissions are safe
+ * to cache. This restriction may be lifted at a later time.
+ *
+ */
+
+class PermissionCache : Singleton<PermissionCache> {
+    struct Entry {
+        String16    name;
+        uid_t       uid;
+        bool        granted;
+        inline bool operator < (const Entry& e) const {
+            return (uid == e.uid) ? (name < e.name) : (uid < e.uid);
+        }
+    };
+    mutable Mutex mLock;
+    // we pool all the permission names we see, as many permissions checks
+    // will have identical names
+    SortedVector< String16 > mPermissionNamesPool;
+    // this is our cache per say. it stores pooled names.
+    SortedVector< Entry > mCache;
+
+    // free the whole cache, but keep the permission name pool
+    void purge();
+
+    status_t check(bool* granted,
+            const String16& permission, uid_t uid) const;
+
+    void cache(const String16& permission, uid_t uid, bool granted);
+
+public:
+    PermissionCache();
+
+    static bool checkCallingPermission(const String16& permission);
+
+    static bool checkCallingPermission(const String16& permission,
+                                int32_t* outPid, int32_t* outUid);
+
+    static bool checkPermission(const String16& permission,
+            pid_t pid, uid_t uid);
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif /* BINDER_PERMISSION_H */
diff --git a/include/binder/ProcessState.h b/include/binder/ProcessState.h
index feeb3c3..9725822 100644
--- a/include/binder/ProcessState.h
+++ b/include/binder/ProcessState.h
@@ -39,8 +39,6 @@
 public:
     static  sp<ProcessState>    self();
 
-    static  void                setSingleProcess(bool singleProcess);
-
             void                setContextObject(const sp<IBinder>& object);
             sp<IBinder>         getContextObject(const sp<IBinder>& caller);
         
@@ -48,8 +46,6 @@
                                                  const String16& name);
             sp<IBinder>         getContextObject(const String16& name,
                                                  const sp<IBinder>& caller);
-                                                 
-            bool                supportsProcesses() const;
 
             void                startThreadPool();
                         
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index 7106bfa..f701280 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -18,9 +18,11 @@
 #define ANDROID_HARDWARE_CAMERA_H
 
 #include <utils/Timers.h>
-#include <camera/ICameraClient.h>
 #include <gui/ISurfaceTexture.h>
 #include <system/camera.h>
+#include <camera/ICameraClient.h>
+#include <camera/ICameraRecordingProxy.h>
+#include <camera/ICameraRecordingProxyListener.h>
 
 namespace android {
 
@@ -70,7 +72,7 @@
     static  status_t    getCameraInfo(int cameraId,
                                       struct CameraInfo* cameraInfo);
     static  sp<Camera>  connect(int cameraId);
-                        ~Camera();
+            virtual     ~Camera();
             void        init();
 
             status_t    reconnect();
@@ -129,8 +131,11 @@
             status_t    storeMetaDataInBuffers(bool enabled);
 
             void        setListener(const sp<CameraListener>& listener);
+            void        setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener);
             void        setPreviewCallbackFlags(int preview_callback_flag);
 
+            sp<ICameraRecordingProxy> getRecordingProxy();
+
     // ICameraClient interface
     virtual void        notifyCallback(int32_t msgType, int32_t ext, int32_t ext2);
     virtual void        dataCallback(int32_t msgType, const sp<IMemory>& dataPtr);
@@ -138,6 +143,20 @@
 
     sp<ICamera>         remote();
 
+    class RecordingProxy : public BnCameraRecordingProxy
+    {
+    public:
+        RecordingProxy(const sp<Camera>& camera);
+
+        // ICameraRecordingProxy interface
+        virtual status_t startRecording(const sp<ICameraRecordingProxyListener>& listener);
+        virtual void stopRecording();
+        virtual void releaseRecordingFrame(const sp<IMemory>& mem);
+
+    private:
+        sp<Camera>         mCamera;
+    };
+
 private:
                         Camera();
                         Camera(const Camera&);
@@ -162,12 +181,12 @@
             status_t            mStatus;
 
             sp<CameraListener>  mListener;
+            sp<ICameraRecordingProxyListener>  mRecordingProxyListener;
 
             friend class DeathNotifier;
 
             static  Mutex               mLock;
             static  sp<ICameraService>  mCameraService;
-
 };
 
 }; // namespace android
diff --git a/include/camera/ICameraRecordingProxy.h b/include/camera/ICameraRecordingProxy.h
new file mode 100644
index 0000000..2aac284
--- /dev/null
+++ b/include/camera/ICameraRecordingProxy.h
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_H
+#define ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_H
+
+#include <binder/IInterface.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class ICameraRecordingProxyListener;
+class IMemory;
+class Parcel;
+
+/*
+ * The purpose of ICameraRecordingProxy and ICameraRecordingProxyListener is to
+ * allow applications using the camera during recording.
+ *
+ * Camera service allows only one client at a time. Since camcorder application
+ * needs to own the camera to do things like zoom, the media recorder cannot
+ * access the camera directly during recording. So ICameraRecordingProxy is a
+ * proxy of ICamera, which allows the media recorder to start/stop the recording
+ * and release recording frames. ICameraRecordingProxyListener is an interface
+ * that allows the recorder to receive video frames during recording.
+ *
+ * ICameraRecordingProxy
+ *   startRecording()
+ *   stopRecording()
+ *   releaseRecordingFrame()
+ *
+ * ICameraRecordingProxyListener
+ *   dataCallbackTimestamp()
+
+ * The camcorder app opens the camera and starts the preview. The app passes
+ * ICamera and ICameraRecordingProxy to the media recorder by
+ * MediaRecorder::setCamera(). The recorder uses ICamera to setup the camera in
+ * MediaRecorder::start(). After setup, the recorder disconnects from camera
+ * service. The recorder calls ICameraRecordingProxy::startRecording() and
+ * passes a ICameraRecordingProxyListener to the app. The app connects back to
+ * camera service and starts the recording. The app owns the camera and can do
+ * things like zoom. The media recorder receives the video frames from the
+ * listener and releases them by ICameraRecordingProxy::releaseRecordingFrame.
+ * The recorder calls ICameraRecordingProxy::stopRecording() to stop the
+ * recording.
+ *
+ * The call sequences are as follows:
+ * 1. The app: Camera.unlock().
+ * 2. The app: MediaRecorder.setCamera().
+ * 3. Start recording
+ *    (1) The app: MediaRecorder.start().
+ *    (2) The recorder: ICamera.unlock() and ICamera.disconnect().
+ *    (3) The recorder: ICameraRecordingProxy.startRecording().
+ *    (4) The app: ICamera.reconnect().
+ *    (5) The app: ICamera.startRecording().
+ * 4. During recording
+ *    (1) The recorder: receive frames from ICameraRecordingProxyListener.dataCallbackTimestamp()
+ *    (2) The recorder: release frames by ICameraRecordingProxy.releaseRecordingFrame().
+ * 5. Stop recording
+ *    (1) The app: MediaRecorder.stop()
+ *    (2) The recorder: ICameraRecordingProxy.stopRecording().
+ *    (3) The app: ICamera.stopRecording().
+ */
+
+class ICameraRecordingProxy: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(CameraRecordingProxy);
+
+    virtual status_t        startRecording(const sp<ICameraRecordingProxyListener>& listener) = 0;
+    virtual void            stopRecording() = 0;
+    virtual void            releaseRecordingFrame(const sp<IMemory>& mem) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnCameraRecordingProxy: public BnInterface<ICameraRecordingProxy>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif
diff --git a/include/camera/ICameraRecordingProxyListener.h b/include/camera/ICameraRecordingProxyListener.h
new file mode 100644
index 0000000..b6c0624
--- /dev/null
+++ b/include/camera/ICameraRecordingProxyListener.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_LISTENER_H
+#define ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_LISTENER_H
+
+#include <binder/IInterface.h>
+#include <stdint.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+
+namespace android {
+
+class Parcel;
+class IMemory;
+
+class ICameraRecordingProxyListener: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(CameraRecordingProxyListener);
+
+    virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+                                       const sp<IMemory>& data) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnCameraRecordingProxyListener: public BnInterface<ICameraRecordingProxyListener>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index e558dfd..e36360c 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -46,11 +46,14 @@
     enum { NUM_BUFFER_SLOTS = 32 };
 
     struct FrameAvailableListener : public virtual RefBase {
-        // onFrameAvailable() is called from queueBuffer() is the FIFO is
-        // empty. You can use SurfaceTexture::getQueuedCount() to
-        // figure out if there are more frames waiting.
-        // This is called without any lock held can be called concurrently by
-        // multiple threads.
+        // onFrameAvailable() is called from queueBuffer() each time an
+        // additional frame becomes available for consumption. This means that
+        // frames that are queued while in asynchronous mode only trigger the
+        // callback if no previous frames are pending. Frames queued while in
+        // synchronous mode always trigger the callback.
+        //
+        // This is called without any lock held and can be called concurrently
+        // by multiple threads.
         virtual void onFrameAvailable() = 0;
     };
 
@@ -101,11 +104,6 @@
     // target texture belongs is bound to the calling thread.
     status_t updateTexImage();
 
-    // getqueuedCount returns the number of queued frames waiting in the
-    // FIFO. In asynchronous mode, this always returns 0 or 1 since
-    // frames are not accumulating in the FIFO.
-    size_t getQueuedCount() const;
-
     // setBufferCountServer set the buffer count. If the client has requested
     // a buffer count using setBufferCount, the server-buffer count will
     // take effect once the client sets the count back to zero.
@@ -141,7 +139,7 @@
 
     // setFrameAvailableListener sets the listener object that will be notified
     // when a new frame becomes available.
-    void setFrameAvailableListener(const sp<FrameAvailableListener>& l);
+    void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
 
     // getAllocator retrieves the binder object that must be referenced as long
     // as the GraphicBuffers dequeued from this SurfaceTexture are referenced.
@@ -345,7 +343,7 @@
     uint32_t mNextTransform;
 
     // mTexName is the name of the OpenGL texture to which streamed images will
-    // be bound when updateTexImage is called. It is set at construction time 
+    // be bound when updateTexImage is called. It is set at construction time
     // changed with a call to setTexName.
     const GLuint mTexName;
 
diff --git a/include/media/EffectBassBoostApi.h b/include/media/EffectBassBoostApi.h
deleted file mode 100644
index 56119eb..0000000
--- a/include/media/EffectBassBoostApi.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef ANDROID_EFFECTBASSBOOSTAPI_H_
-#define ANDROID_EFFECTBASSBOOSTAPI_H_
-
-#include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-#ifndef OPENSL_ES_H_
-static const effect_uuid_t SL_IID_BASSBOOST_ = { 0x0634f220, 0xddd4, 0x11db, 0xa0fc, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
-const effect_uuid_t * const SL_IID_BASSBOOST = &SL_IID_BASSBOOST_;
-#endif //OPENSL_ES_H_
-
-/* enumerated parameter settings for BassBoost effect */
-typedef enum
-{
-    BASSBOOST_PARAM_STRENGTH_SUPPORTED,
-    BASSBOOST_PARAM_STRENGTH
-} t_bassboost_params;
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
-
-#endif /*ANDROID_EFFECTBASSBOOSTAPI_H_*/
diff --git a/include/media/EffectEnvironmentalReverbApi.h b/include/media/EffectEnvironmentalReverbApi.h
deleted file mode 100644
index f11c5ec..0000000
--- a/include/media/EffectEnvironmentalReverbApi.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef ANDROID_EFFECTENVIRONMENTALREVERBAPI_H_
-#define ANDROID_EFFECTENVIRONMENTALREVERBAPI_H_
-
-#include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-#ifndef OPENSL_ES_H_
-static const effect_uuid_t SL_IID_ENVIRONMENTALREVERB_ = { 0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, { 0x4e, 0x23, 0x4d, 0x6, 0x83, 0x9e } };
-const effect_uuid_t * const SL_IID_ENVIRONMENTALREVERB = &SL_IID_ENVIRONMENTALREVERB_;
-#endif //OPENSL_ES_H_
-
-/* enumerated parameter settings for environmental reverb effect */
-typedef enum
-{
-    // Parameters below are as defined in OpenSL ES specification for environmental reverb interface
-    REVERB_PARAM_ROOM_LEVEL,            // in millibels,    range -6000 to 0
-    REVERB_PARAM_ROOM_HF_LEVEL,         // in millibels,    range -4000 to 0
-    REVERB_PARAM_DECAY_TIME,            // in milliseconds, range 100 to 20000
-    REVERB_PARAM_DECAY_HF_RATIO,        // in permilles,    range 100 to 1000
-    REVERB_PARAM_REFLECTIONS_LEVEL,     // in millibels,    range -6000 to 0
-    REVERB_PARAM_REFLECTIONS_DELAY,     // in milliseconds, range 0 to 65
-    REVERB_PARAM_REVERB_LEVEL,          // in millibels,    range -6000 to 0
-    REVERB_PARAM_REVERB_DELAY,          // in milliseconds, range 0 to 65
-    REVERB_PARAM_DIFFUSION,             // in permilles,    range 0 to 1000
-    REVERB_PARAM_DENSITY,               // in permilles,    range 0 to 1000
-    REVERB_PARAM_PROPERTIES,
-    REVERB_PARAM_BYPASS
-} t_env_reverb_params;
-
-//t_reverb_settings is equal to SLEnvironmentalReverbSettings defined in OpenSL ES specification.
-typedef struct s_reverb_settings {
-    int16_t     roomLevel;
-    int16_t     roomHFLevel;
-    uint32_t    decayTime;
-    int16_t     decayHFRatio;
-    int16_t     reflectionsLevel;
-    uint32_t    reflectionsDelay;
-    int16_t     reverbLevel;
-    uint32_t    reverbDelay;
-    int16_t     diffusion;
-    int16_t     density;
-} __attribute__((packed)) t_reverb_settings;
-
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
-
-#endif /*ANDROID_EFFECTENVIRONMENTALREVERBAPI_H_*/
diff --git a/include/media/EffectEqualizerApi.h b/include/media/EffectEqualizerApi.h
deleted file mode 100644
index 950d138..0000000
--- a/include/media/EffectEqualizerApi.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef ANDROID_EFFECTEQUALIZERAPI_H_
-#define ANDROID_EFFECTEQUALIZERAPI_H_
-
-#include <hardware/audio_effect.h>
-
-#ifndef OPENSL_ES_H_
-static const effect_uuid_t SL_IID_EQUALIZER_ = { 0x0bed4300, 0xddd6, 0x11db, 0x8f34, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
-const effect_uuid_t * const SL_IID_EQUALIZER = &SL_IID_EQUALIZER_;
-#endif //OPENSL_ES_H_
-
-#if __cplusplus
-extern "C" {
-#endif
-
-/* enumerated parameters for Equalizer effect */
-typedef enum
-{
-    EQ_PARAM_NUM_BANDS,             // Gets the number of frequency bands that the equalizer supports.
-    EQ_PARAM_LEVEL_RANGE,           // Returns the minimum and maximum band levels supported.
-    EQ_PARAM_BAND_LEVEL,            // Gets/Sets the gain set for the given equalizer band.
-    EQ_PARAM_CENTER_FREQ,           // Gets the center frequency of the given band.
-    EQ_PARAM_BAND_FREQ_RANGE,       // Gets the frequency range of the given frequency band.
-    EQ_PARAM_GET_BAND,              // Gets the band that has the most effect on the given frequency.
-    EQ_PARAM_CUR_PRESET,            // Gets/Sets the current preset.
-    EQ_PARAM_GET_NUM_OF_PRESETS,    // Gets the total number of presets the equalizer supports.
-    EQ_PARAM_GET_PRESET_NAME,       // Gets the preset name based on the index.
-    EQ_PARAM_PROPERTIES             // Gets/Sets all parameters at a time.
-} t_equalizer_params;
-
-//t_equalizer_settings groups all current equalizer setting for backup and restore.
-typedef struct s_equalizer_settings {
-    uint16_t curPreset;
-    uint16_t numBands;
-    uint16_t bandLevels[];
-} t_equalizer_settings;
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
-
-#endif /*ANDROID_EFFECTEQUALIZERAPI_H_*/
diff --git a/include/media/EffectPresetReverbApi.h b/include/media/EffectPresetReverbApi.h
deleted file mode 100644
index e5b168a..0000000
--- a/include/media/EffectPresetReverbApi.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef ANDROID_EFFECTPRESETREVERBAPI_H_
-#define ANDROID_EFFECTPRESETREVERBAPI_H_
-
-#include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-#ifndef OPENSL_ES_H_
-static const effect_uuid_t SL_IID_PRESETREVERB_ = { 0x47382d60, 0xddd8, 0x11db, 0xbf3a, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
-const effect_uuid_t * const SL_IID_PRESETREVERB = &SL_IID_PRESETREVERB_;
-#endif //OPENSL_ES_H_
-
-/* enumerated parameter settings for preset reverb effect */
-typedef enum
-{
-    REVERB_PARAM_PRESET
-} t_preset_reverb_params;
-
-
-typedef enum
-{
-    REVERB_PRESET_NONE,
-    REVERB_PRESET_SMALLROOM,
-    REVERB_PRESET_MEDIUMROOM,
-    REVERB_PRESET_LARGEROOM,
-    REVERB_PRESET_MEDIUMHALL,
-    REVERB_PRESET_LARGEHALL,
-    REVERB_PRESET_PLATE,
-    REVERB_PRESET_LAST = REVERB_PRESET_PLATE
-} t_reverb_presets;
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
-
-#endif /*ANDROID_EFFECTPRESETREVERBAPI_H_*/
diff --git a/include/media/EffectVirtualizerApi.h b/include/media/EffectVirtualizerApi.h
deleted file mode 100644
index 2e216e2..0000000
--- a/include/media/EffectVirtualizerApi.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef ANDROID_EFFECTVIRTUALIZERAPI_H_
-#define ANDROID_EFFECTVIRTUALIZERAPI_H_
-
-#include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-#ifndef OPENSL_ES_H_
-static const effect_uuid_t SL_IID_VIRTUALIZER_ = { 0x37cc2c00, 0xdddd, 0x11db, 0x8577, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
-const effect_uuid_t * const SL_IID_VIRTUALIZER = &SL_IID_VIRTUALIZER_;
-#endif //OPENSL_ES_H_
-
-/* enumerated parameter settings for virtualizer effect */
-typedef enum
-{
-    VIRTUALIZER_PARAM_STRENGTH_SUPPORTED,
-    VIRTUALIZER_PARAM_STRENGTH
-} t_virtualizer_params;
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
-
-#endif /*ANDROID_EFFECTVIRTUALIZERAPI_H_*/
diff --git a/include/media/EffectVisualizerApi.h b/include/media/EffectVisualizerApi.h
deleted file mode 100644
index e0fa328..0000000
--- a/include/media/EffectVisualizerApi.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef ANDROID_EFFECTVISUALIZERAPI_H_
-#define ANDROID_EFFECTVISUALIZERAPI_H_
-
-#include <hardware/audio_effect.h>
-
-#if __cplusplus
-extern "C" {
-#endif
-
-#ifndef OPENSL_ES_H_
-static const effect_uuid_t SL_IID_VISUALIZATION_ =
-    { 0xe46b26a0, 0xdddd, 0x11db, 0x8afd, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
-const effect_uuid_t * const SL_IID_VISUALIZATION = &SL_IID_VISUALIZATION_;
-#endif //OPENSL_ES_H_
-
-#define VISUALIZER_CAPTURE_SIZE_MAX 1024  // maximum capture size in samples
-#define VISUALIZER_CAPTURE_SIZE_MIN 128   // minimum capture size in samples
-
-/* enumerated parameters for Visualizer effect */
-typedef enum
-{
-    VISU_PARAM_CAPTURE_SIZE,        // Sets the number PCM samples in the capture.
-} t_visualizer_params;
-
-/* commands */
-typedef enum
-{
-    VISU_CMD_CAPTURE = EFFECT_CMD_FIRST_PROPRIETARY, // Gets the latest PCM capture.
-}t_visualizer_cmds;
-
-// VISU_CMD_CAPTURE retrieves the latest PCM snapshot captured by the visualizer engine.
-// It returns the number of samples specified by VISU_PARAM_CAPTURE_SIZE
-// in 8 bit unsigned format (0 = 0x80)
-
-#if __cplusplus
-}  // extern "C"
-#endif
-
-
-#endif /*ANDROID_EFFECTVISUALIZERAPI_H_*/
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 28be7c1..a73267d 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -24,6 +24,7 @@
 
 class Surface;
 class ICamera;
+class ICameraRecordingProxy;
 class IMediaRecorderClient;
 
 class IMediaRecorder: public IInterface
@@ -31,28 +32,29 @@
 public:
     DECLARE_META_INTERFACE(MediaRecorder);
 
-    virtual	status_t		setCamera(const sp<ICamera>& camera) = 0;
-    virtual	status_t		setPreviewSurface(const sp<Surface>& surface) = 0;
-    virtual	status_t		setVideoSource(int vs) = 0;
-    virtual	status_t		setAudioSource(int as) = 0;
-    virtual	status_t		setOutputFormat(int of) = 0;
-    virtual	status_t		setVideoEncoder(int ve) = 0;
-    virtual	status_t		setAudioEncoder(int ae) = 0;
-    virtual	status_t		setOutputFile(const char* path) = 0;
-    virtual	status_t		setOutputFile(int fd, int64_t offset, int64_t length) = 0;
-    virtual	status_t		setOutputFileAuxiliary(int fd) = 0;
-    virtual	status_t		setVideoSize(int width, int height) = 0;
-    virtual	status_t		setVideoFrameRate(int frames_per_second) = 0;
-    virtual     status_t                setParameters(const String8& params) = 0;
-    virtual     status_t                setListener(const sp<IMediaRecorderClient>& listener) = 0;
-    virtual	status_t		prepare() = 0;
-    virtual	status_t		getMaxAmplitude(int* max) = 0;
-    virtual	status_t		start() = 0;
-    virtual	status_t		stop() = 0;
-    virtual	status_t		reset() = 0;
-    virtual status_t        init() = 0;
-    virtual status_t        close() = 0;
-    virtual	status_t		release() = 0;
+    virtual status_t setCamera(const sp<ICamera>& camera,
+                               const sp<ICameraRecordingProxy>& proxy) = 0;
+    virtual status_t setPreviewSurface(const sp<Surface>& surface) = 0;
+    virtual status_t setVideoSource(int vs) = 0;
+    virtual status_t setAudioSource(int as) = 0;
+    virtual status_t setOutputFormat(int of) = 0;
+    virtual status_t setVideoEncoder(int ve) = 0;
+    virtual status_t setAudioEncoder(int ae) = 0;
+    virtual status_t setOutputFile(const char* path) = 0;
+    virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
+    virtual status_t setOutputFileAuxiliary(int fd) = 0;
+    virtual status_t setVideoSize(int width, int height) = 0;
+    virtual status_t setVideoFrameRate(int frames_per_second) = 0;
+    virtual status_t setParameters(const String8& params) = 0;
+    virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0;
+    virtual status_t prepare() = 0;
+    virtual status_t getMaxAmplitude(int* max) = 0;
+    virtual status_t start() = 0;
+    virtual status_t stop() = 0;
+    virtual status_t reset() = 0;
+    virtual status_t init() = 0;
+    virtual status_t close() = 0;
+    virtual status_t release() = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 18e8a5f..4328d3c 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -103,6 +103,10 @@
     virtual status_t    initCheck() = 0;
     virtual bool        hardwareOutput() = 0;
 
+    virtual status_t    setUID(uid_t uid) {
+        return INVALID_OPERATION;
+    }
+
     virtual status_t    setDataSource(
             const char *url,
             const KeyedVector<String8, String8> *headers = NULL) = 0;
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 7e22a24..1c08969 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -24,6 +24,7 @@
 
 namespace android {
 
+class ICameraRecordingProxy;
 class Surface;
 
 struct MediaRecorderBase {
@@ -38,7 +39,8 @@
     virtual status_t setVideoEncoder(video_encoder ve) = 0;
     virtual status_t setVideoSize(int width, int height) = 0;
     virtual status_t setVideoFrameRate(int frames_per_second) = 0;
-    virtual status_t setCamera(const sp<ICamera>& camera) = 0;
+    virtual status_t setCamera(const sp<ICamera>& camera,
+                               const sp<ICameraRecordingProxy>& proxy) = 0;
     virtual status_t setPreviewSurface(const sp<Surface>& surface) = 0;
     virtual status_t setOutputFile(const char *path) = 0;
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
diff --git a/include/media/Visualizer.h b/include/media/Visualizer.h
index b8746c2..5d2c874 100644
--- a/include/media/Visualizer.h
+++ b/include/media/Visualizer.h
@@ -18,7 +18,7 @@
 #define ANDROID_MEDIA_VISUALIZER_H
 
 #include <media/AudioEffect.h>
-#include <media/EffectVisualizerApi.h>
+#include <audio_effects/effect_visualizer.h>
 #include <string.h>
 
 /**
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
index 28f305d..9aa6700 100644
--- a/include/media/mediametadataretriever.h
+++ b/include/media/mediametadataretriever.h
@@ -53,6 +53,7 @@
     METADATA_KEY_VIDEO_HEIGHT    = 19,
     METADATA_KEY_BITRATE         = 20,
     METADATA_KEY_TIMED_TEXT_LANGUAGES      = 21,
+    METADATA_KEY_IS_DRM          = 22,
 
     // Add more here...
 };
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 36bf34e..af12d3c 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -30,6 +30,7 @@
 class Surface;
 class IMediaRecorder;
 class ICamera;
+class ICameraRecordingProxy;
 
 typedef void (*media_completion_f)(status_t status, void *cookie);
 
@@ -202,7 +203,7 @@
 
     void        died();
     status_t    initCheck();
-    status_t    setCamera(const sp<ICamera>& camera);
+    status_t    setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
     status_t    setPreviewSurface(const sp<Surface>& surface);
     status_t    setVideoSource(int vs);
     status_t    setAudioSource(int as);
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index bb25bae..8c1c593 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -21,6 +21,7 @@
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaSource.h>
 #include <camera/ICamera.h>
+#include <camera/ICameraRecordingProxyListener.h>
 #include <camera/CameraParameters.h>
 #include <utils/List.h>
 #include <utils/RefBase.h>
@@ -68,6 +69,7 @@
      * @return NULL on error.
      */
     static CameraSource *CreateFromCamera(const sp<ICamera> &camera,
+                                          const sp<ICameraRecordingProxy> &proxy,
                                           int32_t cameraId,
                                           Size videoSize,
                                           int32_t frameRate,
@@ -111,6 +113,23 @@
     virtual void signalBufferReturned(MediaBuffer* buffer);
 
 protected:
+    class ProxyListener: public BnCameraRecordingProxyListener {
+    public:
+        ProxyListener(const sp<CameraSource>& source);
+        virtual void dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
+                const sp<IMemory> &data);
+
+    private:
+        sp<CameraSource> mSource;
+    };
+
+    // isBinderAlive needs linkToDeath to work.
+    class DeathNotifier: public IBinder::DeathRecipient {
+    public:
+        DeathNotifier() {}
+        virtual void binderDied(const wp<IBinder>& who);
+    };
+
     enum CameraFlags {
         FLAGS_SET_CAMERA = 1L << 0,
         FLAGS_HOT_CAMERA = 1L << 1,
@@ -123,6 +142,8 @@
     status_t mInitCheck;
 
     sp<Camera>   mCamera;
+    sp<ICameraRecordingProxy>   mCameraRecordingProxy;
+    sp<DeathNotifier> mDeathNotifier;
     sp<Surface>  mSurface;
     sp<MetaData> mMeta;
 
@@ -132,7 +153,8 @@
     bool mStarted;
     int32_t mNumFramesEncoded;
 
-    CameraSource(const sp<ICamera>& camera, int32_t cameraId,
+    CameraSource(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+                 int32_t cameraId,
                  Size videoSize, int32_t frameRate,
                  const sp<Surface>& surface,
                  bool storeMetaDataInVideoBuffers);
@@ -172,10 +194,18 @@
     void releaseOneRecordingFrame(const sp<IMemory>& frame);
 
 
-    status_t init(const sp<ICamera>& camera, int32_t cameraId,
-                Size videoSize, int32_t frameRate,
-                bool storeMetaDataInVideoBuffers);
-    status_t isCameraAvailable(const sp<ICamera>& camera, int32_t cameraId);
+    status_t init(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+                  int32_t cameraId, Size videoSize, int32_t frameRate,
+                  bool storeMetaDataInVideoBuffers);
+
+    status_t initWithCameraAccess(
+                  const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+                  int32_t cameraId, Size videoSize, int32_t frameRate,
+                  bool storeMetaDataInVideoBuffers);
+
+    status_t isCameraAvailable(const sp<ICamera>& camera,
+                               const sp<ICameraRecordingProxy>& proxy,
+                               int32_t cameraId);
     status_t isCameraColorFormatSupported(const CameraParameters& params);
     status_t configureCamera(CameraParameters* params,
                     int32_t width, int32_t height,
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index 0e5d534..f07ebba 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -33,6 +33,7 @@
 public:
     static CameraSourceTimeLapse *CreateFromCamera(
         const sp<ICamera> &camera,
+        const sp<ICameraRecordingProxy> &proxy,
         int32_t cameraId,
         Size videoSize,
         int32_t videoFrameRate,
@@ -132,6 +133,7 @@
 
     CameraSourceTimeLapse(
         const sp<ICamera> &camera,
+        const sp<ICameraRecordingProxy> &proxy,
         int32_t cameraId,
         Size videoSize,
         int32_t videoFrameRate,
diff --git a/include/media/stagefright/MPEG2TSWriter.h b/include/media/stagefright/MPEG2TSWriter.h
index f2c6505..e4c1c49 100644
--- a/include/media/stagefright/MPEG2TSWriter.h
+++ b/include/media/stagefright/MPEG2TSWriter.h
@@ -31,6 +31,10 @@
     MPEG2TSWriter(int fd);
     MPEG2TSWriter(const char *filename);
 
+    MPEG2TSWriter(
+            void *cookie,
+            ssize_t (*write)(void *cookie, const void *data, size_t size));
+
     virtual status_t addSource(const sp<MediaSource> &source);
     virtual status_t start(MetaData *param = NULL);
     virtual status_t stop();
@@ -51,6 +55,10 @@
     struct SourceInfo;
 
     FILE *mFile;
+
+    void *mWriteCookie;
+    ssize_t (*mWriteFunc)(void *cookie, const void *data, size_t size);
+
     sp<ALooper> mLooper;
     sp<AHandlerReflector<MPEG2TSWriter> > mReflector;
 
@@ -69,6 +77,8 @@
     void writeProgramMap();
     void writeAccessUnit(int32_t sourceIndex, const sp<ABuffer> &buffer);
 
+    ssize_t internalWrite(const void *data, size_t size);
+
     DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSWriter);
 };
 
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 904ce2a..77166ed 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -71,7 +71,8 @@
     bool mUse32BitOffset;
     bool mIsFileSizeLimitExplicitlyRequested;
     bool mPaused;
-    bool mStarted;
+    bool mStarted;  // Writer thread + track threads started successfully
+    bool mWriterThreadStarted;  // Only writer thread started successfully
     off64_t mOffset;
     off_t mMdatOffset;
     uint8_t *mMoovBoxBuffer;
@@ -182,6 +183,7 @@
     void writeLatitude(int degreex10000);
     void writeLongitude(int degreex10000);
     void sendSessionSummary();
+    void release();
 
     MPEG4Writer(const MPEG4Writer &);
     MPEG4Writer &operator=(const MPEG4Writer &);
diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
index a82106e..eb45237 100644
--- a/include/media/stagefright/MediaExtractor.h
+++ b/include/media/stagefright/MediaExtractor.h
@@ -56,7 +56,12 @@
     virtual uint32_t flags() const;
 
     // for DRM
-    virtual void setDrmFlag(bool flag) {};
+    virtual void setDrmFlag(bool flag) {
+        mIsDrm = flag;
+    };
+    virtual bool getDrmFlag() {
+        return mIsDrm;
+    }
     virtual char* getDrmTrackInfo(size_t trackID, int *len) {
         return NULL;
     }
@@ -66,6 +71,8 @@
     virtual ~MediaExtractor() {}
 
 private:
+    bool mIsDrm;
+
     MediaExtractor(const MediaExtractor &);
     MediaExtractor &operator=(const MediaExtractor &);
 };
diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h
index a31395e..37dbcd8 100644
--- a/include/media/stagefright/MediaSource.h
+++ b/include/media/stagefright/MediaSource.h
@@ -22,6 +22,7 @@
 
 #include <media/stagefright/MediaErrors.h>
 #include <utils/RefBase.h>
+#include <utils/Vector.h>
 
 namespace android {
 
@@ -99,6 +100,15 @@
         return ERROR_UNSUPPORTED;
     }
 
+    // The consumer of this media source requests that the given buffers
+    // are to be returned exclusively in response to read calls.
+    // This will be called after a successful start() and before the
+    // first read() call.
+    // Callee assumes ownership of the buffers if no error is returned.
+    virtual status_t setBuffers(const Vector<MediaBuffer *> &buffers) {
+        return ERROR_UNSUPPORTED;
+    }
+
 protected:
     virtual ~MediaSource();
 
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 99b72ad..57f678c 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -121,6 +121,8 @@
 
     // To store the timed text format data
     kKeyTextFormatData    = 'text',  // raw data
+
+    kKeyRequiresSecureBuffers = 'secu',  // bool (int32_t)
 };
 
 enum {
diff --git a/include/media/stagefright/MetadataBufferType.h b/include/media/stagefright/MetadataBufferType.h
new file mode 100644
index 0000000..275c19f
--- /dev/null
+++ b/include/media/stagefright/MetadataBufferType.h
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+#ifndef METADATA_BUFFER_TYPE_H
+#define METADATA_BUFFER_TYPE_H
+
+namespace android {
+/*
+ * MetadataBufferType defines the type of the metadata buffers that
+ * can be passed to video encoder component for encoding, via Stagefright
+ * media recording framework. To see how to work with the metadata buffers
+ * in media recording framework, please consult HardwareAPI.h
+ *
+ * The creator of metadata buffers and video encoder share common knowledge
+ * on what is actually being stored in these metadata buffers, and
+ * how the information can be used by the video encoder component
+ * to locate the actual pixel data as the source input for video
+ * encoder, plus whatever other information that is necessary. Stagefright
+ * media recording framework does not need to know anything specific about the
+ * metadata buffers, except for receving each individual metadata buffer
+ * as the source input, making a copy of the metadata buffer, and passing the
+ * copy via OpenMAX API to the video encoder component.
+ *
+ * The creator of the metadata buffers must ensure that the first
+ * 4 bytes in every metadata buffer indicates its buffer type,
+ * and the rest of the metadata buffer contains the
+ * actual metadata information. When a video encoder component receives
+ * a metadata buffer, it uses the first 4 bytes in that buffer to find
+ * out the type of the metadata buffer, and takes action appropriate
+ * to that type of metadata buffers (for instance, locate the actual
+ * pixel data input and then encoding the input data to produce a
+ * compressed output buffer).
+ *
+ * The following shows the layout of a metadata buffer,
+ * where buffer type is a 4-byte field of MetadataBufferType,
+ * and the payload is the metadata information.
+ *
+ * --------------------------------------------------------------
+ * |  buffer type  |          payload                           |
+ * --------------------------------------------------------------
+ *
+ */
+typedef enum {
+
+    /*
+     * kMetadataBufferTypeCameraSource is used to indicate that
+     * the source of the metadata buffer is the camera component.
+     */
+    kMetadataBufferTypeCameraSource  = 0,
+
+    /*
+     * kMetadataBufferTypeGrallocSource is used to indicate that
+     * the payload of the metadata buffers can be interpreted as
+     * a buffer_handle_t.
+     */
+    kMetadataBufferTypeGrallocSource = 1,
+
+    // Add more here...
+
+} MetadataBufferType;
+
+}  // namespace android
+
+#endif  // METADATA_BUFFER_TYPE_H
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 589cefd..7f3c497 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -53,6 +53,9 @@
 
         // Enable GRALLOC_USAGE_PROTECTED for output buffers from native window
         kEnableGrallocUsageProtected = 128,
+
+        // Secure decoding mode
+        kUseSecureInputBuffers = 256,
     };
     static sp<MediaSource> Create(
             const sp<IOMX> &omx,
@@ -79,6 +82,13 @@
     // from MediaBufferObserver
     virtual void signalBufferReturned(MediaBuffer *buffer);
 
+    // for use by ACodec
+    static void findMatchingCodecs(
+            const char *mime,
+            bool createEncoder, const char *matchComponentName,
+            uint32_t flags,
+            Vector<String8> *matchingCodecs);
+
 protected:
     virtual ~OMXCodec();
 
@@ -157,6 +167,10 @@
     bool mOMXLivesLocally;
     IOMX::node_id mNode;
     uint32_t mQuirks;
+
+    // Flags specified in the creation of the codec.
+    uint32_t mFlags;
+
     bool mIsEncoder;
     char *mMIME;
     char *mComponentName;
@@ -198,15 +212,12 @@
     List<size_t> mFilledBuffers;
     Condition mBufferFilled;
 
-    bool mIsMetaDataStoredInVideoBuffers;
-    bool mOnlySubmitOneBufferAtOneTime;
-    bool mEnableGrallocUsageProtected;
-
     // Used to record the decoding time for an output picture from
     // a video encoder.
     List<int64_t> mDecodingTimeList;
 
-    OMXCodec(const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
+    OMXCodec(const sp<IOMX> &omx, IOMX::node_id node,
+             uint32_t quirks, uint32_t flags,
              bool isEncoder, const char *mime, const char *componentName,
              const sp<MediaSource> &source,
              const sp<ANativeWindow> &nativeWindow);
@@ -280,6 +291,10 @@
     void drainInputBuffers();
     void fillOutputBuffers();
 
+    bool drainAnyInputBuffer();
+    BufferInfo *findInputBufferByDataPointer(void *ptr);
+    BufferInfo *findEmptyInputBuffer();
+
     // Returns true iff a flush was initiated and a completion event is
     // upcoming, false otherwise (A flush was not necessary as we own all
     // the buffers on that port).
@@ -306,17 +321,11 @@
 
     void dumpPortStatus(OMX_U32 portIndex);
 
-    status_t configureCodec(const sp<MetaData> &meta, uint32_t flags);
+    status_t configureCodec(const sp<MetaData> &meta);
 
     static uint32_t getComponentQuirks(
             const char *componentName, bool isEncoder);
 
-    static void findMatchingCodecs(
-            const char *mime,
-            bool createEncoder, const char *matchComponentName,
-            uint32_t flags,
-            Vector<String8> *matchingCodecs);
-
     void restorePatchedDataPointer(BufferInfo *info);
 
     status_t applyRotation();
diff --git a/include/pim/EventRecurrence.h b/include/pim/EventRecurrence.h
deleted file mode 100644
index 1ceda41..0000000
--- a/include/pim/EventRecurrence.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//
-#ifndef _PIM_EVENT_RECURRENCE_H
-#define _PIM_EVENT_RECURRENCE_H
-
-#include <utils/String16.h>
-
-namespace android {
-
-struct EventRecurrence
-{
-public:
-                EventRecurrence();
-                ~EventRecurrence();
-    
-    status_t    parse(const String16&);
-
-
-    enum freq_t {
-        SECONDLY = 1,
-        MINUTELY = 2,
-        HOURLY = 3,
-        DAILY = 4,
-        WEEKLY = 5,
-        MONTHLY = 6,
-        YEARLY = 7
-    };
-
-    enum {
-        SU = 0x00010000,
-        MO = 0x00020000,
-        TU = 0x00040000,
-        WE = 0x00080000,
-        TH = 0x00100000,
-        FR = 0x00200000,
-        SA = 0x00400000
-    };
-    
-    freq_t    freq;
-    String16  until;
-    int       count;
-    int       interval;
-    int*      bysecond;
-    int       bysecondCount;
-    int*      byminute;
-    int       byminuteCount;
-    int*      byhour;
-    int       byhourCount;
-    int*      byday;
-    int*      bydayNum;
-    int       bydayCount;   
-    int*      bymonthday;
-    int       bymonthdayCount;
-    int*      byyearday;
-    int       byyeardayCount;
-    int*      byweekno;
-    int       byweeknoCount;
-    int*      bymonth;
-    int       bymonthCount;
-    int*      bysetpos;
-    int       bysetposCount;
-    int       wkst;
-};
-
-}; // namespace android
-
-#endif // _PIM_EVENT_RECURRENCE_H
diff --git a/include/private/surfaceflinger/LayerState.h b/include/private/surfaceflinger/LayerState.h
index d7fe572..d2fed41 100644
--- a/include/private/surfaceflinger/LayerState.h
+++ b/include/private/surfaceflinger/LayerState.h
@@ -29,6 +29,7 @@
 namespace android {
 
 class Parcel;
+class ISurfaceComposerClient;
 
 struct layer_state_t {
 
@@ -68,6 +69,13 @@
             Region          transparentRegion;
 };
 
+struct ComposerState {
+    sp<ISurfaceComposerClient> client;
+    layer_state_t state;
+    status_t    write(Parcel& output) const;
+    status_t    read(const Parcel& input);
+};
+
 }; // namespace android
 
 #endif // ANDROID_SF_LAYER_STATE_H
diff --git a/include/surfaceflinger/IGraphicBufferAlloc.h b/include/surfaceflinger/IGraphicBufferAlloc.h
index e1b6b57..d3b2062 100644
--- a/include/surfaceflinger/IGraphicBufferAlloc.h
+++ b/include/surfaceflinger/IGraphicBufferAlloc.h
@@ -37,7 +37,7 @@
     /* Create a new GraphicBuffer for the client to use.
      */
     virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
-            PixelFormat format, uint32_t usage) = 0;
+            PixelFormat format, uint32_t usage, status_t* error) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index 03fd01b..dba98a3 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -34,6 +34,7 @@
 // ----------------------------------------------------------------------------
 
 class IMemoryHeap;
+class ComposerState;
 
 class ISurfaceComposer : public IInterface
 {
@@ -105,8 +106,7 @@
     virtual sp<IMemoryHeap> getCblk() const = 0;
 
     /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
-    virtual void openGlobalTransaction() = 0;
-    virtual void closeGlobalTransaction() = 0;
+    virtual void setTransactionState(const Vector<ComposerState>& state) = 0;
 
     /* [un]freeze display. requires ACCESS_SURFACE_FLINGER permission */
     virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags) = 0;
@@ -149,8 +149,7 @@
         CREATE_CONNECTION,
         CREATE_GRAPHIC_BUFFER_ALLOC,
         GET_CBLK,
-        OPEN_GLOBAL_TRANSACTION,
-        CLOSE_GLOBAL_TRANSACTION,
+        SET_TRANSACTION_STATE,
         SET_ORIENTATION,
         FREEZE_DISPLAY,
         UNFREEZE_DISPLAY,
diff --git a/include/surfaceflinger/ISurfaceComposerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h
index 2e75a0e..6e9a654 100644
--- a/include/surfaceflinger/ISurfaceComposerClient.h
+++ b/include/surfaceflinger/ISurfaceComposerClient.h
@@ -37,8 +37,6 @@
 
 // ----------------------------------------------------------------------------
 
-class layer_state_t;
-
 class ISurfaceComposerClient : public IInterface
 {
 public:
@@ -69,11 +67,6 @@
      * Requires ACCESS_SURFACE_FLINGER permission
      */
     virtual status_t    destroySurface(SurfaceID sid) = 0;
-
-    /*
-     * Requires ACCESS_SURFACE_FLINGER permission
-     */
-    virtual status_t    setState(int32_t count, const layer_state_t* states) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
index 140b9f8..7fbbfb24 100644
--- a/include/surfaceflinger/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -37,10 +37,12 @@
 // ---------------------------------------------------------------------------
 
 class DisplayInfo;
+class Composer;
 class IMemoryHeap;
 class ISurfaceComposer;
 class Region;
 class surface_flinger_cblk_t;
+struct layer_state_t;
 
 // ---------------------------------------------------------------------------
 
@@ -59,8 +61,11 @@
 
 // ---------------------------------------------------------------------------
 
+class Composer;
+
 class SurfaceComposerClient : public RefBase
 {
+    friend class Composer;
 public:    
                 SurfaceComposerClient();
     virtual     ~SurfaceComposerClient();
@@ -101,13 +106,7 @@
     // All composer parameters must be changed within a transaction
     // several surfaces can be updated in one transaction, all changes are
     // committed at once when the transaction is closed.
-    // CloseTransaction() usually requires an IPC with the server.
-    
-    //! Open a composer transaction
-    status_t    openTransaction();
-
-    //! commit the transaction
-    status_t    closeTransaction();
+    // closeGlobalTransaction() usually requires an IPC with the server.
 
     //! Open a composer transaction on all active SurfaceComposerClients.
     static void openGlobalTransaction();
@@ -152,19 +151,12 @@
 
 private:
     virtual void onFirstRef();
-    inline layer_state_t*   get_state_l(SurfaceID id);
-    layer_state_t*          lockLayerState(SurfaceID id);
-    inline void             unlockLayerState();
+    Composer& getComposer();
 
-    mutable     Mutex                               mLock;
-                SortedVector<layer_state_t>         mStates;
-                int32_t                             mTransactionOpen;
-                layer_state_t*                      mPrebuiltLayerState;
-
-                // these don't need to be protected because they never change
-                // after assignment
+    mutable     Mutex                       mLock;
                 status_t                    mStatus;
                 sp<ISurfaceComposerClient>  mClient;
+                Composer&                   mComposer;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/include/utils/BitSet.h b/include/utils/BitSet.h
index de748b5..600017e 100644
--- a/include/utils/BitSet.h
+++ b/include/utils/BitSet.h
@@ -44,6 +44,9 @@
     // Returns true if the bit set does not contain any marked bits.
     inline bool isEmpty() const { return ! value; }
 
+    // Returns true if the bit set does not contain any unmarked bits.
+    inline bool isFull() const { return value == 0xffffffff; }
+
     // Returns true if the specified bit is marked.
     inline bool hasBit(uint32_t n) const { return value & valueForBit(n); }
 
diff --git a/include/utils/LinearTransform.h b/include/utils/LinearTransform.h
new file mode 100644
index 0000000..04cb355
--- /dev/null
+++ b/include/utils/LinearTransform.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBS_UTILS_LINEAR_TRANSFORM_H
+#define _LIBS_UTILS_LINEAR_TRANSFORM_H
+
+#include <stdint.h>
+
+namespace android {
+
+// LinearTransform defines a structure which hold the definition of a
+// transformation from single dimensional coordinate system A into coordinate
+// system B (and back again).  Values in A and in B are 64 bit, the linear
+// scale factor is expressed as a rational number using two 32 bit values.
+//
+// Specifically, let
+// f(a) = b
+// F(b) = f^-1(b) = a
+// then
+//
+// f(a) = (((a - a_zero) * a_to_b_numer) / a_to_b_denom) + b_zero;
+//
+// and
+//
+// F(b) = (((b - b_zero) * a_to_b_denom) / a_to_b_numer) + a_zero;
+//
+struct LinearTransform {
+  int64_t  a_zero;
+  int64_t  b_zero;
+  int32_t  a_to_b_numer;
+  uint32_t a_to_b_denom;
+
+  // Transform from A->B
+  // Returns true on success, or false in the case of a singularity or an
+  // overflow.
+  bool doForwardTransform(int64_t a_in, int64_t* b_out) const;
+
+  // Transform from B->A
+  // Returns true on success, or false in the case of a singularity or an
+  // overflow.
+  bool doReverseTransform(int64_t b_in, int64_t* a_out) const;
+
+  // Helpers which will reduce the fraction N/D using Euclid's method.
+  template <class T> static void reduce(T* N, T* D);
+  static void reduce(int32_t* N, uint32_t* D);
+};
+
+
+}
+
+#endif  // _LIBS_UTILS_LINEAR_TRANSFORM_H
diff --git a/include/utils/SortedVector.h b/include/utils/SortedVector.h
index 8beec57..0e98aeb 100644
--- a/include/utils/SortedVector.h
+++ b/include/utils/SortedVector.h
@@ -32,6 +32,8 @@
 template <class TYPE>
 class SortedVector : private SortedVectorImpl
 {
+    friend class Vector<TYPE>;
+
 public:
             typedef TYPE    value_type;
     
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
index f1e87e6..b908e2a 100644
--- a/include/utils/Vector.h
+++ b/include/utils/Vector.h
@@ -29,6 +29,9 @@
 
 namespace android {
 
+template <typename TYPE>
+class SortedVector;
+
 /*!
  * The main templated vector class ensuring type safety
  * while making use of VectorImpl.
@@ -47,13 +50,17 @@
     
                             Vector();
                             Vector(const Vector<TYPE>& rhs);
+    explicit                Vector(const SortedVector<TYPE>& rhs);
     virtual                 ~Vector();
 
     /*! copy operator */
             const Vector<TYPE>&     operator = (const Vector<TYPE>& rhs) const;
             Vector<TYPE>&           operator = (const Vector<TYPE>& rhs);    
 
-    /*
+            const Vector<TYPE>&     operator = (const SortedVector<TYPE>& rhs) const;
+            Vector<TYPE>&           operator = (const SortedVector<TYPE>& rhs);
+
+            /*
      * empty the vector
      */
 
@@ -215,6 +222,11 @@
 }
 
 template<class TYPE> inline
+Vector<TYPE>::Vector(const SortedVector<TYPE>& rhs)
+    : VectorImpl(static_cast<const VectorImpl&>(rhs)) {
+}
+
+template<class TYPE> inline
 Vector<TYPE>::~Vector() {
     finish_vector();
 }
@@ -227,6 +239,18 @@
 
 template<class TYPE> inline
 const Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) const {
+    VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+    return *this;
+}
+
+template<class TYPE> inline
+Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
+    VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+    return *this;
+}
+
+template<class TYPE> inline
+const Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
     VectorImpl::operator = (rhs);
     return *this; 
 }
diff --git a/include/utils/threads.h b/include/utils/threads.h
index 0bd69cf..c8e9c04 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -133,13 +133,13 @@
 // Change the scheduling group of a particular thread.  The group
 // should be one of the ANDROID_TGROUP constants.  Returns BAD_VALUE if
 // grp is out of range, else another non-zero value with errno set if
-// the operation failed.
+// the operation failed.  Thread ID zero means current thread.
 extern int androidSetThreadSchedulingGroup(pid_t tid, int grp);
 
 // Change the priority AND scheduling group of a particular thread.  The priority
 // should be one of the ANDROID_PRIORITY constants.  Returns INVALID_OPERATION
 // if the priority set failed, else another value if just the group set failed;
-// in either case errno is set.
+// in either case errno is set.  Thread ID zero means current thread.
 extern int androidSetThreadPriority(pid_t tid, int prio);
 
 #ifdef __cplusplus
@@ -510,6 +510,10 @@
     // that case.
             status_t    requestExitAndWait();
 
+    // Wait until this object's thread exits. Returns immediately if not yet running.
+    // Do not call from this object's thread; will return WOULD_BLOCK in that case.
+            status_t    join();
+
 protected:
     // exitPending() returns true if requestExit() has been called.
             bool        exitPending() const;
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index fd6c22c..f75208d 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -60,16 +60,17 @@
     public static final String WIFI = "WIFI_";
 
     /** Data type for public keys. */
-    public static final String PUBLIC_KEY = "KEY";
+    public static final String EXTRA_PUBLIC_KEY = "KEY";
 
     /** Data type for private keys. */
-    public static final String PRIVATE_KEY = "PKEY";
+    public static final String EXTRA_PRIVATE_KEY = "PKEY";
 
-    /** Data type for certificates. */
-    public static final String CERTIFICATE = "CERT";
-
-    /** Data type for PKCS12. */
-    public static final String PKCS12 = "PKCS12";
+    // historically used by Android
+    public static final String EXTENSION_CRT = ".crt";
+    public static final String EXTENSION_P12 = ".p12";
+    // commonly used on Windows
+    public static final String EXTENSION_CER = ".cer";
+    public static final String EXTENSION_PFX = ".pfx";
 
     /**
      * Convert objects to a PEM format, which is used for
@@ -123,18 +124,20 @@
         }
     }
 
-    private Intent createInstallIntent() {
-        Intent intent = new Intent(INSTALL_ACTION);
-        intent.setClassName("com.android.certinstaller",
-                "com.android.certinstaller.CertInstallerMain");
-        return intent;
+    public void install(Context context) {
+        try {
+            Intent intent = KeyChain.createInstallIntent();
+            context.startActivity(intent);
+        } catch (ActivityNotFoundException e) {
+            Log.w(LOGTAG, e.toString());
+        }
     }
 
     public void install(Context context, KeyPair pair) {
         try {
-            Intent intent = createInstallIntent();
-            intent.putExtra(PRIVATE_KEY, pair.getPrivate().getEncoded());
-            intent.putExtra(PUBLIC_KEY, pair.getPublic().getEncoded());
+            Intent intent = KeyChain.createInstallIntent();
+            intent.putExtra(EXTRA_PRIVATE_KEY, pair.getPrivate().getEncoded());
+            intent.putExtra(EXTRA_PUBLIC_KEY, pair.getPublic().getEncoded());
             context.startActivity(intent);
         } catch (ActivityNotFoundException e) {
             Log.w(LOGTAG, e.toString());
@@ -143,7 +146,7 @@
 
     public void install(Context context, String type, byte[] value) {
         try {
-            Intent intent = createInstallIntent();
+            Intent intent = KeyChain.createInstallIntent();
             intent.putExtra(type, value);
             context.startActivity(intent);
         } catch (ActivityNotFoundException e) {
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index 2763e46..23ffd59 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -30,5 +30,6 @@
     void installCaCertificate(in byte[] caCertificate);
 
     // APIs used by Settings
+    boolean deleteCaCertificate(String alias);
     boolean reset();
 }
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 4f1596d..6229331 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -22,6 +22,7 @@
 import android.accounts.AuthenticatorException;
 import android.accounts.OperationCanceledException;
 import android.app.Activity;
+import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -44,8 +45,12 @@
 import java.security.cert.X509Certificate;
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
+import libcore.util.Objects;
+import org.apache.harmony.xnet.provider.jsse.TrustedCertificateStore;
 
 /**
  * The {@code KeyChain} class provides access to private keys and
@@ -76,6 +81,13 @@
  * avoid prompting the user with {@link #choosePrivateKeyAlias
  * choosePrivateKeyAlias} on subsequent connections. If the alias is
  * no longer valid, null will be returned on lookups using that value
+ *
+ * <p>An application can request the installation of private keys and
+ * certificates via the {@code Intent} provided by {@link
+ * #createInstallIntent}. Private keys installed via this {@code
+ * Intent} will be accessible via {@link #choosePrivateKeyAlias} while
+ * Certificate Authority (CA) certificates will be trusted by all
+ * applications through the default {@code X509TrustManager}.
  */
 // TODO reference intent for credential installation when public
 public final class KeyChain {
@@ -88,11 +100,109 @@
     public static final String ACCOUNT_TYPE = "com.android.keychain";
 
     /**
+     * Action to bring up the KeyChainActivity
+     */
+    private static final String ACTION_CHOOSER = "com.android.keychain.CHOOSER";
+
+    /**
+     * Extra for use with {@link #ACTION_CHOOSER}
      * @hide Also used by KeyChainActivity implementation
      */
     public static final String EXTRA_RESPONSE = "response";
 
     /**
+     * Extra for use with {@link #ACTION_CHOOSER}
+     * @hide Also used by KeyChainActivity implementation
+     */
+    public static final String EXTRA_HOST = "host";
+
+    /**
+     * Extra for use with {@link #ACTION_CHOOSER}
+     * @hide Also used by KeyChainActivity implementation
+     */
+    public static final String EXTRA_PORT = "port";
+
+    /**
+     * Extra for use with {@link #ACTION_CHOOSER}
+     * @hide Also used by KeyChainActivity implementation
+     */
+    public static final String EXTRA_ALIAS = "alias";
+
+    /**
+     * Extra for use with {@link #ACTION_CHOOSER}
+     * @hide Also used by KeyChainActivity implementation
+     */
+    public static final String EXTRA_SENDER = "sender";
+
+    /**
+     * Action to bring up the CertInstaller
+     */
+    private static final String ACTION_INSTALL = "android.credentials.INSTALL";
+
+    /**
+     * Optional extra to specify a {@code String} credential name on
+     * the {@code Intent} returned by {@link #createInstallIntent}.
+     */
+    // Compatible with old com.android.certinstaller.CredentialHelper.CERT_NAME_KEY
+    public static final String EXTRA_NAME = "name";
+
+    /**
+     * Optional extra to specify an X.509 certificate to install on
+     * the {@code Intent} returned by {@link #createInstallIntent}.
+     * The extra value should be a PEM or ASN.1 DER encoded {@code
+     * byte[]}. An {@link X509Certificate} can be converted to DER
+     * encoded bytes with {@link X509Certificate#getEncoded}.
+     *
+     * <p>{@link #EXTRA_NAME} may be used to provide a default alias
+     * name for the installed certificate.
+     */
+    // Compatible with old android.security.Credentials.CERTIFICATE
+    public static final String EXTRA_CERTIFICATE = "CERT";
+
+    /**
+     * Optional extra for use with the {@code Intent} returned by
+     * {@link #createInstallIntent} to specify a PKCS#12 key store to
+     * install. The extra value should be a {@code byte[]}. The bytes
+     * may come from an external source or be generated with {@link
+     * java.security.KeyStore#store} on a "PKCS12" instance.
+     *
+     * <p>The user will be prompted for the password to load the key store.
+     *
+     * <p>The key store will be scanned for {@link
+     * java.security.KeyStore.PrivateKeyEntry} entries and both the
+     * private key and associated certificate chain will be installed.
+     *
+     * <p>{@link #EXTRA_NAME} may be used to provide a default alias
+     * name for the installed credentials.
+     */
+    // Compatible with old android.security.Credentials.PKCS12
+    public static final String EXTRA_PKCS12 = "PKCS12";
+
+    /**
+     * Returns an {@code Intent} that can be used for credential
+     * installation. The intent may be used without any extras, in
+     * which case the user will be able to install credentials from
+     * their own source.
+     *
+     * <p>Alternatively, {@link #EXTRA_CERTIFICATE} or {@link
+     * #EXTRA_PKCS12} maybe used to specify the bytes of an X.509
+     * certificate or a PKCS#12 key store for installation. These
+     * extras may be combined with {@link #EXTRA_NAME} to provide a
+     * default alias name for credentials being installed.
+     *
+     * <p>When used with {@link Activity#startActivityForResult},
+     * {@link Activity#RESULT_OK} will be returned if a credential was
+     * successfully installed, otherwise {@link
+     * Activity#RESULT_CANCELED} will be returned.
+     */
+    public static Intent createInstallIntent() {
+        Intent intent = new Intent(ACTION_INSTALL);
+        intent.setClassName("com.android.certinstaller",
+                            "com.android.certinstaller.CertInstallerMain");
+        return intent;
+    }
+
+    /**
      * Launches an {@code Activity} for the user to select the alias
      * for a private key and certificate pair for authentication. The
      * selected alias or null will be returned via the
@@ -106,6 +216,9 @@
      * <p>{@code host} and {@code port} may be used to give the user
      * more context about the server requesting the credentials.
      *
+     * <p>{@code alias} allows the chooser to preselect an existing
+     * alias which will still be subject to user confirmation.
+     *
      * <p>This method requires the caller to hold the permission
      * {@link android.Manifest.permission#USE_CREDENTIALS}.
      *
@@ -123,14 +236,17 @@
      *     certificate, or null if unavailable.
      * @param port The port number of the server requesting the
      *     certificate, or -1 if unavailable.
+     * @param alias The alias to preselect if available, or null if
+     *     unavailable.
      */
     public static void choosePrivateKeyAlias(Activity activity, KeyChainAliasCallback response,
                                              String[] keyTypes, Principal[] issuers,
-                                             String host, int port) {
+                                             String host, int port,
+                                             String alias) {
         /*
-         * TODO currently keyTypes, issuers, host, and port are
-         * unused. They are meant to follow the semantics and purpose
-         * of X509KeyManager method arguments.
+         * TODO currently keyTypes, issuers are unused. They are meant
+         * to follow the semantics and purpose of X509KeyManager
+         * method arguments.
          *
          * keyTypes would allow the list to be filtered and typically
          * will be set correctly by the server. In practice today,
@@ -142,11 +258,6 @@
          * server. Others will send none. If this is used, if there
          * are no matches after applying the constraint, it should be
          * ignored.
-         *
-         * host and port may be shown to the user if available, but it
-         * should be clear that they are not validated values, perhaps
-         * shown along with requesting application identity to clarify
-         * the source of the request.
          */
         if (activity == null) {
             throw new NullPointerException("activity == null");
@@ -154,8 +265,13 @@
         if (response == null) {
             throw new NullPointerException("response == null");
         }
-        Intent intent = new Intent("com.android.keychain.CHOOSER");
+        Intent intent = new Intent(ACTION_CHOOSER);
         intent.putExtra(EXTRA_RESPONSE, new AliasResponse(activity, response));
+        intent.putExtra(EXTRA_HOST, host);
+        intent.putExtra(EXTRA_PORT, port);
+        intent.putExtra(EXTRA_ALIAS, alias);
+        // the PendingIntent is used to get calling package name
+        intent.putExtra(EXTRA_SENDER, PendingIntent.getActivity(activity, 0, new Intent(), 0));
         activity.startActivity(intent);
     }
 
@@ -272,7 +388,21 @@
             }
             IKeyChainService keyChainService = keyChainConnection.getService();
             byte[] certificateBytes = keyChainService.getCertificate(alias, authToken);
-            return new X509Certificate[] { toCertificate(certificateBytes) };
+            List<X509Certificate> chain = new ArrayList<X509Certificate>();
+            chain.add(toCertificate(certificateBytes));
+            TrustedCertificateStore store = new TrustedCertificateStore();
+            for (int i = 0; true; i++) {
+                X509Certificate cert = chain.get(i);
+                if (Objects.equal(cert.getSubjectX500Principal(), cert.getIssuerX500Principal())) {
+                    break;
+                }
+                X509Certificate issuer = store.findIssuer(cert);
+                if (issuer == null) {
+                    break;
+                }
+                chain.add(issuer);
+            }
+            return chain.toArray(new X509Certificate[chain.size()]);
         } catch (RemoteException e) {
             throw new KeyChainException(e);
         } catch (RuntimeException e) {
diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java
index 4582aa0..15e253c 100755
--- a/keystore/tests/src/android/security/KeyStoreTest.java
+++ b/keystore/tests/src/android/security/KeyStoreTest.java
@@ -75,11 +75,21 @@
         assertEquals(KeyStore.State.UNLOCKED, mKeyStore.state());
     }
 
+    public void testGet() throws Exception {
+        assertNull(mKeyStore.get(TEST_KEYNAME));
+        mKeyStore.password(TEST_PASSWD);
+        assertNull(mKeyStore.get(TEST_KEYNAME));
+        assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
+        assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
+    }
+
     public void testPut() throws Exception {
+        assertNull(mKeyStore.get(TEST_KEYNAME));
         assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
         assertFalse(mKeyStore.contains(TEST_KEYNAME));
         mKeyStore.password(TEST_PASSWD);
         assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
+        assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
     }
 
     public void testI18n() throws Exception {
@@ -96,7 +106,9 @@
         assertTrue(mKeyStore.delete(TEST_KEYNAME));
 
         mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE);
+        assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
         assertTrue(mKeyStore.delete(TEST_KEYNAME));
+        assertNull(mKeyStore.get(TEST_KEYNAME));
     }
 
     public void testContains() throws Exception {
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index f9d9f25..3a12e96 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -27,7 +27,7 @@
     MemoryHeapBase.cpp \
     MemoryHeapPmem.cpp \
     Parcel.cpp \
-    Permission.cpp \
+    PermissionCache.cpp \
     ProcessState.cpp \
     Static.cpp
 
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index bc8c412..1ace8f8 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -42,11 +42,11 @@
 public:
     HeapCache();
     virtual ~HeapCache();
-    
+
     virtual void binderDied(const wp<IBinder>& who);
 
-    sp<IMemoryHeap> find_heap(const sp<IBinder>& binder); 
-    void free_heap(const sp<IBinder>& binder); 
+    sp<IMemoryHeap> find_heap(const sp<IBinder>& binder);
+    void free_heap(const sp<IBinder>& binder);
     sp<IMemoryHeap> get_heap(const sp<IBinder>& binder);
     void dump_heaps();
 
@@ -57,7 +57,7 @@
         int32_t         count;
     };
 
-    void free_heap(const wp<IBinder>& binder); 
+    void free_heap(const wp<IBinder>& binder);
 
     Mutex mHeapCacheLock;
     KeyedVector< wp<IBinder>, heap_info_t > mHeapCache;
@@ -81,11 +81,12 @@
     virtual void* getBase() const;
     virtual size_t getSize() const;
     virtual uint32_t getFlags() const;
+    virtual uint32_t getOffset() const;
 
 private:
     friend class IMemory;
     friend class HeapCache;
-    
+
     // for debugging in this module
     static inline sp<IMemoryHeap> find_heap(const sp<IBinder>& binder) {
         return gHeapCache->find_heap(binder);
@@ -97,7 +98,7 @@
         return gHeapCache->get_heap(binder);
     }
     static inline void dump_heaps() {
-        gHeapCache->dump_heaps();       
+        gHeapCache->dump_heaps();
     }
 
     void assertMapped() const;
@@ -107,6 +108,7 @@
     mutable void*       mBase;
     mutable size_t      mSize;
     mutable uint32_t    mFlags;
+    mutable uint32_t    mOffset;
     mutable bool        mRealHeap;
     mutable Mutex       mLock;
 };
@@ -123,7 +125,7 @@
     BpMemory(const sp<IBinder>& impl);
     virtual ~BpMemory();
     virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const;
-    
+
 private:
     mutable sp<IMemoryHeap> mHeap;
     mutable ssize_t mOffset;
@@ -203,7 +205,7 @@
 BnMemory::BnMemory() {
 }
 
-BnMemory::~BnMemory() { 
+BnMemory::~BnMemory() {
 }
 
 status_t BnMemory::onTransact(
@@ -229,7 +231,7 @@
 
 BpMemoryHeap::BpMemoryHeap(const sp<IBinder>& impl)
     : BpInterface<IMemoryHeap>(impl),
-        mHeapId(-1), mBase(MAP_FAILED), mSize(0), mFlags(0), mRealHeap(false)
+        mHeapId(-1), mBase(MAP_FAILED), mSize(0), mFlags(0), mOffset(0), mRealHeap(false)
 {
 }
 
@@ -242,7 +244,7 @@
                 sp<IBinder> binder = const_cast<BpMemoryHeap*>(this)->asBinder();
 
                 if (VERBOSE) {
-                    LOGD("UNMAPPING binder=%p, heap=%p, size=%d, fd=%d", 
+                    LOGD("UNMAPPING binder=%p, heap=%p, size=%d, fd=%d",
                             binder.get(), this, mSize, mHeapId);
                     CallStack stack;
                     stack.update();
@@ -270,6 +272,7 @@
             if (mHeapId == -1) {
                 mBase   = heap->mBase;
                 mSize   = heap->mSize;
+                mOffset = heap->mOffset;
                 android_atomic_write( dup( heap->mHeapId ), &mHeapId );
             }
         } else {
@@ -286,13 +289,14 @@
         // remote call without mLock held, worse case scenario, we end up
         // calling transact() from multiple threads, but that's not a problem,
         // only mmap below must be in the critical section.
-        
+
         Parcel data, reply;
         data.writeInterfaceToken(IMemoryHeap::getInterfaceDescriptor());
         status_t err = remote()->transact(HEAP_ID, data, &reply);
         int parcel_fd = reply.readFileDescriptor();
         ssize_t size = reply.readInt32();
         uint32_t flags = reply.readInt32();
+        uint32_t offset = reply.readInt32();
 
         LOGE_IF(err, "binder=%p transaction failed fd=%d, size=%ld, err=%d (%s)",
                 asBinder().get(), parcel_fd, size, err, strerror(-err));
@@ -309,7 +313,7 @@
         Mutex::Autolock _l(mLock);
         if (mHeapId == -1) {
             mRealHeap = true;
-            mBase = mmap(0, size, access, MAP_SHARED, fd, 0);
+            mBase = mmap(0, size, access, MAP_SHARED, fd, offset);
             if (mBase == MAP_FAILED) {
                 LOGE("cannot map BpMemoryHeap (binder=%p), size=%ld, fd=%d (%s)",
                         asBinder().get(), size, fd, strerror(errno));
@@ -317,6 +321,7 @@
             } else {
                 mSize = size;
                 mFlags = flags;
+                mOffset = offset;
                 android_atomic_write(fd, &mHeapId);
             }
         }
@@ -343,14 +348,19 @@
     return mFlags;
 }
 
+uint32_t BpMemoryHeap::getOffset() const {
+    assertMapped();
+    return mOffset;
+}
+
 // ---------------------------------------------------------------------------
 
 IMPLEMENT_META_INTERFACE(MemoryHeap, "android.utils.IMemoryHeap");
 
-BnMemoryHeap::BnMemoryHeap() { 
+BnMemoryHeap::BnMemoryHeap() {
 }
 
-BnMemoryHeap::~BnMemoryHeap() { 
+BnMemoryHeap::~BnMemoryHeap() {
 }
 
 status_t BnMemoryHeap::onTransact(
@@ -362,6 +372,7 @@
             reply->writeFileDescriptor(getHeapID());
             reply->writeInt32(getSize());
             reply->writeInt32(getFlags());
+            reply->writeInt32(getOffset());
             return NO_ERROR;
         } break;
         default:
@@ -383,17 +394,17 @@
 void HeapCache::binderDied(const wp<IBinder>& binder)
 {
     //LOGD("binderDied binder=%p", binder.unsafe_get());
-    free_heap(binder); 
+    free_heap(binder);
 }
 
-sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder) 
+sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder)
 {
     Mutex::Autolock _l(mHeapCacheLock);
     ssize_t i = mHeapCache.indexOfKey(binder);
     if (i>=0) {
         heap_info_t& info = mHeapCache.editValueAt(i);
         LOGD_IF(VERBOSE,
-                "found binder=%p, heap=%p, size=%d, fd=%d, count=%d", 
+                "found binder=%p, heap=%p, size=%d, fd=%d, count=%d",
                 binder.get(), info.heap.get(),
                 static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
                 static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
@@ -415,7 +426,7 @@
     free_heap( wp<IBinder>(binder) );
 }
 
-void HeapCache::free_heap(const wp<IBinder>& binder) 
+void HeapCache::free_heap(const wp<IBinder>& binder)
 {
     sp<IMemoryHeap> rel;
     {
@@ -426,7 +437,7 @@
             int32_t c = android_atomic_dec(&info.count);
             if (c == 1) {
                 LOGD_IF(VERBOSE,
-                        "removing binder=%p, heap=%p, size=%d, fd=%d, count=%d", 
+                        "removing binder=%p, heap=%p, size=%d, fd=%d, count=%d",
                         binder.unsafe_get(), info.heap.get(),
                         static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
                         static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
@@ -450,7 +461,7 @@
     return realHeap;
 }
 
-void HeapCache::dump_heaps() 
+void HeapCache::dump_heaps()
 {
     Mutex::Autolock _l(mHeapCacheLock);
     int c = mHeapCache.size();
@@ -459,7 +470,7 @@
         BpMemoryHeap const* h(static_cast<BpMemoryHeap const *>(info.heap.get()));
         LOGD("hey=%p, heap=%p, count=%d, (fd=%d, base=%p, size=%d)",
                 mHeapCache.keyAt(i).unsafe_get(),
-                info.heap.get(), info.count, 
+                info.heap.get(), info.count,
                 h->mHeapId, h->mBase, h->mSize);
     }
 }
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index 9f501e2..bf4a73f 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -40,15 +40,15 @@
 
 // ---------------------------------------------------------------------------
 
-MemoryHeapBase::MemoryHeapBase() 
+MemoryHeapBase::MemoryHeapBase()
     : mFD(-1), mSize(0), mBase(MAP_FAILED),
-      mDevice(NULL), mNeedUnmap(false) 
+      mDevice(NULL), mNeedUnmap(false), mOffset(0)
 {
 }
 
 MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name)
     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
-      mDevice(0), mNeedUnmap(false)
+      mDevice(0), mNeedUnmap(false), mOffset(0)
 {
     const size_t pagesize = getpagesize();
     size = ((size + pagesize-1) & ~(pagesize-1));
@@ -65,7 +65,7 @@
 
 MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags)
     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
-      mDevice(0), mNeedUnmap(false)
+      mDevice(0), mNeedUnmap(false), mOffset(0)
 {
     int open_flags = O_RDWR;
     if (flags & NO_CACHING)
@@ -84,7 +84,7 @@
 
 MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, uint32_t offset)
     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
-      mDevice(0), mNeedUnmap(false)
+      mDevice(0), mNeedUnmap(false), mOffset(0)
 {
     const size_t pagesize = getpagesize();
     size = ((size + pagesize-1) & ~(pagesize-1));
@@ -141,6 +141,7 @@
     }
     mFD = fd;
     mSize = size;
+    mOffset = offset;
     return NO_ERROR;
 }
 
@@ -183,5 +184,9 @@
     return mDevice;
 }
 
+uint32_t MemoryHeapBase::getOffset() const {
+    return mOffset;
+}
+
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/libs/binder/Permission.cpp b/libs/binder/Permission.cpp
deleted file mode 100644
index fd8fe69..0000000
--- a/libs/binder/Permission.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#include <stdint.h>
-#include <utils/Log.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/Permission.h>
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-Permission::Permission(char const* name)
-    : mPermissionName(name), mPid(getpid())
-{
-}
-
-Permission::Permission(const String16& name)
-    : mPermissionName(name), mPid(getpid())
-{
-}
-
-Permission::Permission(const Permission& rhs)
-    : mPermissionName(rhs.mPermissionName),
-    mGranted(rhs.mGranted),
-    mPid(rhs.mPid)
-{
-}
-
-Permission::~Permission()
-{
-}
-
-bool Permission::operator < (const Permission& rhs) const
-{
-    return mPermissionName < rhs.mPermissionName;
-}
-
-bool Permission::checkCalling() const
-{
-    IPCThreadState* ipcState = IPCThreadState::self();
-    pid_t pid = ipcState->getCallingPid();
-    uid_t uid = ipcState->getCallingUid();
-    return doCheckPermission(pid, uid);
-}
-
-bool Permission::check(pid_t pid, uid_t uid) const
-{
-    return doCheckPermission(pid, uid);
-}
-
-bool Permission::doCheckPermission(pid_t pid, uid_t uid) const
-{
-    if ((uid == 0) || (pid == mPid)) {
-        // root and ourselves is always okay
-        return true;
-    } else {
-        // see if we already granted this permission for this uid
-        Mutex::Autolock _l(mLock);
-        if (mGranted.indexOf(uid) >= 0)
-            return true;
-    }
-
-    bool granted = checkPermission(mPermissionName, pid, uid);
-    if (granted) {
-        Mutex::Autolock _l(mLock);
-        // no need to check again, the old item will be replaced if it is
-        // already there.
-        mGranted.add(uid);
-    }
-    return granted;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/libs/binder/PermissionCache.cpp b/libs/binder/PermissionCache.cpp
new file mode 100644
index 0000000..7278187
--- /dev/null
+++ b/libs/binder/PermissionCache.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#define LOG_TAG "PermissionCache"
+
+#include <stdint.h>
+#include <utils/Log.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/PermissionCache.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+ANDROID_SINGLETON_STATIC_INSTANCE(PermissionCache) ;
+
+// ----------------------------------------------------------------------------
+
+PermissionCache::PermissionCache() {
+}
+
+status_t PermissionCache::check(bool* granted,
+        const String16& permission, uid_t uid) const {
+    Mutex::Autolock _l(mLock);
+    Entry e;
+    e.name = permission;
+    e.uid  = uid;
+    ssize_t index = mCache.indexOf(e);
+    if (index >= 0) {
+        *granted = mCache.itemAt(index).granted;
+        return NO_ERROR;
+    }
+    return NAME_NOT_FOUND;
+}
+
+void PermissionCache::cache(const String16& permission,
+        uid_t uid, bool granted) {
+    Mutex::Autolock _l(mLock);
+    Entry e;
+    ssize_t index = mPermissionNamesPool.indexOf(permission);
+    if (index > 0) {
+        e.name = mPermissionNamesPool.itemAt(index);
+    } else {
+        mPermissionNamesPool.add(permission);
+        e.name = permission;
+    }
+    // note, we don't need to store the pid, which is not actually used in
+    // permission checks
+    e.uid  = uid;
+    e.granted = granted;
+    index = mCache.indexOf(e);
+    if (index < 0) {
+        mCache.add(e);
+    }
+}
+
+void PermissionCache::purge() {
+    Mutex::Autolock _l(mLock);
+    mCache.clear();
+}
+
+bool PermissionCache::checkCallingPermission(const String16& permission) {
+    return PermissionCache::checkCallingPermission(permission, NULL, NULL);
+}
+
+bool PermissionCache::checkCallingPermission(
+        const String16& permission, int32_t* outPid, int32_t* outUid) {
+    IPCThreadState* ipcState = IPCThreadState::self();
+    pid_t pid = ipcState->getCallingPid();
+    uid_t uid = ipcState->getCallingUid();
+    if (outPid) *outPid = pid;
+    if (outUid) *outUid = uid;
+    return PermissionCache::checkPermission(permission, pid, uid);
+}
+
+bool PermissionCache::checkPermission(
+        const String16& permission, pid_t pid, uid_t uid) {
+    if ((uid == 0) || (pid == getpid())) {
+        // root and ourselves is always okay
+        return true;
+    }
+
+    PermissionCache& pc(PermissionCache::getInstance());
+    bool granted = false;
+    if (pc.check(&granted, permission, uid) != NO_ERROR) {
+        nsecs_t t = -systemTime();
+        granted = android::checkPermission(permission, pid, uid);
+        t += systemTime();
+        LOGD("checking %s for uid=%d => %s (%d us)",
+                String8(permission).string(), uid,
+                granted?"granted":"denied", (int)ns2us(t));
+        pc.cache(permission, uid, granted);
+    }
+    return granted;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 2d4e10d..7264ac4 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -43,8 +43,6 @@
 
 #define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
 
-static bool gSingleProcess = false;
-
 
 // ---------------------------------------------------------------------------
 
@@ -82,12 +80,6 @@
     return gProcess;
 }
 
-void ProcessState::setSingleProcess(bool singleProcess)
-{
-    gSingleProcess = singleProcess;
-}
-
-
 void ProcessState::setContextObject(const sp<IBinder>& object)
 {
     setContextObject(object, String16("default"));
@@ -95,11 +87,7 @@
 
 sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
 {
-    if (supportsProcesses()) {
-        return getStrongProxyForHandle(0);
-    } else {
-        return getContextObject(String16("default"), caller);
-    }
+    return getStrongProxyForHandle(0);
 }
 
 void ProcessState::setContextObject(const sp<IBinder>& object, const String16& name)
@@ -144,11 +132,6 @@
     return object;
 }
 
-bool ProcessState::supportsProcesses() const
-{
-    return mDriverFD >= 0;
-}
-
 void ProcessState::startThreadPool()
 {
     AutoMutex _l(mLock);
@@ -169,24 +152,19 @@
         AutoMutex _l(mLock);
         mBinderContextCheckFunc = checkFunc;
         mBinderContextUserData = userData;
-        if (mDriverFD >= 0) {
-            int dummy = 0;
+
+        int dummy = 0;
 #if defined(HAVE_ANDROID_OS)
-            status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
+        status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
 #else
-            status_t result = INVALID_OPERATION;
+        status_t result = INVALID_OPERATION;
 #endif
-            if (result == 0) {
-                mManagesContexts = true;
-            } else if (result == -1) {
-                mBinderContextCheckFunc = NULL;
-                mBinderContextUserData = NULL;
-                LOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
-            }
-        } else {
-            // If there is no driver, our only world is the local
-            // process so we can always become the context manager there.
+        if (result == 0) {
             mManagesContexts = true;
+        } else if (result == -1) {
+            mBinderContextCheckFunc = NULL;
+            mBinderContextUserData = NULL;
+            LOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
         }
     }
     return mManagesContexts;
@@ -322,10 +300,6 @@
 
 static int open_driver()
 {
-    if (gSingleProcess) {
-        return -1;
-    }
-
     int fd = open("/dev/binder", O_RDWR);
     if (fd >= 0) {
         fcntl(fd, F_SETFD, FD_CLOEXEC);
@@ -386,9 +360,8 @@
         mDriverFD = -1;
 #endif
     }
-    if (mDriverFD < 0) {
-        // Need to run without the driver, starting our own thread pool.
-    }
+
+    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
 }
 
 ProcessState::~ProcessState()
diff --git a/libs/camera/Android.mk b/libs/camera/Android.mk
index b17b3d2..dc00957 100644
--- a/libs/camera/Android.mk
+++ b/libs/camera/Android.mk
@@ -6,7 +6,9 @@
 	CameraParameters.cpp \
 	ICamera.cpp \
 	ICameraClient.cpp \
-	ICameraService.cpp
+	ICameraService.cpp \
+	ICameraRecordingProxy.cpp \
+	ICameraRecordingProxyListener.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp
index 5eb48da..3c00db5 100644
--- a/libs/camera/Camera.cpp
+++ b/libs/camera/Camera.cpp
@@ -19,11 +19,12 @@
 #define LOG_TAG "Camera"
 #include <utils/Log.h>
 #include <utils/threads.h>
-
+#include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/IMemory.h>
 
 #include <camera/Camera.h>
+#include <camera/ICameraRecordingProxyListener.h>
 #include <camera/ICameraService.h>
 
 #include <surfaceflinger/Surface.h>
@@ -236,6 +237,10 @@
 void Camera::stopRecording()
 {
     LOGV("stopRecording");
+    {
+        Mutex::Autolock _l(mLock);
+        mRecordingProxyListener.clear();
+    }
     sp <ICamera> c = mCamera;
     if (c == 0) return;
     c->stopRecording();
@@ -327,6 +332,12 @@
     mListener = listener;
 }
 
+void Camera::setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener)
+{
+    Mutex::Autolock _l(mLock);
+    mRecordingProxyListener = listener;
+}
+
 void Camera::setPreviewCallbackFlags(int flag)
 {
     LOGV("setPreviewCallbackFlags");
@@ -364,6 +375,19 @@
 // callback from camera service when timestamped frame is ready
 void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
 {
+    // If recording proxy listener is registered, forward the frame and return.
+    // The other listener (mListener) is ignored because the receiver needs to
+    // call releaseRecordingFrame.
+    sp<ICameraRecordingProxyListener> proxylistener;
+    {
+        Mutex::Autolock _l(mLock);
+        proxylistener = mRecordingProxyListener;
+    }
+    if (proxylistener != NULL) {
+        proxylistener->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+        return;
+    }
+
     sp<CameraListener> listener;
     {
         Mutex::Autolock _l(mLock);
@@ -389,4 +413,34 @@
     LOGW("Camera server died!");
 }
 
+sp<ICameraRecordingProxy> Camera::getRecordingProxy() {
+    LOGV("getProxy");
+    return new RecordingProxy(this);
+}
+
+status_t Camera::RecordingProxy::startRecording(const sp<ICameraRecordingProxyListener>& listener)
+{
+    LOGV("RecordingProxy::startRecording");
+    mCamera->setRecordingProxyListener(listener);
+    mCamera->reconnect();
+    return mCamera->startRecording();
+}
+
+void Camera::RecordingProxy::stopRecording()
+{
+    LOGV("RecordingProxy::stopRecording");
+    mCamera->stopRecording();
+}
+
+void Camera::RecordingProxy::releaseRecordingFrame(const sp<IMemory>& mem)
+{
+    LOGV("RecordingProxy::releaseRecordingFrame");
+    mCamera->releaseRecordingFrame(mem);
+}
+
+Camera::RecordingProxy::RecordingProxy(const sp<Camera>& camera)
+{
+    mCamera = camera;
+}
+
 }; // namespace android
diff --git a/libs/camera/ICameraRecordingProxy.cpp b/libs/camera/ICameraRecordingProxy.cpp
new file mode 100644
index 0000000..64b6a5c
--- /dev/null
+++ b/libs/camera/ICameraRecordingProxy.cpp
@@ -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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ICameraRecordingProxy"
+#include <camera/ICameraRecordingProxy.h>
+#include <camera/ICameraRecordingProxyListener.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <stdint.h>
+#include <utils/Log.h>
+
+namespace android {
+
+enum {
+    START_RECORDING = IBinder::FIRST_CALL_TRANSACTION,
+    STOP_RECORDING,
+    RELEASE_RECORDING_FRAME,
+};
+
+
+class BpCameraRecordingProxy: public BpInterface<ICameraRecordingProxy>
+{
+public:
+    BpCameraRecordingProxy(const sp<IBinder>& impl)
+        : BpInterface<ICameraRecordingProxy>(impl)
+    {
+    }
+
+    status_t startRecording(const sp<ICameraRecordingProxyListener>& listener)
+    {
+        LOGV("startRecording");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+        data.writeStrongBinder(listener->asBinder());
+        remote()->transact(START_RECORDING, data, &reply);
+        return reply.readInt32();
+    }
+
+    void stopRecording()
+    {
+        LOGV("stopRecording");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+        remote()->transact(STOP_RECORDING, data, &reply);
+    }
+
+    void releaseRecordingFrame(const sp<IMemory>& mem)
+    {
+        LOGV("releaseRecordingFrame");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+        data.writeStrongBinder(mem->asBinder());
+        remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(CameraRecordingProxy, "android.hardware.ICameraRecordingProxy");
+
+// ----------------------------------------------------------------------
+
+status_t BnCameraRecordingProxy::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case START_RECORDING: {
+            LOGV("START_RECORDING");
+            CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+            sp<ICameraRecordingProxyListener> listener =
+                interface_cast<ICameraRecordingProxyListener>(data.readStrongBinder());
+            reply->writeInt32(startRecording(listener));
+            return NO_ERROR;
+        } break;
+        case STOP_RECORDING: {
+            LOGV("STOP_RECORDING");
+            CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+            stopRecording();
+            return NO_ERROR;
+        } break;
+        case RELEASE_RECORDING_FRAME: {
+            LOGV("RELEASE_RECORDING_FRAME");
+            CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+            sp<IMemory> mem = interface_cast<IMemory>(data.readStrongBinder());
+            releaseRecordingFrame(mem);
+            return NO_ERROR;
+        } break;
+
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/libs/camera/ICameraRecordingProxyListener.cpp b/libs/camera/ICameraRecordingProxyListener.cpp
new file mode 100644
index 0000000..f8cece5
--- /dev/null
+++ b/libs/camera/ICameraRecordingProxyListener.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ICameraRecordingProxyListener"
+#include <camera/ICameraRecordingProxyListener.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <utils/Log.h>
+
+namespace android {
+
+enum {
+    DATA_CALLBACK_TIMESTAMP = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpCameraRecordingProxyListener: public BpInterface<ICameraRecordingProxyListener>
+{
+public:
+    BpCameraRecordingProxyListener(const sp<IBinder>& impl)
+        : BpInterface<ICameraRecordingProxyListener>(impl)
+    {
+    }
+
+    void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& imageData)
+    {
+        LOGV("dataCallback");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraRecordingProxyListener::getInterfaceDescriptor());
+        data.writeInt64(timestamp);
+        data.writeInt32(msgType);
+        data.writeStrongBinder(imageData->asBinder());
+        remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(CameraRecordingProxyListener, "android.hardware.ICameraRecordingProxyListener");
+
+// ----------------------------------------------------------------------
+
+status_t BnCameraRecordingProxyListener::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case DATA_CALLBACK_TIMESTAMP: {
+            LOGV("DATA_CALLBACK_TIMESTAMP");
+            CHECK_INTERFACE(ICameraRecordingProxyListener, data, reply);
+            nsecs_t timestamp = data.readInt64();
+            int32_t msgType = data.readInt32();
+            sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
+            dataCallbackTimestamp(timestamp, msgType, imageData);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp
index 0cd51da..30f8d00 100644
--- a/libs/gui/IGraphicBufferAlloc.cpp
+++ b/libs/gui/IGraphicBufferAlloc.cpp
@@ -43,7 +43,7 @@
     }
 
     virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
-            PixelFormat format, uint32_t usage) {
+            PixelFormat format, uint32_t usage, status_t* error) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());
         data.writeInt32(w);
@@ -52,14 +52,15 @@
         data.writeInt32(usage);
         remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
         sp<GraphicBuffer> graphicBuffer;
-        bool nonNull = (bool)reply.readInt32();
-        if (nonNull) {
+        status_t result = reply.readInt32();
+        if (result == NO_ERROR) {
             graphicBuffer = new GraphicBuffer();
             reply.read(*graphicBuffer);
             // reply.readStrongBinder();
             // here we don't even have to read the BufferReference from
             // the parcel, it'll die with the parcel.
         }
+        *error = result;
         return graphicBuffer;
     }
 };
@@ -91,8 +92,10 @@
             uint32_t h = data.readInt32();
             PixelFormat format = data.readInt32();
             uint32_t usage = data.readInt32();
-            sp<GraphicBuffer> result(createGraphicBuffer(w, h, format, usage));
-            reply->writeInt32(result != 0);
+            status_t error;
+            sp<GraphicBuffer> result =
+                    createGraphicBuffer(w, h, format, usage, &error);
+            reply->writeInt32(error);
             if (result != 0) {
                 reply->write(*result);
                 // We add a BufferReference to this parcel to make sure the
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 40450a3..c1156d5 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -25,6 +25,8 @@
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 
+#include <private/surfaceflinger/LayerState.h>
+
 #include <surfaceflinger/ISurfaceComposer.h>
 
 #include <ui/DisplayInfo.h>
@@ -74,18 +76,17 @@
         return interface_cast<IMemoryHeap>(reply.readStrongBinder());
     }
 
-    virtual void openGlobalTransaction()
+    virtual void setTransactionState(const Vector<ComposerState>& state)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        remote()->transact(BnSurfaceComposer::OPEN_GLOBAL_TRANSACTION, data, &reply);
-    }
-
-    virtual void closeGlobalTransaction()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        remote()->transact(BnSurfaceComposer::CLOSE_GLOBAL_TRANSACTION, data, &reply);
+        Vector<ComposerState>::const_iterator b(state.begin());
+        Vector<ComposerState>::const_iterator e(state.end());
+        data.writeInt32(state.size());
+        for ( ; b != e ; ++b ) {
+            b->write(data);
+        }
+        remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
     }
 
     virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags)
@@ -218,13 +219,17 @@
             sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
             reply->writeStrongBinder(b);
         } break;
-        case OPEN_GLOBAL_TRANSACTION: {
+        case SET_TRANSACTION_STATE: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            openGlobalTransaction();
-        } break;
-        case CLOSE_GLOBAL_TRANSACTION: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            closeGlobalTransaction();
+            size_t count = data.readInt32();
+            ComposerState s;
+            Vector<ComposerState> state;
+            state.setCapacity(count);
+            for (size_t i=0 ; i<count ; i++) {
+                s.read(data);
+                state.add(s);
+            }
+            setTransactionState(state);
         } break;
         case SET_ORIENTATION: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index 8d83392..bc97cac 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -51,8 +51,7 @@
 
 enum {
     CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
-    DESTROY_SURFACE,
-    SET_STATE
+    DESTROY_SURFACE
 };
 
 class BpSurfaceComposerClient : public BpInterface<ISurfaceComposerClient>
@@ -92,17 +91,6 @@
         remote()->transact(DESTROY_SURFACE, data, &reply);
         return reply.readInt32();
     }
-
-    virtual status_t setState(int32_t count, const layer_state_t* states)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
-        data.writeInt32(count);
-        for (int i=0 ; i<count ; i++)
-            states[i].write(data);
-        remote()->transact(SET_STATE, data, &reply);
-        return reply.readInt32();
-    }
 };
 
 IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClient");
@@ -133,17 +121,6 @@
             reply->writeInt32( destroySurface( data.readInt32() ) );
             return NO_ERROR;
         } break;
-        case SET_STATE: {
-            CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
-            int32_t count = data.readInt32();
-            layer_state_t* states = new layer_state_t[count];
-            for (int i=0 ; i<count ; i++)
-                states[i].read(data);
-            status_t err = setState(count, states);
-            delete [] states;
-            reply->writeInt32(err);
-            return NO_ERROR;
-        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 01c4c7e..87901e8 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -17,6 +17,7 @@
 #include <utils/Errors.h>
 #include <binder/Parcel.h>
 #include <private/surfaceflinger/LayerState.h>
+#include <surfaceflinger/ISurfaceComposerClient.h>
 
 namespace android {
 
@@ -58,4 +59,14 @@
     return NO_ERROR;
 }
 
+status_t ComposerState::write(Parcel& output) const {
+    output.writeStrongBinder(client->asBinder());
+    return state.write(output);
+}
+
+status_t ComposerState::read(const Parcel& input) {
+    client = interface_cast<ISurfaceComposerClient>(input.readStrongBinder());
+    return state.read(input);
+}
+
 }; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 1678711..8cead80 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -74,75 +74,52 @@
 
 // ---------------------------------------------------------------------------
 
+// NOTE: this is NOT a member function (it's a friend defined with its
+// declaration).
+static inline
+int compare_type( const ComposerState& lhs, const ComposerState& rhs) {
+    if (lhs.client < rhs.client)  return -1;
+    if (lhs.client > rhs.client)  return 1;
+    if (lhs.state.surface < rhs.state.surface)  return -1;
+    if (lhs.state.surface > rhs.state.surface)  return 1;
+    return 0;
+}
+
 class Composer : public Singleton<Composer>
 {
-    Mutex mLock;
-    SortedVector< wp<SurfaceComposerClient> > mActiveConnections;
-    SortedVector<sp<SurfaceComposerClient> > mOpenTransactions;
-
-    Composer() : Singleton<Composer>() {
-    }
-
-    void addClientImpl(const sp<SurfaceComposerClient>& client) {
-        Mutex::Autolock _l(mLock);
-        mActiveConnections.add(client);
-    }
-
-    void removeClientImpl(const sp<SurfaceComposerClient>& client) {
-        Mutex::Autolock _l(mLock);
-        mActiveConnections.remove(client);
-    }
-
-    void openGlobalTransactionImpl()
-    {
-        Mutex::Autolock _l(mLock);
-        if (mOpenTransactions.size()) {
-            LOGE("openGlobalTransaction() called more than once. skipping.");
-            return;
-        }
-        const size_t N = mActiveConnections.size();
-        for (size_t i=0; i<N; i++) {
-            sp<SurfaceComposerClient> client(mActiveConnections[i].promote());
-            if (client != 0 && mOpenTransactions.indexOf(client) < 0) {
-                if (client->openTransaction() == NO_ERROR) {
-                    mOpenTransactions.add(client);
-                } else {
-                    LOGE("openTransaction on client %p failed", client.get());
-                    // let it go, it'll fail later when the user
-                    // tries to do something with the transaction
-                }
-            }
-        }
-    }
-
-    void closeGlobalTransactionImpl()
-    {
-        mLock.lock();
-            SortedVector< sp<SurfaceComposerClient> > clients(mOpenTransactions);
-            mOpenTransactions.clear();
-        mLock.unlock();
-
-        sp<ISurfaceComposer> sm(getComposerService());
-        sm->openGlobalTransaction();
-            const size_t N = clients.size();
-            for (size_t i=0; i<N; i++) {
-                clients[i]->closeTransaction();
-            }
-        sm->closeGlobalTransaction();
-    }
-
     friend class Singleton<Composer>;
 
+    mutable Mutex               mLock;
+    SortedVector<ComposerState> mStates;
+
+    Composer() : Singleton<Composer>() { }
+
+    void closeGlobalTransactionImpl();
+
+    layer_state_t* getLayerStateLocked(
+            const sp<SurfaceComposerClient>& client, SurfaceID id);
+
 public:
-    static void addClient(const sp<SurfaceComposerClient>& client) {
-        Composer::getInstance().addClientImpl(client);
-    }
-    static void removeClient(const sp<SurfaceComposerClient>& client) {
-        Composer::getInstance().removeClientImpl(client);
-    }
-    static void openGlobalTransaction() {
-        Composer::getInstance().openGlobalTransactionImpl();
-    }
+
+    status_t setPosition(const sp<SurfaceComposerClient>& client, SurfaceID id,
+            int32_t x, int32_t y);
+    status_t setSize(const sp<SurfaceComposerClient>& client, SurfaceID id,
+            uint32_t w, uint32_t h);
+    status_t setLayer(const sp<SurfaceComposerClient>& client, SurfaceID id,
+            int32_t z);
+    status_t setFlags(const sp<SurfaceComposerClient>& client, SurfaceID id,
+            uint32_t flags, uint32_t mask);
+    status_t setTransparentRegionHint(
+            const sp<SurfaceComposerClient>& client, SurfaceID id,
+            const Region& transparentRegion);
+    status_t setAlpha(const sp<SurfaceComposerClient>& client, SurfaceID id,
+            float alpha);
+    status_t setMatrix(const sp<SurfaceComposerClient>& client, SurfaceID id,
+            float dsdx, float dtdx, float dsdy, float dtdy);
+    status_t setFreezeTint(
+            const sp<SurfaceComposerClient>& client, SurfaceID id,
+            uint32_t tint);
+
     static void closeGlobalTransaction() {
         Composer::getInstance().closeGlobalTransactionImpl();
     }
@@ -152,69 +129,306 @@
 
 // ---------------------------------------------------------------------------
 
-static inline int compare_type( const layer_state_t& lhs,
-                                const layer_state_t& rhs) {
-    if (lhs.surface < rhs.surface)  return -1;
-    if (lhs.surface > rhs.surface)  return 1;
-    return 0;
+void Composer::closeGlobalTransactionImpl() {
+    sp<ISurfaceComposer> sm(getComposerService());
+
+    Vector<ComposerState> transaction;
+
+    { // scope for the lock
+        Mutex::Autolock _l(mLock);
+        transaction = mStates;
+        mStates.clear();
+    }
+
+   sm->setTransactionState(transaction);
 }
 
+layer_state_t* Composer::getLayerStateLocked(
+        const sp<SurfaceComposerClient>& client, SurfaceID id) {
+
+    ComposerState s;
+    s.client = client->mClient;
+    s.state.surface = id;
+
+    ssize_t index = mStates.indexOf(s);
+    if (index < 0) {
+        // we don't have it, add an initialized layer_state to our list
+        index = mStates.add(s);
+    }
+
+    ComposerState* const out = mStates.editArray();
+    return &(out[index].state);
+}
+
+status_t Composer::setPosition(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, int32_t x, int32_t y) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::ePositionChanged;
+    s->x = x;
+    s->y = y;
+    return NO_ERROR;
+}
+
+status_t Composer::setSize(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, uint32_t w, uint32_t h) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eSizeChanged;
+    s->w = w;
+    s->h = h;
+    return NO_ERROR;
+}
+
+status_t Composer::setLayer(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, int32_t z) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eLayerChanged;
+    s->z = z;
+    return NO_ERROR;
+}
+
+status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, uint32_t flags,
+        uint32_t mask) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eVisibilityChanged;
+    s->flags &= ~mask;
+    s->flags |= (flags & mask);
+    s->mask |= mask;
+    return NO_ERROR;
+}
+
+status_t Composer::setTransparentRegionHint(
+        const sp<SurfaceComposerClient>& client, SurfaceID id,
+        const Region& transparentRegion) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eTransparentRegionChanged;
+    s->transparentRegion = transparentRegion;
+    return NO_ERROR;
+}
+
+status_t Composer::setAlpha(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, float alpha) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eAlphaChanged;
+    s->alpha = alpha;
+    return NO_ERROR;
+}
+
+status_t Composer::setMatrix(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, float dsdx, float dtdx,
+        float dsdy, float dtdy) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eMatrixChanged;
+    layer_state_t::matrix22_t matrix;
+    matrix.dsdx = dsdx;
+    matrix.dtdx = dtdx;
+    matrix.dsdy = dsdy;
+    matrix.dtdy = dtdy;
+    s->matrix = matrix;
+    return NO_ERROR;
+}
+
+status_t Composer::setFreezeTint(const sp<SurfaceComposerClient>& client,
+        SurfaceID id, uint32_t tint) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s)
+        return BAD_INDEX;
+    s->what |= ISurfaceComposer::eFreezeTintChanged;
+    s->tint = tint;
+    return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+
 SurfaceComposerClient::SurfaceComposerClient()
-    : mTransactionOpen(0), mPrebuiltLayerState(0), mStatus(NO_INIT)
+    : mStatus(NO_INIT), mComposer(Composer::getInstance())
 {
 }
 
-void SurfaceComposerClient::onFirstRef()
-{
+void SurfaceComposerClient::onFirstRef() {
     sp<ISurfaceComposer> sm(getComposerService());
     if (sm != 0) {
         sp<ISurfaceComposerClient> conn = sm->createConnection();
         if (conn != 0) {
             mClient = conn;
-            Composer::addClient(this);
-            mPrebuiltLayerState = new layer_state_t;
             mStatus = NO_ERROR;
         }
     }
 }
 
-SurfaceComposerClient::~SurfaceComposerClient()
-{
-    delete mPrebuiltLayerState;
+SurfaceComposerClient::~SurfaceComposerClient() {
     dispose();
 }
 
-status_t SurfaceComposerClient::initCheck() const
-{
+status_t SurfaceComposerClient::initCheck() const {
     return mStatus;
 }
 
-sp<IBinder> SurfaceComposerClient::connection() const
-{
+sp<IBinder> SurfaceComposerClient::connection() const {
     return (mClient != 0) ? mClient->asBinder() : 0;
 }
 
 status_t SurfaceComposerClient::linkToComposerDeath(
         const sp<IBinder::DeathRecipient>& recipient,
-        void* cookie, uint32_t flags)
-{
+        void* cookie, uint32_t flags) {
     sp<ISurfaceComposer> sm(getComposerService());
     return sm->asBinder()->linkToDeath(recipient, cookie, flags);
 }
 
-void SurfaceComposerClient::dispose()
-{
+void SurfaceComposerClient::dispose() {
     // this can be called more than once.
     sp<ISurfaceComposerClient> client;
     Mutex::Autolock _lm(mLock);
     if (mClient != 0) {
-        Composer::removeClient(this);
         client = mClient; // hold ref while lock is held
         mClient.clear();
     }
     mStatus = NO_INIT;
 }
 
+sp<SurfaceControl> SurfaceComposerClient::createSurface(
+        DisplayID display,
+        uint32_t w,
+        uint32_t h,
+        PixelFormat format,
+        uint32_t flags)
+{
+    String8 name;
+    const size_t SIZE = 128;
+    char buffer[SIZE];
+    snprintf(buffer, SIZE, "<pid_%d>", getpid());
+    name.append(buffer);
+
+    return SurfaceComposerClient::createSurface(name, display,
+            w, h, format, flags);
+}
+
+sp<SurfaceControl> SurfaceComposerClient::createSurface(
+        const String8& name,
+        DisplayID display,
+        uint32_t w,
+        uint32_t h,
+        PixelFormat format,
+        uint32_t flags)
+{
+    sp<SurfaceControl> result;
+    if (mStatus == NO_ERROR) {
+        ISurfaceComposerClient::surface_data_t data;
+        sp<ISurface> surface = mClient->createSurface(&data, name,
+                display, w, h, format, flags);
+        if (surface != 0) {
+            result = new SurfaceControl(this, surface, data, w, h, format, flags);
+        }
+    }
+    return result;
+}
+
+status_t SurfaceComposerClient::destroySurface(SurfaceID sid) {
+    if (mStatus != NO_ERROR)
+        return mStatus;
+    status_t err = mClient->destroySurface(sid);
+    return err;
+}
+
+inline Composer& SurfaceComposerClient::getComposer() {
+    return mComposer;
+}
+
+// ----------------------------------------------------------------------------
+
+void SurfaceComposerClient::openGlobalTransaction() {
+    // Currently a no-op
+}
+
+void SurfaceComposerClient::closeGlobalTransaction() {
+    Composer::closeGlobalTransaction();
+}
+
+// ----------------------------------------------------------------------------
+
+status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) {
+    return getComposer().setFreezeTint(this, id, tint);
+}
+
+status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y) {
+    return getComposer().setPosition(this, id, x, y);
+}
+
+status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h) {
+    return getComposer().setSize(this, id, w, h);
+}
+
+status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z) {
+    return getComposer().setLayer(this, id, z);
+}
+
+status_t SurfaceComposerClient::hide(SurfaceID id) {
+    return getComposer().setFlags(this, id,
+            ISurfaceComposer::eLayerHidden,
+            ISurfaceComposer::eLayerHidden);
+}
+
+status_t SurfaceComposerClient::show(SurfaceID id, int32_t) {
+    return getComposer().setFlags(this, id,
+            0,
+            ISurfaceComposer::eLayerHidden);
+}
+
+status_t SurfaceComposerClient::freeze(SurfaceID id) {
+    return getComposer().setFlags(this, id,
+            ISurfaceComposer::eLayerFrozen,
+            ISurfaceComposer::eLayerFrozen);
+}
+
+status_t SurfaceComposerClient::unfreeze(SurfaceID id) {
+    return getComposer().setFlags(this, id,
+            0,
+            ISurfaceComposer::eLayerFrozen);
+}
+
+status_t SurfaceComposerClient::setFlags(SurfaceID id, uint32_t flags,
+        uint32_t mask) {
+    return getComposer().setFlags(this, id, flags, mask);
+}
+
+status_t SurfaceComposerClient::setTransparentRegionHint(SurfaceID id,
+        const Region& transparentRegion) {
+    return getComposer().setTransparentRegionHint(this, id, transparentRegion);
+}
+
+status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha) {
+    return getComposer().setAlpha(this, id, alpha);
+}
+
+status_t SurfaceComposerClient::setMatrix(SurfaceID id, float dsdx, float dtdx,
+        float dsdy, float dtdy) {
+    return getComposer().setMatrix(this, id, dsdx, dtdx, dsdy, dtdy);
+}
+
+// ----------------------------------------------------------------------------
+
 status_t SurfaceComposerClient::getDisplayInfo(
         DisplayID dpy, DisplayInfo* info)
 {
@@ -273,70 +487,7 @@
     return n;
 }
 
-sp<SurfaceControl> SurfaceComposerClient::createSurface(
-        DisplayID display,
-        uint32_t w,
-        uint32_t h,
-        PixelFormat format,
-        uint32_t flags)
-{
-    String8 name;
-    const size_t SIZE = 128;
-    char buffer[SIZE];
-    snprintf(buffer, SIZE, "<pid_%d>", getpid());
-    name.append(buffer);
-
-    return SurfaceComposerClient::createSurface(name, display,
-            w, h, format, flags);
-}
-
-sp<SurfaceControl> SurfaceComposerClient::createSurface(
-        const String8& name,
-        DisplayID display,
-        uint32_t w,
-        uint32_t h,
-        PixelFormat format,
-        uint32_t flags)
-{
-    sp<SurfaceControl> result;
-    if (mStatus == NO_ERROR) {
-        ISurfaceComposerClient::surface_data_t data;
-        sp<ISurface> surface = mClient->createSurface(&data, name,
-                display, w, h, format, flags);
-        if (surface != 0) {
-            result = new SurfaceControl(this, surface, data, w, h, format, flags);
-        }
-    }
-    return result;
-}
-
-status_t SurfaceComposerClient::destroySurface(SurfaceID sid)
-{
-    if (mStatus != NO_ERROR)
-        return mStatus;
-
-    // it's okay to destroy a surface while a transaction is open,
-    // (transactions really are a client-side concept)
-    // however, this indicates probably a misuse of the API or a bug
-    // in the client code.
-    LOGW_IF(mTransactionOpen,
-         "Destroying surface while a transaction is open. "
-         "Client %p: destroying surface %d, mTransactionOpen=%d",
-         this, sid, mTransactionOpen);
-
-    status_t err = mClient->destroySurface(sid);
-    return err;
-}
-
-void SurfaceComposerClient::openGlobalTransaction()
-{
-    Composer::openGlobalTransaction();
-}
-
-void SurfaceComposerClient::closeGlobalTransaction()
-{
-    Composer::closeGlobalTransaction();
-}
+// ----------------------------------------------------------------------------
 
 status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags)
 {
@@ -350,199 +501,13 @@
     return sm->unfreezeDisplay(dpy, flags);
 }
 
-int SurfaceComposerClient::setOrientation(DisplayID dpy, 
+int SurfaceComposerClient::setOrientation(DisplayID dpy,
         int orientation, uint32_t flags)
 {
     sp<ISurfaceComposer> sm(getComposerService());
     return sm->setOrientation(dpy, orientation, flags);
 }
 
-status_t SurfaceComposerClient::openTransaction()
-{
-    if (mStatus != NO_ERROR)
-        return mStatus;
-    Mutex::Autolock _l(mLock);
-    mTransactionOpen++;
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::closeTransaction()
-{
-    if (mStatus != NO_ERROR)
-        return mStatus;
-
-    Mutex::Autolock _l(mLock);
-    if (mTransactionOpen <= 0) {
-        LOGE(   "closeTransaction (client %p, mTransactionOpen=%d) "
-                "called more times than openTransaction()",
-                this, mTransactionOpen);
-        return INVALID_OPERATION;
-    }
-
-    if (mTransactionOpen >= 2) {
-        mTransactionOpen--;
-        return NO_ERROR;
-    }
-
-    mTransactionOpen = 0;
-    const ssize_t count = mStates.size();
-    if (count) {
-        mClient->setState(count, mStates.array());
-        mStates.clear();
-    }
-    return NO_ERROR;
-}
-
-layer_state_t* SurfaceComposerClient::get_state_l(SurfaceID index)
-{
-    // API usage error, do nothing.
-    if (mTransactionOpen<=0) {
-        LOGE("Not in transaction (client=%p, SurfaceID=%d, mTransactionOpen=%d",
-                this, int(index), mTransactionOpen);
-        return 0;
-    }
-
-    // use mPrebuiltLayerState just to find out if we already have it
-    layer_state_t& dummy(*mPrebuiltLayerState);
-    dummy.surface = index;
-    ssize_t i = mStates.indexOf(dummy);
-    if (i < 0) {
-        // we don't have it, add an initialized layer_state to our list
-        i = mStates.add(dummy);
-    }
-    return mStates.editArray() + i;
-}
-
-layer_state_t* SurfaceComposerClient::lockLayerState(SurfaceID id)
-{
-    layer_state_t* s;
-    mLock.lock();
-    s = get_state_l(id);
-    if (!s) mLock.unlock();
-    return s;
-}
-
-void SurfaceComposerClient::unlockLayerState()
-{
-    mLock.unlock();
-}
-
-status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::ePositionChanged;
-    s->x = x;
-    s->y = y;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eSizeChanged;
-    s->w = w;
-    s->h = h;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eLayerChanged;
-    s->z = z;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::hide(SurfaceID id)
-{
-    return setFlags(id, ISurfaceComposer::eLayerHidden,
-            ISurfaceComposer::eLayerHidden);
-}
-
-status_t SurfaceComposerClient::show(SurfaceID id, int32_t)
-{
-    return setFlags(id, 0, ISurfaceComposer::eLayerHidden);
-}
-
-status_t SurfaceComposerClient::freeze(SurfaceID id)
-{
-    return setFlags(id, ISurfaceComposer::eLayerFrozen,
-            ISurfaceComposer::eLayerFrozen);
-}
-
-status_t SurfaceComposerClient::unfreeze(SurfaceID id)
-{
-    return setFlags(id, 0, ISurfaceComposer::eLayerFrozen);
-}
-
-status_t SurfaceComposerClient::setFlags(SurfaceID id,
-        uint32_t flags, uint32_t mask)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eVisibilityChanged;
-    s->flags &= ~mask;
-    s->flags |= (flags & mask);
-    s->mask |= mask;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setTransparentRegionHint(
-        SurfaceID id, const Region& transparentRegion)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eTransparentRegionChanged;
-    s->transparentRegion = transparentRegion;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eAlphaChanged;
-    s->alpha = alpha;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setMatrix(
-        SurfaceID id,
-        float dsdx, float dtdx,
-        float dsdy, float dtdy )
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eMatrixChanged;
-    layer_state_t::matrix22_t matrix;
-    matrix.dsdx = dsdx;
-    matrix.dtdx = dtdx;
-    matrix.dsdy = dsdy;
-    matrix.dtdy = dtdy;
-    s->matrix = matrix;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint)
-{
-    layer_state_t* s = lockLayerState(id);
-    if (!s) return BAD_INDEX;
-    s->what |= ISurfaceComposer::eFreezeTintChanged;
-    s->tint = tint;
-    unlockLayerState();
-    return NO_ERROR;
-}
-
 // ----------------------------------------------------------------------------
 
 ScreenshotClient::ScreenshotClient()
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 37e6d11..886a3fb 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -148,6 +148,11 @@
     LOGV("SurfaceTexture::setBufferCount");
     Mutex::Autolock lock(mMutex);
 
+    if (bufferCount > NUM_BUFFER_SLOTS) {
+        LOGE("setBufferCount: bufferCount larger than slots available");
+        return BAD_VALUE;
+    }
+
     // Error out if the user has dequeued buffers
     for (int i=0 ; i<mBufferCount ; i++) {
         if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
@@ -208,7 +213,7 @@
         uint32_t format, uint32_t usage) {
     LOGV("SurfaceTexture::dequeueBuffer");
 
-    if ((w && !h) || (!w & h)) {
+    if ((w && !h) || (!w && h)) {
         LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
         return BAD_VALUE;
     }
@@ -347,11 +352,13 @@
         ((uint32_t(buffer->usage) & usage) != usage))
     {
         usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+        status_t error;
         sp<GraphicBuffer> graphicBuffer(
-                mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
+                mGraphicBufferAlloc->createGraphicBuffer(
+                        w, h, format, usage, &error));
         if (graphicBuffer == 0) {
             LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
-            return NO_MEMORY;
+            return error;
         }
         if (updateFormat) {
             mPixelFormat = format;
@@ -417,17 +424,22 @@
             return -EINVAL;
         }
 
-        if (mQueue.empty()) {
-            listener = mFrameAvailableListener;
-        }
-
         if (mSynchronousMode) {
-            // in synchronous mode we queue all buffers in a FIFO
+            // In synchronous mode we queue all buffers in a FIFO.
             mQueue.push_back(buf);
+
+            // Synchronous mode always signals that an additional frame should
+            // be consumed.
+            listener = mFrameAvailableListener;
         } else {
-            // in asynchronous mode we only keep the most recent buffer
+            // In asynchronous mode we only keep the most recent buffer.
             if (mQueue.empty()) {
                 mQueue.push_back(buf);
+
+                // Asynchronous mode only signals that a frame should be
+                // consumed if no previous frame was pending. If a frame were
+                // pending then the consumer would have already been notified.
+                listener = mFrameAvailableListener;
             } else {
                 Fifo::iterator front(mQueue.begin());
                 // buffer currently queued is freed
@@ -483,24 +495,14 @@
 
 status_t SurfaceTexture::updateTexImage() {
     LOGV("SurfaceTexture::updateTexImage");
-
     Mutex::Autolock lock(mMutex);
 
-    int buf = mCurrentTexture;
+    // In asynchronous mode the list is guaranteed to be one buffer
+    // deep, while in synchronous mode we use the oldest buffer.
     if (!mQueue.empty()) {
-        // in asynchronous mode the list is guaranteed to be one buffer deep,
-        // while in synchronous mode we use the oldest buffer
         Fifo::iterator front(mQueue.begin());
-        buf = *front;
-        mQueue.erase(front);
-        if (mQueue.isEmpty()) {
-            mDequeueCondition.signal();
-        }
-    }
+        int buf = *front;
 
-    // Initially both mCurrentTexture and buf are INVALID_BUFFER_SLOT,
-    // so this check will fail until a buffer gets queued.
-    if (mCurrentTexture != buf) {
         // Update the GL texture object.
         EGLImageKHR image = mSlots[buf].mEglImage;
         if (image == EGL_NO_IMAGE_KHR) {
@@ -538,7 +540,7 @@
         }
 
         if (mCurrentTexture != INVALID_BUFFER_SLOT) {
-            // the current buffer becomes FREE if it was still in the queued
+            // The current buffer becomes FREE if it was still in the queued
             // state. If it has already been given to the client
             // (synchronous mode), then it stays in DEQUEUED state.
             if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED)
@@ -553,17 +555,17 @@
         mCurrentTransform = mSlots[buf].mTransform;
         mCurrentTimestamp = mSlots[buf].mTimestamp;
         computeCurrentTransformMatrix();
+
+        // Now that we've passed the point at which failures can happen,
+        // it's safe to remove the buffer from the front of the queue.
+        mQueue.erase(front);
         mDequeueCondition.signal();
     } else {
         // We always bind the texture even if we don't update its contents.
         glBindTexture(mCurrentTextureTarget, mTexName);
     }
-    return OK;
-}
 
-size_t SurfaceTexture::getQueuedCount() const {
-    Mutex::Autolock lock(mMutex);
-    return mQueue.size();
+    return OK;
 }
 
 bool SurfaceTexture::isExternalFormat(uint32_t format)
@@ -704,10 +706,10 @@
 }
 
 void SurfaceTexture::setFrameAvailableListener(
-        const sp<FrameAvailableListener>& l) {
+        const sp<FrameAvailableListener>& listener) {
     LOGV("SurfaceTexture::setFrameAvailableListener");
     Mutex::Autolock lock(mMutex);
-    mFrameAvailableListener = l;
+    mFrameAvailableListener = listener;
 }
 
 sp<IBinder> SurfaceTexture::getAllocator() {
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index f219639..88433fb 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -84,10 +84,10 @@
             ASSERT_TRUE(mSurfaceControl != NULL);
             ASSERT_TRUE(mSurfaceControl->isValid());
 
-            ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction());
+            SurfaceComposerClient::openGlobalTransaction();
             ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
             ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
-            ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction());
+            SurfaceComposerClient::closeGlobalTransaction();
 
             sp<ANativeWindow> window = mSurfaceControl->getSurface();
             mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
@@ -419,6 +419,31 @@
         ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
     }
 
+    class FrameWaiter : public SurfaceTexture::FrameAvailableListener {
+    public:
+        FrameWaiter():
+                mPendingFrames(0) {
+        }
+
+        void waitForFrame() {
+            Mutex::Autolock lock(mMutex);
+            while (mPendingFrames == 0) {
+                mCondition.wait(mMutex);
+            }
+            mPendingFrames--;
+        }
+
+        virtual void onFrameAvailable() {
+            Mutex::Autolock lock(mMutex);
+            mPendingFrames++;
+            mCondition.signal();
+        }
+
+        int mPendingFrames;
+        Mutex mMutex;
+        Condition mCondition;
+    };
+
     sp<SurfaceTexture> mST;
     sp<SurfaceTextureClient> mSTC;
     sp<ANativeWindow> mANW;
@@ -648,6 +673,157 @@
     }
 }
 
+// This test is intended to catch synchronization bugs between the CPU-written
+// and GPU-read buffers.
+TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) {
+    enum { texWidth = 16 };
+    enum { texHeight = 16 };
+    enum { numFrames = 1024 };
+
+    ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true));
+    ASSERT_EQ(NO_ERROR, mST->setBufferCountServer(2));
+    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+            texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
+    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+            GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+    struct TestPixel {
+        int x;
+        int y;
+    };
+    const TestPixel testPixels[] = {
+        {  4, 11 },
+        { 12, 14 },
+        {  7,  2 },
+    };
+    enum {numTestPixels = sizeof(testPixels) / sizeof(testPixels[0])};
+
+    class ProducerThread : public Thread {
+    public:
+        ProducerThread(const sp<ANativeWindow>& anw, const TestPixel* testPixels):
+                mANW(anw),
+                mTestPixels(testPixels) {
+        }
+
+        virtual ~ProducerThread() {
+        }
+
+        virtual bool threadLoop() {
+            for (int i = 0; i < numFrames; i++) {
+                ANativeWindowBuffer* anb;
+                if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) {
+                    return false;
+                }
+                if (anb == NULL) {
+                    return false;
+                }
+
+                sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+                if (mANW->lockBuffer(mANW.get(), buf->getNativeBuffer())
+                        != NO_ERROR) {
+                    return false;
+                }
+
+                const int yuvTexOffsetY = 0;
+                int stride = buf->getStride();
+                int yuvTexStrideY = stride;
+                int yuvTexOffsetV = yuvTexStrideY * texHeight;
+                int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
+                int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * texHeight/2;
+                int yuvTexStrideU = yuvTexStrideV;
+
+                uint8_t* img = NULL;
+                buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+
+                // Gray out all the test pixels first, so we're more likely to
+                // see a failure if GL is still texturing from the buffer we
+                // just dequeued.
+                for (int j = 0; j < numTestPixels; j++) {
+                    int x = mTestPixels[j].x;
+                    int y = mTestPixels[j].y;
+                    uint8_t value = 128;
+                    img[y*stride + x] = value;
+                }
+
+                // Fill the buffer with gray.
+                for (int y = 0; y < texHeight; y++) {
+                    for (int x = 0; x < texWidth; x++) {
+                        img[yuvTexOffsetY + y*yuvTexStrideY + x] = 128;
+                        img[yuvTexOffsetU + (y/2)*yuvTexStrideU + x/2] = 128;
+                        img[yuvTexOffsetV + (y/2)*yuvTexStrideV + x/2] = 128;
+                    }
+                }
+
+                // Set the test pixels to either white or black.
+                for (int j = 0; j < numTestPixels; j++) {
+                    int x = mTestPixels[j].x;
+                    int y = mTestPixels[j].y;
+                    uint8_t value = 0;
+                    if (j == (i % numTestPixels)) {
+                        value = 255;
+                    }
+                    img[y*stride + x] = value;
+                }
+
+                buf->unlock();
+                if (mANW->queueBuffer(mANW.get(), buf->getNativeBuffer())
+                        != NO_ERROR) {
+                    return false;
+                }
+            }
+            return false;
+        }
+
+        sp<ANativeWindow> mANW;
+        const TestPixel* mTestPixels;
+    };
+
+    sp<FrameWaiter> fw(new FrameWaiter);
+    mST->setFrameAvailableListener(fw);
+
+    sp<Thread> pt(new ProducerThread(mANW, testPixels));
+    pt->run();
+
+    glViewport(0, 0, texWidth, texHeight);
+
+    glClearColor(0.2, 0.2, 0.2, 0.2);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    // We wait for the first two frames up front so that the producer will be
+    // likely to dequeue the buffer that's currently being textured from.
+    fw->waitForFrame();
+    fw->waitForFrame();
+
+    for (int i = 0; i < numFrames; i++) {
+        SCOPED_TRACE(String8::format("frame %d", i).string());
+
+        // We must wait for each frame to come in because if we ever do an
+        // updateTexImage call that doesn't consume a newly available buffer
+        // then the producer and consumer will get out of sync, which will cause
+        // a deadlock.
+        if (i > 1) {
+            fw->waitForFrame();
+        }
+        mST->updateTexImage();
+        drawTexture();
+
+        for (int j = 0; j < numTestPixels; j++) {
+            int x = testPixels[j].x;
+            int y = testPixels[j].y;
+            uint8_t value = 0;
+            if (j == (i % numTestPixels)) {
+                // We must y-invert the texture coords
+                EXPECT_TRUE(checkPixel(x, texHeight-y-1, 255, 255, 255, 255));
+            } else {
+                // We must y-invert the texture coords
+                EXPECT_TRUE(checkPixel(x, texHeight-y-1, 0, 0, 0, 255));
+            }
+        }
+    }
+
+    pt->requestExitAndWait();
+}
+
 // XXX: This test is disabled because there are currently no drivers that can
 // handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target.
 TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferNpot) {
@@ -1004,8 +1180,7 @@
     sp<FrameCondition> mFC;
 };
 
-// XXX: This test is disabled because it causes hangs on some devices.
-TEST_F(SurfaceTextureGLToGLTest, DISABLED_UpdateTexImageBeforeFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedWorks) {
     class PT : public ProducerThread {
         virtual void render() {
             glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
@@ -1023,8 +1198,7 @@
     // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
 }
 
-// XXX: This test is disabled because it causes hangs on some devices.
-TEST_F(SurfaceTextureGLToGLTest, DISABLED_UpdateTexImageAfterFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedWorks) {
     class PT : public ProducerThread {
         virtual void render() {
             glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
@@ -1042,8 +1216,7 @@
     // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
 }
 
-// XXX: This test is disabled because it causes hangs on some devices.
-TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedUpdateTexImageBeforeFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedWorks) {
     enum { NUM_ITERATIONS = 1024 };
 
     class PT : public ProducerThread {
@@ -1071,8 +1244,7 @@
     }
 }
 
-// XXX: This test is disabled because it causes hangs on some devices.
-TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedUpdateTexImageAfterFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedWorks) {
     enum { NUM_ITERATIONS = 1024 };
 
     class PT : public ProducerThread {
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 35c8640..ce587b3 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -31,15 +31,15 @@
         ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
 
         mSurfaceControl = mComposerClient->createSurface(
-                String8("Test Surface"), 0, 32, 32, PIXEL_FORMAT_RGB_888, 0);
+                String8("Test Surface"), 0, 32, 32, PIXEL_FORMAT_RGBA_8888, 0);
 
         ASSERT_TRUE(mSurfaceControl != NULL);
         ASSERT_TRUE(mSurfaceControl->isValid());
 
-        ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction());
-        ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(30000));
+        SurfaceComposerClient::openGlobalTransaction();
+        ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7fffffff));
         ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
-        ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction());
+        SurfaceComposerClient::closeGlobalTransaction();
 
         mSurface = mSurfaceControl->getSurface();
         ASSERT_TRUE(mSurface != NULL);
@@ -84,7 +84,7 @@
     PixelFormat fmt=0;
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt, 64, 64, 0,
-            40000));
+            0x7fffffff));
     ASSERT_TRUE(heap != NULL);
 
     // Set the PROTECTED usage bit and verify that the screenshot fails.  Note
@@ -94,6 +94,18 @@
             GRALLOC_USAGE_PROTECTED));
     ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3));
     ANativeWindowBuffer* buf = 0;
+
+    status_t err = anw->dequeueBuffer(anw.get(), &buf);
+    if (err) {
+        // we could fail if GRALLOC_USAGE_PROTECTED is not supported.
+        // that's okay as long as this is the reason for the failure.
+        // try again without the GRALLOC_USAGE_PROTECTED bit.
+        ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(), 0));
+        ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf));
+        return;
+    }
+    ASSERT_EQ(NO_ERROR, anw->cancelBuffer(anw.get(), buf));
+
     for (int i = 0; i < 4; i++) {
         // Loop to make sure SurfaceFlinger has retired a protected buffer.
         ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf));
@@ -103,7 +115,7 @@
     heap = 0;
     w = h = fmt = 0;
     ASSERT_EQ(INVALID_OPERATION, sf->captureScreen(0, &heap, &w, &h, &fmt,
-            64, 64, 0, 40000));
+            64, 64, 0, 0x7fffffff));
     ASSERT_TRUE(heap == NULL);
 
     // XXX: This should not be needed, but it seems that the new buffers don't
@@ -126,7 +138,7 @@
     heap = 0;
     w = h = fmt = 0;
     ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt, 64, 64, 0,
-            40000));
+            0x7fffffff));
     ASSERT_TRUE(heap != NULL);
 }
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index e43f6e5..8b1caeee 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -699,9 +699,10 @@
                 float* vertices = getFloats(verticesCount);
                 bool hasColors = getInt();
                 int* colors = hasColors ? getInts(colorsCount) : NULL;
+                SkPaint* paint = getPaint();
 
                 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
-                renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, getPaint());
+                renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, paint);
             }
             break;
             case DrawPatch: {
@@ -718,9 +719,15 @@
                 yDivs = getInts(yDivsCount);
                 colors = getUInts(numColors);
 
+                float left = getFloat();
+                float top = getFloat();
+                float right = getFloat();
+                float bottom = getFloat();
+                SkPaint* paint = getPaint();
+
                 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
                 renderer.drawPatch(bitmap, xDivs, yDivs, colors, xDivsCount, yDivsCount,
-                        numColors, getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
+                        numColors, left, top, right, bottom, paint);
             }
             break;
             case DrawColor: {
@@ -799,15 +806,17 @@
             case DrawLines: {
                 int count = 0;
                 float* points = getFloats(count);
+                SkPaint* paint = getPaint();
                 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
-                renderer.drawLines(points, count, getPaint());
+                renderer.drawLines(points, count, paint);
             }
             break;
             case DrawPoints: {
                 int count = 0;
                 float* points = getFloats(count);
+                SkPaint* paint = getPaint();
                 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
-                renderer.drawPoints(points, count, getPaint());
+                renderer.drawPoints(points, count, paint);
             }
             break;
             case DrawText: {
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 0310bc3..3c2d80d 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -27,6 +27,7 @@
 
 #include "Rect.h"
 #include "SkiaColorFilter.h"
+#include "Texture.h"
 #include "Vertex.h"
 
 namespace android {
@@ -40,14 +41,18 @@
  * A layer has dimensions and is backed by an OpenGL texture or FBO.
  */
 struct Layer {
-    Layer(const uint32_t layerWidth, const uint32_t layerHeight):
-            width(layerWidth), height(layerHeight) {
+    Layer(const uint32_t layerWidth, const uint32_t layerHeight) {
         mesh = NULL;
         meshIndices = NULL;
         meshElementCount = 0;
-        isCacheable = true;
-        isTextureLayer = false;
+        cacheable = true;
+        textureLayer = false;
         renderTarget = GL_TEXTURE_2D;
+        texture.width = layerWidth;
+        texture.height = layerHeight;
+        colorFilter = NULL;
+        firstFilter = true;
+        firstWrap = true;
     }
 
     ~Layer() {
@@ -64,12 +69,152 @@
         regionRect.set(bounds.leftTop().x, bounds.leftTop().y,
                bounds.rightBottom().x, bounds.rightBottom().y);
 
-        const float texX = 1.0f / float(width);
-        const float texY = 1.0f / float(height);
+        const float texX = 1.0f / float(texture.width);
+        const float texY = 1.0f / float(texture.height);
         const float height = layer.getHeight();
         texCoords.set(
                regionRect.left * texX, (height - regionRect.top) * texY,
                regionRect.right * texX, (height - regionRect.bottom) * texY);
+
+        regionRect.translate(layer.left, layer.top);
+    }
+
+    inline uint32_t getWidth() {
+        return texture.width;
+    }
+
+    inline uint32_t getHeight() {
+        return texture.height;
+    }
+
+    void setSize(uint32_t width, uint32_t height) {
+        texture.width = width;
+        texture.height = height;
+    }
+
+    inline void setBlend(bool blend) {
+        texture.blend = blend;
+    }
+
+    inline bool isBlend() {
+        return texture.blend;
+    }
+
+    inline void setAlpha(int alpha) {
+        this->alpha = alpha;
+    }
+
+    inline void setAlpha(int alpha, SkXfermode::Mode mode) {
+        this->alpha = alpha;
+        this->mode = mode;
+    }
+
+    inline int getAlpha() {
+        return alpha;
+    }
+
+    inline SkXfermode::Mode getMode() {
+        return mode;
+    }
+
+    inline void setEmpty(bool empty) {
+        this->empty = empty;
+    }
+
+    inline bool isEmpty() {
+        return empty;
+    }
+
+    inline void setFbo(GLuint fbo) {
+        this->fbo = fbo;
+    }
+
+    inline GLuint getFbo() {
+        return fbo;
+    }
+
+    inline GLuint* getTexturePointer() {
+        return &texture.id;
+    }
+
+    inline GLuint getTexture() {
+        return texture.id;
+    }
+
+    inline GLenum getRenderTarget() {
+        return renderTarget;
+    }
+
+    inline void setRenderTarget(GLenum renderTarget) {
+        this->renderTarget = renderTarget;
+    }
+
+    void setWrap(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false) {
+        if (firstWrap || force || wrapS != texture.wrapS || wrapT != texture.wrapT) {
+            firstWrap = true;
+            texture.setWrap(wrapS, wrapT);
+            if (bindTexture) {
+                glBindTexture(renderTarget, texture.id);
+            }
+            glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS);
+            glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT);
+        }
+    }
+
+    void setFilter(GLenum min, GLenum mag, bool bindTexture = false, bool force = false) {
+        if (firstFilter || force || min != texture.minFilter || mag != texture.magFilter) {
+            firstFilter = false;
+            texture.setFilter(min, mag);
+            if (bindTexture) {
+                glBindTexture(renderTarget, texture.id);
+            }
+            glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min);
+            glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag);
+        }
+    }
+
+    inline bool isCacheable() {
+        return cacheable;
+    }
+
+    inline void setCacheable(bool cacheable) {
+        this->cacheable = cacheable;
+    }
+
+    inline bool isTextureLayer() {
+        return textureLayer;
+    }
+
+    inline void setTextureLayer(bool textureLayer) {
+        this->textureLayer = textureLayer;
+    }
+
+    inline SkiaColorFilter* getColorFilter() {
+        return colorFilter;
+    }
+
+    inline void setColorFilter(SkiaColorFilter* filter) {
+        colorFilter = filter;
+    }
+
+    inline void bindTexture() {
+        glBindTexture(renderTarget, texture.id);
+    }
+
+    inline void generateTexture() {
+        glGenTextures(1, &texture.id);
+    }
+
+    inline void deleteTexture() {
+        if (texture.id) glDeleteTextures(1, &texture.id);
+    }
+
+    inline void allocateTexture(GLenum format, GLenum storage) {
+        glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL);
+    }
+
+    inline mat4& getTexTransform() {
+        return texTransform;
     }
 
     /**
@@ -82,43 +227,6 @@
     Rect texCoords;
 
     /**
-     * Name of the FBO used to render the layer. If the name is 0
-     * this layer is not backed by an FBO, but a simple texture.
-     */
-    GLuint fbo;
-
-    /**
-     * Opacity of the layer.
-     */
-    int alpha;
-    /**
-     * Blending mode of the layer.
-     */
-    SkXfermode::Mode mode;
-    /**
-     * Indicates whether this layer should be blended.
-     */
-    bool blend;
-
-    /**
-     * Indicates whether this layer has been used already.
-     */
-    bool empty;
-
-    /**
-     * Name of the texture used to render the layer.
-     */
-    GLuint texture;
-    /**
-     * Width of the layer texture.
-     */
-    uint32_t width;
-    /**
-     * Height of the layer texture.
-     */
-    uint32_t height;
-
-    /**
      * Dirty region indicating what parts of the layer
      * have been drawn.
      */
@@ -130,37 +238,66 @@
     Rect regionRect;
 
     /**
-     * Color filter used to draw this layer. Optional.
-     */
-    SkiaColorFilter* colorFilter;
-
-    /**
      * If the layer can be rendered as a mesh, this is non-null.
      */
     TextureVertex* mesh;
     uint16_t* meshIndices;
     GLsizei meshElementCount;
 
+private:
+    /**
+     * Name of the FBO used to render the layer. If the name is 0
+     * this layer is not backed by an FBO, but a simple texture.
+     */
+    GLuint fbo;
+
+    /**
+     * Indicates whether this layer has been used already.
+     */
+    bool empty;
+
+    /**
+     * The texture backing this layer.
+     */
+    Texture texture;
+
     /**
      * If set to true (by default), the layer can be reused.
      */
-    bool isCacheable;
+    bool cacheable;
 
     /**
      * When set to true, this layer must be treated as a texture
      * layer.
      */
-    bool isTextureLayer;
+    bool textureLayer;
+
+    /**
+     * Indicates the render target.
+     */
+    GLenum renderTarget;
+
+    /**
+     * Color filter used to draw this layer. Optional.
+     */
+    SkiaColorFilter* colorFilter;
+
+    /**
+     * Opacity of the layer.
+     */
+    int alpha;
+    /**
+     * Blending mode of the layer.
+     */
+    SkXfermode::Mode mode;
 
     /**
      * Optional texture coordinates transform.
      */
     mat4 texTransform;
 
-    /**
-     * Indicates the render target.
-     */
-    GLenum renderTarget;
+    bool firstFilter;
+    bool firstWrap;
 }; // struct Layer
 
 }; // namespace uirenderer
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index b2d795f..1a15e87 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -68,8 +68,8 @@
 
 void LayerCache::deleteLayer(Layer* layer) {
     if (layer) {
-        mSize -= layer->width * layer->height * 4;
-        glDeleteTextures(1, &layer->texture);
+        mSize -= layer->getWidth() * layer->getHeight() * 4;
+        layer->deleteTexture();
         delete layer;
     }
 }
@@ -93,29 +93,23 @@
         mCache.removeAt(index);
 
         layer = entry.mLayer;
-        mSize -= layer->width * layer->height * 4;
+        mSize -= layer->getWidth() * layer->getHeight() * 4;
 
-        LAYER_LOGD("Reusing layer %dx%d", layer->width, layer->height);
+        LAYER_LOGD("Reusing layer %dx%d", layer->getWidth(), layer->getHeight());
     } else {
         LAYER_LOGD("Creating new layer %dx%d", entry.mWidth, entry.mHeight);
 
         layer = new Layer(entry.mWidth, entry.mHeight);
-        layer->blend = true;
-        layer->empty = true;
-        layer->fbo = 0;
-        layer->colorFilter = NULL;
+        layer->setBlend(true);
+        layer->setEmpty(true);
+        layer->setFbo(0);
 
-        glGenTextures(1, &layer->texture);
-        glBindTexture(GL_TEXTURE_2D, layer->texture);
-
+        layer->generateTexture();
+        layer->bindTexture();
+        layer->setFilter(GL_NEAREST, GL_NEAREST);
+        layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
         glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
 #if DEBUG_LAYERS
         size_t size = mCache.size();
         for (size_t i = 0; i < size; i++) {
@@ -133,30 +127,30 @@
     //       size already in the cache, and reuse it instead of creating a new one
 
     LayerEntry entry(width, height);
-    if (entry.mWidth <= layer->width && entry.mHeight <= layer->height) {
+    if (entry.mWidth <= layer->getWidth() && entry.mHeight <= layer->getHeight()) {
         return true;
     }
 
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, layer->texture);
+    uint32_t oldWidth = layer->getWidth();
+    uint32_t oldHeight = layer->getHeight();
 
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, entry.mWidth, entry.mHeight, 0,
-            GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    glActiveTexture(GL_TEXTURE0);
+    layer->bindTexture();
+    layer->setSize(entry.mWidth, entry.mHeight);
+    layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
 
     if (glGetError() != GL_NO_ERROR) {
+        layer->setSize(oldWidth, oldHeight);
         return false;
     }
 
-    layer->width = entry.mWidth;
-    layer->height = entry.mHeight;
-
     return true;
 }
 
 bool LayerCache::put(Layer* layer) {
-    if (!layer->isCacheable) return false;
+    if (!layer->isCacheable()) return false;
 
-    const uint32_t size = layer->width * layer->height * 4;
+    const uint32_t size = layer->getWidth() * layer->getHeight() * 4;
     // Don't even try to cache a layer that's bigger than the cache
     if (size < mMaxSize) {
         // TODO: Use an LRU
diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h
index d2d5f39..81b8bf3 100644
--- a/libs/hwui/LayerCache.h
+++ b/libs/hwui/LayerCache.h
@@ -119,7 +119,7 @@
         }
 
         LayerEntry(Layer* layer):
-            mLayer(layer), mWidth(layer->width), mHeight(layer->height) {
+            mLayer(layer), mWidth(layer->getWidth()), mHeight(layer->getHeight()) {
         }
 
         bool operator<(const LayerEntry& rhs) const {
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index dfb5d3b..1fa343b 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -32,9 +32,9 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
-    LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->fbo);
+    LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
 
-    glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, mLayer->getFbo());
 
     const float width = mLayer->layer.getWidth();
     const float height = mLayer->layer.getHeight();
@@ -62,14 +62,14 @@
 
     generateMesh();
 
-    LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mLayer->fbo);
+    LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mLayer->getFbo());
 
     // No need to unbind our FBO, this will be taken care of by the caller
     // who will invoke OpenGLRenderer::resume()
 }
 
 GLint LayerRenderer::getTargetFbo() {
-    return mLayer->fbo;
+    return mLayer->getFbo();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -128,8 +128,8 @@
     }
     mLayer->meshElementCount = elementCount;
 
-    const float texX = 1.0f / float(mLayer->width);
-    const float texY = 1.0f / float(mLayer->height);
+    const float texX = 1.0f / float(mLayer->getWidth());
+    const float texY = 1.0f / float(mLayer->getHeight());
     const float height = mLayer->layer.getHeight();
 
     TextureVertex* mesh = mLayer->mesh;
@@ -166,30 +166,6 @@
 // Layers management
 ///////////////////////////////////////////////////////////////////////////////
 
-Layer* LayerRenderer::createTextureLayer(bool isOpaque) {
-    LAYER_RENDERER_LOGD("Creating new texture layer");
-
-    Layer* layer = new Layer(0, 0);
-    layer->isCacheable = false;
-    layer->isTextureLayer = true;
-    layer->blend = !isOpaque;
-    layer->empty = true;
-    layer->fbo = 0;
-    layer->colorFilter = NULL;
-    layer->fbo = 0;
-    layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f);
-    layer->texCoords.set(0.0f, 1.0f, 0.0f, 1.0f);
-    layer->alpha = 255;
-    layer->mode = SkXfermode::kSrcOver_Mode;
-    layer->colorFilter = NULL;
-    layer->region.clear();
-
-    glActiveTexture(GL_TEXTURE0);
-    glGenTextures(1, &layer->texture);
-
-    return layer;
-}
-
 Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) {
     LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height);
 
@@ -206,40 +182,41 @@
         return NULL;
     }
 
-    layer->fbo = fbo;
+    layer->setFbo(fbo);
     layer->layer.set(0.0f, 0.0f, width, height);
-    layer->texCoords.set(0.0f, height / float(layer->height),
-            width / float(layer->width), 0.0f);
-    layer->alpha = 255;
-    layer->mode = SkXfermode::kSrcOver_Mode;
-    layer->blend = !isOpaque;
-    layer->colorFilter = NULL;
+    layer->texCoords.set(0.0f, height / float(layer->getHeight()),
+            width / float(layer->getWidth()), 0.0f);
+    layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
+    layer->setBlend(!isOpaque);
+    layer->setColorFilter(NULL);
     layer->region.clear();
 
     GLuint previousFbo;
     glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
 
-    glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo);
-    glBindTexture(GL_TEXTURE_2D, layer->texture);
+    glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
+    layer->bindTexture();
 
     // Initialize the texture if needed
-    if (layer->empty) {
-        layer->empty = false;
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->width, layer->height, 0,
-                GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    if (layer->isEmpty()) {
+        layer->setEmpty(false);
+        layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
 
         if (glGetError() != GL_NO_ERROR) {
             LOGD("Could not allocate texture");
+
             glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-            glDeleteTextures(1, &layer->texture);
             Caches::getInstance().fboCache.put(fbo);
+
+            layer->deleteTexture();
             delete layer;
+
             return NULL;
         }
     }
 
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
-            layer->texture, 0);
+            layer->getTexture(), 0);
 
     glDisable(GL_SCISSOR_TEST);
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -253,14 +230,14 @@
 
 bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) {
     if (layer) {
-        LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->fbo, width, height);
+        LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->getFbo(), width, height);
 
         if (Caches::getInstance().layerCache.resize(layer, width, height)) {
             layer->layer.set(0.0f, 0.0f, width, height);
-            layer->texCoords.set(0.0f, height / float(layer->height),
-                    width / float(layer->width), 0.0f);
+            layer->texCoords.set(0.0f, height / float(layer->getHeight()),
+                    width / float(layer->getWidth()), 0.0f);
         } else {
-            if (layer->texture) glDeleteTextures(1, &layer->texture);
+            layer->deleteTexture();
             delete layer;
             return false;
         }
@@ -269,38 +246,56 @@
     return true;
 }
 
+Layer* LayerRenderer::createTextureLayer(bool isOpaque) {
+    LAYER_RENDERER_LOGD("Creating new texture layer");
+
+    Layer* layer = new Layer(0, 0);
+    layer->setCacheable(false);
+    layer->setTextureLayer(true);
+    layer->setBlend(!isOpaque);
+    layer->setEmpty(true);
+    layer->setFbo(0);
+    layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
+    layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f);
+    layer->texCoords.set(0.0f, 1.0f, 0.0f, 1.0f);
+    layer->region.clear();
+    layer->setRenderTarget(GL_NONE); // see ::updateTextureLayer()
+
+    glActiveTexture(GL_TEXTURE0);
+    layer->generateTexture();
+
+    return layer;
+}
+
 void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
         bool isOpaque, GLenum renderTarget, float* transform) {
     if (layer) {
-        layer->blend = !isOpaque;
-        layer->width = width;
-        layer->height = height;
+        layer->setBlend(!isOpaque);
+        layer->setSize(width, height);
         layer->layer.set(0.0f, 0.0f, width, height);
         layer->region.set(width, height);
         layer->regionRect.set(0.0f, 0.0f, width, height);
-        layer->texTransform.load(transform);
-        layer->renderTarget = renderTarget;
+        layer->getTexTransform().load(transform);
 
-        glBindTexture(layer->renderTarget, layer->texture);
-
-        glTexParameteri(layer->renderTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        glTexParameteri(layer->renderTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-        glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        if (renderTarget != layer->getRenderTarget()) {
+            layer->setRenderTarget(renderTarget);
+            layer->bindTexture();
+            layer->setFilter(GL_NEAREST, GL_NEAREST, false, true);
+            layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, false, true);
+        }
     }
 }
 
 void LayerRenderer::destroyLayer(Layer* layer) {
     if (layer) {
-        LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->fbo);
+        LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->getFbo());
 
-        if (layer->fbo) {
-            Caches::getInstance().fboCache.put(layer->fbo);
+        if (layer->getFbo()) {
+            Caches::getInstance().fboCache.put(layer->getFbo());
         }
 
         if (!Caches::getInstance().layerCache.put(layer)) {
-            if (layer->texture) glDeleteTextures(1, &layer->texture);
+            layer->deleteTexture();
             delete layer;
         } else {
             layer->region.clear();
@@ -310,7 +305,7 @@
 
 void LayerRenderer::destroyLayerDeferred(Layer* layer) {
     if (layer) {
-        LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", layer->fbo);
+        LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", layer->getFbo());
 
         Caches::getInstance().deleteLayerDeferred(layer);
     }
@@ -318,7 +313,7 @@
 
 bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
     Caches& caches = Caches::getInstance();
-    if (layer && layer->isTextureLayer && bitmap->width() <= caches.maxTextureSize &&
+    if (layer && layer->isTextureLayer() && bitmap->width() <= caches.maxTextureSize &&
             bitmap->height() <= caches.maxTextureSize) {
 
         GLuint fbo = caches.fboCache.get();
@@ -358,12 +353,11 @@
                 break;
         }
 
-        float alpha = layer->alpha;
-        SkXfermode::Mode mode = layer->mode;
+        float alpha = layer->getAlpha();
+        SkXfermode::Mode mode = layer->getMode();
 
-        layer->mode = SkXfermode::kSrc_Mode;
-        layer->alpha = 255;
-        layer->fbo = fbo;
+        layer->setAlpha(255, SkXfermode::kSrc_Mode);
+        layer->setFbo(fbo);
 
         glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
@@ -374,8 +368,8 @@
         glActiveTexture(GL_TEXTURE0);
         glBindTexture(GL_TEXTURE_2D, texture);
 
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -392,7 +386,7 @@
             LayerRenderer renderer(layer);
             renderer.setViewport(bitmap->width(), bitmap->height());
             renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
-                    bitmap->width(), bitmap->height(), !layer->blend);
+                    bitmap->width(), bitmap->height(), !layer->isBlend());
             if ((error = glGetError()) != GL_NO_ERROR) goto error;
 
             {
@@ -417,9 +411,8 @@
 #endif
 
         glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-        layer->mode = mode;
-        layer->alpha = alpha;
-        layer->fbo = 0;
+        layer->setAlpha(alpha, mode);
+        layer->setFbo(0);
         glDeleteTextures(1, &texture);
         caches.fboCache.put(fbo);
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 1c06a0b..a349121 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -449,12 +449,11 @@
         return false;
     }
 
-    layer->mode = mode;
-    layer->alpha = alpha;
+    layer->setAlpha(alpha, mode);
     layer->layer.set(bounds);
-    layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->height),
-            bounds.getWidth() / float(layer->width), 0.0f);
-    layer->colorFilter = mColorFilter;
+    layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
+            bounds.getWidth() / float(layer->getWidth()), 0.0f);
+    layer->setColorFilter(mColorFilter);
 
     // Save the layer in the snapshot
     snapshot->flags |= Snapshot::kFlagIsLayer;
@@ -464,12 +463,13 @@
         return createFboLayer(layer, bounds, snapshot, previousFbo);
     } else {
         // Copy the framebuffer into the layer
-        glBindTexture(GL_TEXTURE_2D, layer->texture);
+        layer->bindTexture();
         if (!bounds.isEmpty()) {
-            if (layer->empty) {
-                glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left,
-                        snapshot->height - bounds.bottom, layer->width, layer->height, 0);
-                layer->empty = false;
+            if (layer->isEmpty()) {
+                glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+                        bounds.left, snapshot->height - bounds.bottom,
+                        layer->getWidth(), layer->getHeight(), 0);
+                layer->setEmpty(false);
             } else {
                 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left,
                         snapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight());
@@ -485,7 +485,7 @@
 
 bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> snapshot,
         GLuint previousFbo) {
-    layer->fbo = mCaches.fboCache.get();
+    layer->setFbo(mCaches.fboCache.get());
 
 #if RENDER_LAYERS_AS_REGIONS
     snapshot->region = &snapshot->layer->region;
@@ -507,7 +507,7 @@
     clip.translate(-bounds.left, -bounds.top);
 
     snapshot->flags |= Snapshot::kFlagIsFboLayer;
-    snapshot->fbo = layer->fbo;
+    snapshot->fbo = layer->getFbo();
     snapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
     snapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
     snapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
@@ -516,18 +516,17 @@
     snapshot->orthoMatrix.load(mOrthoMatrix);
 
     // Bind texture to FBO
-    glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo);
-    glBindTexture(GL_TEXTURE_2D, layer->texture);
+    glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
+    layer->bindTexture();
 
     // Initialize the texture if needed
-    if (layer->empty) {
-        layer->empty = false;
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->width, layer->height, 0,
-                GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    if (layer->isEmpty()) {
+        layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
+        layer->setEmpty(false);
     }
 
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
-            layer->texture, 0);
+            layer->getTexture(), 0);
 
 #if DEBUG_LAYERS_AS_REGIONS
     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -535,8 +534,8 @@
         LOGE("Framebuffer incomplete (GL error code 0x%x)", status);
 
         glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-        glDeleteTextures(1, &layer->texture);
-        mCaches.fboCache.put(layer->fbo);
+        layer->deleteTexture();
+        mCaches.fboCache.put(layer->getFbo());
 
         delete layer;
 
@@ -578,11 +577,11 @@
     Layer* layer = current->layer;
     const Rect& rect = layer->layer;
 
-    if (!fboLayer && layer->alpha < 255) {
+    if (!fboLayer && layer->getAlpha() < 255) {
         drawColorRect(rect.left, rect.top, rect.right, rect.bottom,
-                layer->alpha << 24, SkXfermode::kDstIn_Mode, true);
+                layer->getAlpha() << 24, SkXfermode::kDstIn_Mode, true);
         // Required below, composeLayerRect() will divide by 255
-        layer->alpha = 255;
+        layer->setAlpha(255);
     }
 
     mCaches.unbindMeshBuffer();
@@ -593,18 +592,16 @@
     // drawing only the dirty region
     if (fboLayer) {
         dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *previous->transform);
-        if (layer->colorFilter) {
-            setupColorFilter(layer->colorFilter);
+        if (layer->getColorFilter()) {
+            setupColorFilter(layer->getColorFilter());
         }
         composeLayerRegion(layer, rect);
-        if (layer->colorFilter) {
+        if (layer->getColorFilter()) {
             resetColorFilter();
         }
-    } else {
-        if (!rect.isEmpty()) {
-            dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
-            composeLayerRect(layer, rect, true);
-        }
+    } else if (!rect.isEmpty()) {
+        dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
+        composeLayerRect(layer, rect, true);
     }
 
     if (fboLayer) {
@@ -622,16 +619,16 @@
     // Failing to add the layer to the cache should happen only if the layer is too large
     if (!mCaches.layerCache.put(layer)) {
         LAYER_LOGD("Deleting layer");
-        glDeleteTextures(1, &layer->texture);
+        layer->deleteTexture();
         delete layer;
     }
 }
 
 void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
-    float alpha = layer->alpha / 255.0f;
+    float alpha = layer->getAlpha() / 255.0f;
 
     setupDraw();
-    if (layer->renderTarget == GL_TEXTURE_2D) {
+    if (layer->getRenderTarget() == GL_TEXTURE_2D) {
         setupDrawWithTexture();
     } else {
         setupDrawWithExternalTexture();
@@ -639,17 +636,28 @@
     setupDrawTextureTransform();
     setupDrawColor(alpha, alpha, alpha, alpha);
     setupDrawColorFilter();
-    setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode);
+    setupDrawBlending(layer->isBlend() || alpha < 1.0f, layer->getMode());
     setupDrawProgram();
-    setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom);
     setupDrawPureColorUniforms();
     setupDrawColorFilterUniforms();
-    if (layer->renderTarget == GL_TEXTURE_2D) {
-        setupDrawTexture(layer->texture);
+    if (layer->getRenderTarget() == GL_TEXTURE_2D) {
+        setupDrawTexture(layer->getTexture());
     } else {
-        setupDrawExternalTexture(layer->texture);
+        setupDrawExternalTexture(layer->getTexture());
     }
-    setupDrawTextureTransformUniforms(layer->texTransform);
+    if (mSnapshot->transform->isPureTranslate() &&
+            layer->getWidth() == (uint32_t) rect.getWidth() &&
+            layer->getHeight() == (uint32_t) rect.getHeight()) {
+        const float x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f);
+        const float y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f);
+
+        layer->setFilter(GL_NEAREST, GL_NEAREST);
+        setupDrawModelView(x, y, x + rect.getWidth(), y + rect.getHeight(), true);
+    } else {
+        layer->setFilter(GL_LINEAR, GL_LINEAR);
+        setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom);
+    }
+    setupDrawTextureTransformUniforms(layer->getTexTransform());
     setupDrawMesh(&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
 
     glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
@@ -658,14 +666,34 @@
 }
 
 void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
-    if (!layer->isTextureLayer) {
+    if (!layer->isTextureLayer()) {
         const Rect& texCoords = layer->texCoords;
         resetDrawTextureTexCoords(texCoords.left, texCoords.top,
                 texCoords.right, texCoords.bottom);
 
-        drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
-                layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
-                &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, swap, swap);
+        float x = rect.left;
+        float y = rect.top;
+        bool simpleTransform = mSnapshot->transform->isPureTranslate() &&
+                layer->getWidth() == (uint32_t) rect.getWidth() &&
+                layer->getHeight() == (uint32_t) rect.getHeight();
+
+        if (simpleTransform) {
+            // When we're swapping, the layer is already in screen coordinates
+            if (!swap) {
+                x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f);
+                y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f);
+            }
+
+            layer->setFilter(GL_NEAREST, GL_NEAREST, true);
+        } else {
+            layer->setFilter(GL_LINEAR, GL_LINEAR, true);
+        }
+
+        drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(),
+                layer->getTexture(), layer->getAlpha() / 255.0f,
+                layer->getMode(), layer->isBlend(),
+                &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
+                GL_TRIANGLE_STRIP, gMeshCount, swap, swap || simpleTransform);
 
         resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
     } else {
@@ -690,9 +718,9 @@
         size_t count;
         const android::Rect* rects = layer->region.getArray(&count);
 
-        const float alpha = layer->alpha / 255.0f;
-        const float texX = 1.0f / float(layer->width);
-        const float texY = 1.0f / float(layer->height);
+        const float alpha = layer->getAlpha() / 255.0f;
+        const float texX = 1.0f / float(layer->getWidth());
+        const float texY = 1.0f / float(layer->getHeight());
         const float height = rect.getHeight();
 
         TextureVertex* mesh = mCaches.getRegionMesh();
@@ -702,13 +730,22 @@
         setupDrawWithTexture();
         setupDrawColor(alpha, alpha, alpha, alpha);
         setupDrawColorFilter();
-        setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false);
+        setupDrawBlending(layer->isBlend() || alpha < 1.0f, layer->getMode(), false);
         setupDrawProgram();
         setupDrawDirtyRegionsDisabled();
         setupDrawPureColorUniforms();
         setupDrawColorFilterUniforms();
-        setupDrawTexture(layer->texture);
-        setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom);
+        setupDrawTexture(layer->getTexture());
+        if (mSnapshot->transform->isPureTranslate()) {
+            const float x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f);
+            const float y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f);
+
+            layer->setFilter(GL_NEAREST, GL_NEAREST);
+            setupDrawModelViewTranslate(x, y, x + rect.getWidth(), y + rect.getHeight(), true);
+        } else {
+            layer->setFilter(GL_LINEAR, GL_LINEAR);
+            setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom);
+        }
         setupDrawMesh(&mesh[0].position[0], &mesh[0].texture[0]);
 
         for (size_t i = 0; i < count; i++) {
@@ -2154,8 +2191,7 @@
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
 
-    layer->alpha = alpha;
-    layer->mode = mode;
+    layer->setAlpha(alpha, mode);
 
 #if RENDER_LAYERS_AS_REGIONS
     if (!layer->region.isEmpty()) {
@@ -2169,13 +2205,23 @@
             setupDrawWithTexture();
             setupDrawColor(a, a, a, a);
             setupDrawColorFilter();
-            setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false);
+            setupDrawBlending(layer->isBlend() || a < 1.0f, layer->getMode(), false);
             setupDrawProgram();
-            setupDrawModelViewTranslate(x, y,
-                    x + layer->layer.getWidth(), y + layer->layer.getHeight());
             setupDrawPureColorUniforms();
             setupDrawColorFilterUniforms();
-            setupDrawTexture(layer->texture);
+            setupDrawTexture(layer->getTexture());
+            if (mSnapshot->transform->isPureTranslate()) {
+                x = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f);
+                y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f);
+
+                layer->setFilter(GL_NEAREST, GL_NEAREST);
+                setupDrawModelViewTranslate(x, y,
+                        x + layer->layer.getWidth(), y + layer->layer.getHeight(), true);
+            } else {
+                layer->setFilter(GL_LINEAR, GL_LINEAR);
+                setupDrawModelViewTranslate(x, y,
+                        x + layer->layer.getWidth(), y + layer->layer.getHeight());
+            }
             setupDrawMesh(&layer->mesh[0].position[0], &layer->mesh[0].texture[0]);
 
             glDrawElements(GL_TRIANGLES, layer->meshElementCount,
diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h
index b048469..f4d9686 100644
--- a/libs/hwui/ShapeCache.h
+++ b/libs/hwui/ShapeCache.h
@@ -537,7 +537,7 @@
     const float pathWidth = fmax(bounds.width(), 1.0f);
     const float pathHeight = fmax(bounds.height(), 1.0f);
 
-    const float offset = fmax(paint->getStrokeWidth(), 1.0f) * 1.5f;
+    const float offset = (int) floorf(fmax(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f);
 
     const uint32_t width = uint32_t(pathWidth + offset * 2.0 + 0.5);
     const uint32_t height = uint32_t(pathHeight + offset * 2.0 + 0.5);
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index 4922bb3..c6ae326 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -29,8 +29,22 @@
     Texture() {
         cleanup = false;
         bitmapSize = 0;
+
         wrapS = GL_CLAMP_TO_EDGE;
         wrapT = GL_CLAMP_TO_EDGE;
+
+        minFilter = GL_NEAREST;
+        magFilter = GL_NEAREST;
+    }
+
+    void setWrap(GLenum wrapS, GLenum wrapT) {
+        this->wrapS = wrapS;
+        this->wrapT = wrapT;
+    }
+
+    void setFilter(GLenum min, GLenum mag) {
+        minFilter = min;
+        magFilter = mag;
     }
 
     /**
@@ -67,6 +81,12 @@
      */
     GLenum wrapS;
     GLenum wrapT;
+
+    /**
+     * Last filters set on this texture. Defaults to GL_NEAREST.
+     */
+    GLenum minFilter;
+    GLenum magFilter;
 }; // struct Texture
 
 class AutoTexture {
diff --git a/libs/rs/driver/rsdBcc.cpp b/libs/rs/driver/rsdBcc.cpp
index 8120864..62eb24e 100644
--- a/libs/rs/driver/rsdBcc.cpp
+++ b/libs/rs/driver/rsdBcc.cpp
@@ -66,65 +66,6 @@
 }
 
 
-// Input: cacheDir
-// Input: resName
-// Input: extName
-//
-// Note: cacheFile = resName + extName
-//
-// Output: Returns cachePath == cacheDir + cacheFile
-static char *genCacheFileName(const char *cacheDir,
-                              const char *resName,
-                              const char *extName) {
-    char cachePath[512];
-    char cacheFile[sizeof(cachePath)];
-    const size_t kBufLen = sizeof(cachePath) - 1;
-
-    cacheFile[0] = '\0';
-    // Note: resName today is usually something like
-    //       "/com.android.fountain:raw/fountain"
-    if (resName[0] != '/') {
-        // Get the absolute path of the raw/***.bc file.
-
-        // Generate the absolute path.  This doesn't do everything it
-        // should, e.g. if resName is "./out/whatever" it doesn't crunch
-        // the leading "./" out because this if-block is not triggered,
-        // but it'll make do.
-        //
-        if (getcwd(cacheFile, kBufLen) == NULL) {
-            LOGE("Can't get CWD while opening raw/***.bc file\n");
-            return NULL;
-        }
-        // Append "/" at the end of cacheFile so far.
-        strncat(cacheFile, "/", kBufLen);
-    }
-
-    // cacheFile = resName + extName
-    //
-    strncat(cacheFile, resName, kBufLen);
-    if (extName != NULL) {
-        // TODO(srhines): strncat() is a bit dangerous
-        strncat(cacheFile, extName, kBufLen);
-    }
-
-    // Turn the path into a flat filename by replacing
-    // any slashes after the first one with '@' characters.
-    char *cp = cacheFile + 1;
-    while (*cp != '\0') {
-        if (*cp == '/') {
-            *cp = '@';
-        }
-        cp++;
-    }
-
-    // Tack on the file name for the actual cache file path.
-    strncpy(cachePath, cacheDir, kBufLen);
-    strncat(cachePath, cacheFile, kBufLen);
-
-    LOGV("Cache file for '%s' '%s' is '%s'\n", resName, extName, cachePath);
-    return strdup(cachePath);
-}
-
 bool rsdScriptInit(const Context *rsc,
                      ScriptC *script,
                      char const *resName,
@@ -164,15 +105,12 @@
         goto error;
     }
 
-#if 1
     if (bccLinkFile(drv->mBccScript, "/system/lib/libclcore.bc", 0) != 0) {
         LOGE("bcc: FAILS to link bitcode");
         goto error;
     }
-#endif
-    cachePath = genCacheFileName(cacheDir, resName, ".oBCC");
 
-    if (bccPrepareExecutable(drv->mBccScript, cachePath, 0) != 0) {
+    if (bccPrepareExecutableEx(drv->mBccScript, cacheDir, resName, 0) != 0) {
         LOGE("bcc: FAILS to prepare executable");
         goto error;
     }
@@ -214,14 +152,13 @@
     const char ** mPragmaKeys;
     const char ** mPragmaValues;
 
-    const static int pragmaMax = 16;
     drv->mPragmaCount = bccGetPragmaCount(drv->mBccScript);
     if (drv->mPragmaCount <= 0) {
         drv->mPragmaKeys = NULL;
         drv->mPragmaValues = NULL;
     } else {
-        drv->mPragmaKeys = (const char **) calloc(drv->mFieldCount, sizeof(const char *));
-        drv->mPragmaValues = (const char **) calloc(drv->mFieldCount, sizeof(const char *));
+        drv->mPragmaKeys = (const char **) calloc(drv->mPragmaCount, sizeof(const char *));
+        drv->mPragmaValues = (const char **) calloc(drv->mPragmaCount, sizeof(const char *));
         bccGetPragmaList(drv->mBccScript, drv->mPragmaCount, drv->mPragmaKeys, drv->mPragmaValues);
     }
 
diff --git a/libs/rs/driver/rsdGL.cpp b/libs/rs/driver/rsdGL.cpp
index 1f7bb0f..04446ad 100644
--- a/libs/rs/driver/rsdGL.cpp
+++ b/libs/rs/driver/rsdGL.cpp
@@ -99,9 +99,8 @@
 
     for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
         EGLint value = -1;
-        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
-        EGLint error = eglGetError();
-        if (returnVal && error == EGL_SUCCESS) {
+        EGLBoolean returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
+        if (returnVal) {
             LOGV(" %s: %d (0x%x)", names[j].name, value, value);
         }
     }
@@ -169,6 +168,24 @@
     configAttribsPtr[1] = EGL_OPENGL_ES2_BIT;
     configAttribsPtr += 2;
 
+    configAttribsPtr[0] = EGL_RED_SIZE;
+    configAttribsPtr[1] = 8;
+    configAttribsPtr += 2;
+
+    configAttribsPtr[0] = EGL_GREEN_SIZE;
+    configAttribsPtr[1] = 8;
+    configAttribsPtr += 2;
+
+    configAttribsPtr[0] = EGL_BLUE_SIZE;
+    configAttribsPtr[1] = 8;
+    configAttribsPtr += 2;
+
+    if (rsc->mUserSurfaceConfig.alphaMin > 0) {
+        configAttribsPtr[0] = EGL_ALPHA_SIZE;
+        configAttribsPtr[1] = rsc->mUserSurfaceConfig.alphaMin;
+        configAttribsPtr += 2;
+    }
+
     if (rsc->mUserSurfaceConfig.depthMin > 0) {
         configAttribsPtr[0] = EGL_DEPTH_SIZE;
         configAttribsPtr[1] = rsc->mUserSurfaceConfig.depthMin;
@@ -191,16 +208,53 @@
     eglInitialize(dc->gl.egl.display, &dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion);
     checkEglError("eglInitialize");
 
-    PixelFormat pf = PIXEL_FORMAT_RGBA_8888;
-    if (rsc->mUserSurfaceConfig.alphaMin == 0) {
-        pf = PIXEL_FORMAT_RGBX_8888;
+    EGLBoolean ret;
+
+    EGLint numConfigs = -1, n = 0;
+    ret = eglChooseConfig(dc->gl.egl.display, configAttribs, 0, 0, &numConfigs);
+    checkEglError("eglGetConfigs", ret);
+
+    if (numConfigs) {
+        EGLConfig* const configs = new EGLConfig[numConfigs];
+
+        ret = eglChooseConfig(dc->gl.egl.display,
+                configAttribs, configs, numConfigs, &n);
+        if (!ret || !n) {
+            checkEglError("eglChooseConfig", ret);
+            LOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc);
+        }
+
+        // The first config is guaranteed to over-satisfy the constraints
+        dc->gl.egl.config = configs[0];
+
+        // go through the list and skip configs that over-satisfy our needs
+        for (int i=0 ; i<n ; i++) {
+            if (rsc->mUserSurfaceConfig.alphaMin <= 0) {
+                EGLint alphaSize;
+                eglGetConfigAttrib(dc->gl.egl.display,
+                        configs[i], EGL_ALPHA_SIZE, &alphaSize);
+                if (alphaSize > 0) {
+                    continue;
+                }
+            }
+
+            if (rsc->mUserSurfaceConfig.depthMin <= 0) {
+                EGLint depthSize;
+                eglGetConfigAttrib(dc->gl.egl.display,
+                        configs[i], EGL_DEPTH_SIZE, &depthSize);
+                if (depthSize > 0) {
+                    continue;
+                }
+            }
+
+            // Found one!
+            dc->gl.egl.config = configs[i];
+            break;
+        }
+
+        delete [] configs;
     }
 
-    status_t err = EGLUtils::selectConfigForPixelFormat(dc->gl.egl.display, configAttribs,
-                                                        pf, &dc->gl.egl.config);
-    if (err) {
-       LOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc);
-    }
     //if (props.mLogVisual) {
     if (0) {
         printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config);
@@ -227,8 +281,8 @@
         return false;
     }
 
-    EGLBoolean ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
-                                    dc->gl.egl.surfaceDefault, dc->gl.egl.context);
+    ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
+                         dc->gl.egl.surfaceDefault, dc->gl.egl.context);
     if (ret == EGL_FALSE) {
         LOGE("eglMakeCurrent returned EGL_FALSE");
         checkEglError("eglMakeCurrent", ret);
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index f9990bb..427bbba 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -43,7 +43,6 @@
 LOCAL_SRC_FILES:= \
 	$(commonSources) \
 	EGLUtils.cpp \
-	EventRecurrence.cpp \
 	FramebufferNativeWindow.cpp \
 	GraphicBuffer.cpp \
 	GraphicBufferAllocator.cpp \
diff --git a/libs/ui/EGLUtils.cpp b/libs/ui/EGLUtils.cpp
index f24a71d..020646b 100644
--- a/libs/ui/EGLUtils.cpp
+++ b/libs/ui/EGLUtils.cpp
@@ -24,6 +24,8 @@
 
 #include <EGL/egl.h>
 
+#include <system/graphics.h>
+
 #include <private/ui/android_natives_priv.h>
 
 // ----------------------------------------------------------------------------
@@ -67,31 +69,49 @@
         return BAD_VALUE;
     
     // Get all the "potential match" configs...
-    if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE)
+    if (eglChooseConfig(dpy, attrs, 0, 0, &numConfigs) == EGL_FALSE)
         return BAD_VALUE;
 
-    EGLConfig* const configs = (EGLConfig*)malloc(sizeof(EGLConfig)*numConfigs);
-    if (eglChooseConfig(dpy, attrs, configs, numConfigs, &n) == EGL_FALSE) {
-        free(configs);
-        return BAD_VALUE;
-    }
-    
-    int i;
-    EGLConfig config = NULL;
-    for (i=0 ; i<n ; i++) {
-        EGLint nativeVisualId = 0;
-        eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
-        if (nativeVisualId>0 && format == nativeVisualId) {
+    if (numConfigs) {
+        EGLConfig* const configs = new EGLConfig[numConfigs];
+        if (eglChooseConfig(dpy, attrs, configs, numConfigs, &n) == EGL_FALSE) {
+            delete [] configs;
+            return BAD_VALUE;
+        }
+
+        bool hasAlpha = false;
+        switch (format) {
+            case HAL_PIXEL_FORMAT_RGBA_8888:
+            case HAL_PIXEL_FORMAT_BGRA_8888:
+            case HAL_PIXEL_FORMAT_RGBA_5551:
+            case HAL_PIXEL_FORMAT_RGBA_4444:
+                hasAlpha = true;
+                break;
+        }
+
+        // The first config is guaranteed to over-satisfy the constraints
+        EGLConfig config = configs[0];
+
+        // go through the list and skip configs that over-satisfy our needs
+        int i;
+        for (i=0 ; i<n ; i++) {
+            if (!hasAlpha) {
+                EGLint alphaSize;
+                eglGetConfigAttrib(dpy, configs[i], EGL_ALPHA_SIZE, &alphaSize);
+                if (alphaSize > 0) {
+                    continue;
+                }
+            }
             config = configs[i];
             break;
         }
-    }
 
-    free(configs);
-    
-    if (i<n) {
-        *outConfig = config;
-        return NO_ERROR;
+        delete [] configs;
+
+        if (i<n) {
+            *outConfig = config;
+            return NO_ERROR;
+        }
     }
 
     return NAME_NOT_FOUND;
diff --git a/libs/ui/EventRecurrence.cpp b/libs/ui/EventRecurrence.cpp
deleted file mode 100644
index b436b50..0000000
--- a/libs/ui/EventRecurrence.cpp
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- *  Copyright 2006 The Android Open Source Project
- */
-
-#include <pim/EventRecurrence.h>
-#include <utils/String8.h>
-#include <stdio.h>
-#include <limits.h>
-
-namespace android {
-
-#define FAIL_HERE() do { \
-            printf("Parsing failed at line %d\n", __LINE__); \
-            return UNKNOWN_ERROR; \
-        } while(0)
-
-EventRecurrence::EventRecurrence()
-    :freq((freq_t)0),
-     until(),
-     count(0),
-     interval(0),
-     bysecond(0),
-     bysecondCount(0),
-     byminute(0),
-     byminuteCount(0),
-     byhour(0),
-     byhourCount(0),
-     byday(0),
-     bydayNum(0),
-     bydayCount(0),
-     bymonthday(0),
-     bymonthdayCount(0),
-     byyearday(0),
-     byyeardayCount(0),
-     byweekno(0),
-     byweeknoCount(0),
-     bymonth(0),
-     bymonthCount(0),
-     bysetpos(0),
-     bysetposCount(0),
-     wkst(0)
-{
-}
-
-EventRecurrence::~EventRecurrence()
-{
-    delete[] bysecond;
-    delete[] byminute;
-    delete[] byhour;
-    delete[] byday;
-    delete[] bydayNum;
-    delete[] byyearday;
-    delete[] bymonthday;
-    delete[] byweekno;
-    delete[] bymonth;
-    delete[] bysetpos;
-}
-
-enum LHS {
-    NONE_LHS = 0,
-    FREQ,
-    UNTIL,
-    COUNT,
-    INTERVAL,
-    BYSECOND,
-    BYMINUTE,
-    BYHOUR,
-    BYDAY,
-    BYMONTHDAY,
-    BYYEARDAY,
-    BYWEEKNO,
-    BYMONTH,
-    BYSETPOS,
-    WKST
-};
-
-struct LHSProc
-{
-    const char16_t* text;
-    size_t textSize;
-    uint32_t value;
-};
-
-const char16_t FREQ_text[] = { 'F', 'R', 'E', 'Q' };
-const char16_t UNTIL_text[] = { 'U', 'N', 'T', 'I', 'L' };
-const char16_t COUNT_text[] = { 'C', 'O', 'U', 'N', 'T' };
-const char16_t INTERVAL_text[] = { 'I', 'N', 'T', 'E', 'R', 'V', 'A', 'L'};
-const char16_t BYSECOND_text[] = { 'B', 'Y', 'S', 'E', 'C', 'O', 'N', 'D' };
-const char16_t BYMINUTE_text[] = { 'B', 'Y', 'M', 'I', 'N', 'U', 'T', 'E' };
-const char16_t BYHOUR_text[] = { 'B', 'Y', 'H', 'O', 'U', 'R' };
-const char16_t BYDAY_text[] = { 'B', 'Y', 'D', 'A', 'Y' };
-const char16_t BYMONTHDAY_text[] = { 'B','Y','M','O','N','T','H','D','A','Y' };
-const char16_t BYYEARDAY_text[] = { 'B','Y','Y','E','A','R','D','A','Y' };
-const char16_t BYWEEKNO_text[] = { 'B', 'Y', 'W', 'E', 'E', 'K', 'N', 'O' };
-const char16_t BYMONTH_text[] = { 'B', 'Y', 'M', 'O', 'N', 'T', 'H' };
-const char16_t BYSETPOS_text[] = { 'B', 'Y', 'S', 'E', 'T', 'P', 'O', 'S' };
-const char16_t WKST_text[] = { 'W', 'K', 'S', 'T' };
-
-#define SIZ(x) (sizeof(x)/sizeof(x[0]))
-
-const LHSProc LHSPROC[] = {
-    { FREQ_text, SIZ(FREQ_text), FREQ },
-    { UNTIL_text, SIZ(UNTIL_text), UNTIL },
-    { COUNT_text, SIZ(COUNT_text), COUNT },
-    { INTERVAL_text, SIZ(INTERVAL_text), INTERVAL },
-    { BYSECOND_text, SIZ(BYSECOND_text), BYSECOND },
-    { BYMINUTE_text, SIZ(BYMINUTE_text), BYMINUTE },
-    { BYHOUR_text, SIZ(BYHOUR_text), BYHOUR },
-    { BYDAY_text, SIZ(BYDAY_text), BYDAY },
-    { BYMONTHDAY_text, SIZ(BYMONTHDAY_text), BYMONTHDAY },
-    { BYYEARDAY_text, SIZ(BYYEARDAY_text), BYYEARDAY },
-    { BYWEEKNO_text, SIZ(BYWEEKNO_text), BYWEEKNO },
-    { BYMONTH_text, SIZ(BYMONTH_text), BYMONTH },
-    { BYSETPOS_text, SIZ(BYSETPOS_text), BYSETPOS },
-    { WKST_text, SIZ(WKST_text), WKST },
-    { NULL, 0, NONE_LHS },
-};
-
-const char16_t SECONDLY_text[] = { 'S','E','C','O','N','D','L','Y' };
-const char16_t MINUTELY_text[] = { 'M','I','N','U','T','E','L','Y' };
-const char16_t HOURLY_text[] = { 'H','O','U','R','L','Y' };
-const char16_t DAILY_text[] = { 'D','A','I','L','Y' };
-const char16_t WEEKLY_text[] = { 'W','E','E','K','L','Y' };
-const char16_t MONTHLY_text[] = { 'M','O','N','T','H','L','Y' };
-const char16_t YEARLY_text[] = { 'Y','E','A','R','L','Y' };
-
-typedef LHSProc FreqProc;
-
-const FreqProc FREQPROC[] = {
-    { SECONDLY_text, SIZ(SECONDLY_text), EventRecurrence::SECONDLY },
-    { MINUTELY_text, SIZ(MINUTELY_text), EventRecurrence::MINUTELY },
-    { HOURLY_text, SIZ(HOURLY_text), EventRecurrence::HOURLY },
-    { DAILY_text, SIZ(DAILY_text), EventRecurrence::DAILY },
-    { WEEKLY_text, SIZ(WEEKLY_text), EventRecurrence::WEEKLY },
-    { MONTHLY_text, SIZ(MONTHLY_text), EventRecurrence::MONTHLY },
-    { YEARLY_text, SIZ(YEARLY_text), EventRecurrence::YEARLY },
-    { NULL, 0, NONE_LHS },
-};
-
-const char16_t SU_text[] = { 'S','U' };
-const char16_t MO_text[] = { 'M','O' };
-const char16_t TU_text[] = { 'T','U' };
-const char16_t WE_text[] = { 'W','E' };
-const char16_t TH_text[] = { 'T','H' };
-const char16_t FR_text[] = { 'F','R' };
-const char16_t SA_text[] = { 'S','A' };
-
-const FreqProc WEEKDAYPROC[] = {
-    { SU_text, SIZ(SU_text), EventRecurrence::SU },
-    { MO_text, SIZ(MO_text), EventRecurrence::MO },
-    { TU_text, SIZ(TU_text), EventRecurrence::TU },
-    { WE_text, SIZ(WE_text), EventRecurrence::WE },
-    { TH_text, SIZ(TH_text), EventRecurrence::TH },
-    { FR_text, SIZ(FR_text), EventRecurrence::FR },
-    { SA_text, SIZ(SA_text), EventRecurrence::SA },
-    { NULL, 0, NONE_LHS },
-};
-
-// returns the index into LHSPROC for the match or -1 if not found
-inline static int
-match_proc(const LHSProc* p, const char16_t* str, size_t len)
-{
-    int i = 0;
-    while (p->text != NULL) {
-        if (p->textSize == len) {
-            if (0 == memcmp(p->text, str, len*sizeof(char16_t))) {
-                return i;
-            }
-        }
-        p++;
-        i++;
-    }
-    return -1;
-}
-
-// rangeMin and rangeMax are inclusive
-static status_t
-parse_int(const char16_t* str, size_t len, int* out,
-            int rangeMin, int rangeMax, bool zeroOK)
-{
-    char16_t c;
-    size_t i=0;
-
-    if (len == 0) {
-        FAIL_HERE();
-    }
-    bool negative = false;
-    c = str[0];
-    if (c == '-' ) {
-        negative = true;
-        i++;
-    }
-    else if (c == '+') {
-        i++;
-    }
-    int n = 0;
-    for (; i<len; i++) {
-        c = str[i];
-        if (c < '0' || c > '9') {
-            FAIL_HERE();
-        }
-        int prev = n;
-        n *= 10;
-        // the spec doesn't address how big these numbers can be,
-        // so we're not going to worry about not being able to represent
-        // INT_MIN, and if we're going to wrap, we'll just clamp to
-        // INT_MAX instead
-        if (n < prev) {
-            n = INT_MAX;
-        } else {
-            n += c - '0';
-        }
-    }
-    if (negative) {
-        n = -n;
-    }
-    if (n < rangeMin || n > rangeMax) {
-        FAIL_HERE();
-    }
-    if (!zeroOK && n == 0) {
-        FAIL_HERE();
-    }
-    *out = n;
-    return NO_ERROR;
-}
-
-static status_t
-parse_int_list(const char16_t* str, size_t len, int* countOut, int** listOut,
-          int rangeMin, int rangeMax, bool zeroOK,
-          status_t (*func)(const char16_t*,size_t,int*,int,int,bool)=parse_int)
-{
-    status_t err;
-
-    if (len == 0) {
-        *countOut = 0;
-        *listOut = NULL;
-        return NO_ERROR;
-    }
-
-    // make one pass through looking for commas so we know how big to make our
-    // out array.
-    int count = 1;
-    for (size_t i=0; i<len; i++) {
-        if (str[i] == ',') {
-            count++;
-        }
-    }
-
-    int* list = new int[count];
-    const char16_t* p = str;
-    int commaIndex = 0;
-    size_t i;
-
-    for (i=0; i<len; i++) {
-        if (str[i] == ',') {
-            err = func(p, (str+i-p), list+commaIndex, rangeMin,
-                    rangeMax, zeroOK);
-            if (err != NO_ERROR) {
-                goto bail;
-            }
-            commaIndex++;
-            p = str+i+1;
-        }
-    }
-
-    err = func(p, (str+i-p), list+commaIndex, rangeMin, rangeMax, zeroOK);
-    if (err != NO_ERROR) {
-        goto bail;
-    }
-    commaIndex++;
-
-    *countOut = count;
-    *listOut = list;
-
-    return NO_ERROR;
-
-bail:
-    delete[] list;
-    FAIL_HERE();
-}
-
-// the numbers here are small, so we pack them both into one value, and then
-// split it out later.  it lets us reuse all the comma separated list code.
-static status_t
-parse_byday(const char16_t* s, size_t len, int* out,
-            int rangeMin, int rangeMax, bool zeroOK)
-{
-    status_t err;
-    int n = 0;
-    const char16_t* p = s;
-    size_t plen = len;
-
-    if (len > 0) {
-        char16_t c = s[0];
-        if (c == '-' || c == '+' || (c >= '0' && c <= '9')) {
-            if (len > 1) {
-                size_t nlen = 0;
-                c = s[nlen];
-                while (nlen < len
-                        && (c == '-' || c == '+' || (c >= '0' && c <= '9'))) {
-                    c = s[nlen];
-                    nlen++;
-                }
-                if (nlen > 0) {
-                    nlen--;
-                    err = parse_int(s, nlen, &n, rangeMin, rangeMax, zeroOK);
-                    if (err != NO_ERROR) {
-                        FAIL_HERE();
-                    }
-                    p += nlen;
-                    plen -= nlen;
-                }
-            }
-        }
-
-        int index = match_proc(WEEKDAYPROC, p, plen);
-        if (index >= 0) {
-            *out = (0xffff0000 & WEEKDAYPROC[index].value)
-                    | (0x0000ffff & n);
-            return NO_ERROR;
-        }
-    }
-    return UNKNOWN_ERROR;
-}
-
-static void
-postprocess_byday(int count, int* byday, int** bydayNum)
-{
-    int* bdn = new int[count];
-    *bydayNum = bdn;
-    for (int i=0; i<count; i++) {
-        uint32_t v = byday[i];
-        int16_t num = v & 0x0000ffff;
-        byday[i] = v & 0xffff0000;  
-        // will sign extend:
-        bdn[i] = num;
-    }
-}
-
-#define PARSE_INT_LIST_CHECKED(name, rangeMin, rangeMax, zeroOK) \
-    if (name##Count != 0 || NO_ERROR != parse_int_list(s, slen, \
-                         &name##Count, &name, rangeMin, rangeMax, zeroOK)) { \
-        FAIL_HERE(); \
-    }
-status_t
-EventRecurrence::parse(const String16& str)
-{
-    char16_t const* work = str.string();
-    size_t len = str.size();
-
-    int lhsIndex = NONE_LHS;
-    int index;
-    
-    size_t start = 0;
-    for (size_t i=0; i<len; i++) {
-        char16_t c = work[i];
-        if (c != ';' && i == len-1) {
-            c = ';';
-            i++;
-        }
-        if (c == ';' || c == '=') {
-            if (i != start) {
-                const char16_t* s = work+start;
-                const size_t slen = i-start;
-
-                String8 thestring(String16(s, slen));
-
-                switch (c)
-                {
-                    case '=':
-                        if (lhsIndex == NONE_LHS) {
-                            lhsIndex = match_proc(LHSPROC, s, slen);
-                            if (lhsIndex >= 0) {
-                                break;
-                            }
-                        }
-                        FAIL_HERE();
-                    case ';':
-                    {
-                        switch (LHSPROC[lhsIndex].value)
-                        {
-                            case FREQ:
-                                if (this->freq != 0) {
-                                    FAIL_HERE();
-                                }
-                                index = match_proc(FREQPROC, s, slen);
-                                if (index >= 0) {
-                                    this->freq = (freq_t)FREQPROC[index].value;
-                                }
-                                break;
-                            case UNTIL:
-                                // XXX should check that this is a valid time
-                                until.setTo(String16(s, slen));
-                                break;
-                            case COUNT:
-                                if (count != 0
-                                     || NO_ERROR != parse_int(s, slen,
-                                             &count, INT_MIN, INT_MAX, true)) {
-                                    FAIL_HERE();
-                                }
-                                break;
-                            case INTERVAL:
-                                if (interval != 0
-                                     || NO_ERROR != parse_int(s, slen,
-                                         &interval, INT_MIN, INT_MAX, false)) {
-                                    FAIL_HERE();
-                                }
-                                break;
-                            case BYSECOND:
-                                PARSE_INT_LIST_CHECKED(bysecond, 0, 59, true)
-                                break;
-                            case BYMINUTE:
-                                PARSE_INT_LIST_CHECKED(byminute, 0, 59, true)
-                                break;
-                            case BYHOUR:
-                                PARSE_INT_LIST_CHECKED(byhour, 0, 23, true)
-                                break;
-                            case BYDAY:
-                                if (bydayCount != 0 || NO_ERROR != 
-                                        parse_int_list(s, slen, &bydayCount,
-                                              &byday, -53, 53, false,
-                                              parse_byday)) {
-                                    FAIL_HERE();
-                                }
-                                postprocess_byday(bydayCount, byday, &bydayNum);
-                                break;
-                            case BYMONTHDAY:
-                                PARSE_INT_LIST_CHECKED(bymonthday, -31, 31,
-                                                        false)
-                                break;
-                            case BYYEARDAY:
-                                PARSE_INT_LIST_CHECKED(byyearday, -366, 366,
-                                                        false)
-                                break;
-                            case BYWEEKNO:
-                                PARSE_INT_LIST_CHECKED(byweekno, -53, 53,
-                                                        false)
-                                break;
-                            case BYMONTH:
-                                PARSE_INT_LIST_CHECKED(bymonth, 1, 12, false)
-                                break;
-                            case BYSETPOS:
-                                PARSE_INT_LIST_CHECKED(bysetpos,
-                                                        INT_MIN, INT_MAX, true)
-                                break;
-                            case WKST:
-                                if (this->wkst != 0) {
-                                    FAIL_HERE();
-                                }
-                                index = match_proc(WEEKDAYPROC, s, slen);
-                                if (index >= 0) {
-                                    this->wkst = (int)WEEKDAYPROC[index].value;
-                                }
-                                break;
-                            default:
-                                FAIL_HERE();
-                        }
-                        lhsIndex = NONE_LHS;
-                        break;
-                    }
-                }
-
-                start = i+1;
-            }
-        }
-    }
-
-    // enforce that there was a FREQ
-    if (freq == 0) {
-        FAIL_HERE();
-    }
-
-    // default wkst to MO if it wasn't specified
-    if (wkst == 0) {
-        wkst = MO;
-    }
-
-    return NO_ERROR;
-}
-
-
-}; // namespace android
-
-
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index ffdfe66..c46d6f4 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -443,7 +443,8 @@
 
     if (! mPinned || ! mMotionEventSampleDataTail) {
         LOGE("channel '%s' publisher ~ Cannot append motion sample because there is no current "
-                "AMOTION_EVENT_ACTION_MOVE event.", mChannel->getName().string());
+                "AMOTION_EVENT_ACTION_MOVE or AMOTION_EVENT_ACTION_HOVER_MOVE event.",
+                mChannel->getName().string());
         return INVALID_OPERATION;
     }
 
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 093189c..774e8c9 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -27,6 +27,7 @@
 	Debug.cpp \
 	FileMap.cpp \
 	Flattenable.cpp \
+	LinearTransform.cpp \
 	ObbFile.cpp \
 	Pool.cpp \
 	PropertyMap.cpp \
diff --git a/libs/utils/LinearTransform.cpp b/libs/utils/LinearTransform.cpp
new file mode 100644
index 0000000..d752415
--- /dev/null
+++ b/libs/utils/LinearTransform.cpp
@@ -0,0 +1,262 @@
+/*
+ * 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.
+ */
+
+#define __STDC_LIMIT_MACROS
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <utils/LinearTransform.h>
+
+namespace android {
+
+template<class T> static inline T ABS(T x) { return (x < 0) ? -x : x; }
+
+// Static math methods involving linear transformations
+static bool scale_u64_to_u64(
+        uint64_t val,
+        uint32_t N,
+        uint32_t D,
+        uint64_t* res,
+        bool round_up_not_down) {
+    uint64_t tmp1, tmp2;
+    uint32_t r;
+
+    assert(res);
+    assert(D);
+
+    // Let U32(X) denote a uint32_t containing the upper 32 bits of a 64 bit
+    // integer X.
+    // Let L32(X) denote a uint32_t containing the lower 32 bits of a 64 bit
+    // integer X.
+    // Let X[A, B] with A <= B denote bits A through B of the integer X.
+    // Let (A | B) denote the concatination of two 32 bit ints, A and B.
+    // IOW X = (A | B) => U32(X) == A && L32(X) == B
+    //
+    // compute M = val * N (a 96 bit int)
+    // ---------------------------------
+    // tmp2 = U32(val) * N (a 64 bit int)
+    // tmp1 = L32(val) * N (a 64 bit int)
+    // which means
+    // M = val * N = (tmp2 << 32) + tmp1
+    tmp2 = (val >> 32) * N;
+    tmp1 = (val & UINT32_MAX) * N;
+
+    // compute M[32, 95]
+    // tmp2 = tmp2 + U32(tmp1)
+    //      = (U32(val) * N) + U32(L32(val) * N)
+    //      = M[32, 95]
+    tmp2 += tmp1 >> 32;
+
+    // if M[64, 95] >= D, then M/D has bits > 63 set and we have
+    // an overflow.
+    if ((tmp2 >> 32) >= D) {
+        *res = UINT64_MAX;
+        return false;
+    }
+
+    // Divide.  Going in we know
+    // tmp2 = M[32, 95]
+    // U32(tmp2) < D
+    r = tmp2 % D;
+    tmp2 /= D;
+
+    // At this point
+    // tmp1      = L32(val) * N
+    // tmp2      = M[32, 95] / D
+    //           = (M / D)[32, 95]
+    // r         = M[32, 95] % D
+    // U32(tmp2) = 0
+    //
+    // compute tmp1 = (r | M[0, 31])
+    tmp1 = (tmp1 & UINT32_MAX) | ((uint64_t)r << 32);
+
+    // Divide again.  Keep the remainder around in order to round properly.
+    r = tmp1 % D;
+    tmp1 /= D;
+
+    // At this point
+    // tmp2      = (M / D)[32, 95]
+    // tmp1      = (M / D)[ 0, 31]
+    // r         =  M % D
+    // U32(tmp1) = 0
+    // U32(tmp2) = 0
+
+    // Pack the result and deal with the round-up case (As well as the
+    // remote possiblility over overflow in such a case).
+    *res = (tmp2 << 32) | tmp1;
+    if (r && round_up_not_down) {
+        ++(*res);
+        if (!(*res)) {
+            *res = UINT64_MAX;
+            return false;
+        }
+    }
+
+    return true;
+}
+
+static bool linear_transform_s64_to_s64(
+        int64_t  val,
+        int64_t  basis1,
+        int32_t  N,
+        uint32_t D,
+        int64_t  basis2,
+        int64_t* out) {
+    uint64_t scaled, res;
+    uint64_t abs_val;
+    bool is_neg;
+
+    if (!out)
+        return false;
+
+    // Compute abs(val - basis_64). Keep track of whether or not this delta
+    // will be negative after the scale opertaion.
+    if (val < basis1) {
+        is_neg = true;
+        abs_val = basis1 - val;
+    } else {
+        is_neg = false;
+        abs_val = val - basis1;
+    }
+
+    if (N < 0)
+        is_neg = !is_neg;
+
+    if (!scale_u64_to_u64(abs_val,
+                          ABS(N),
+                          D,
+                          &scaled,
+                          is_neg))
+        return false; // overflow/undeflow
+
+    // if scaled is >= 0x8000<etc>, then we are going to overflow or
+    // underflow unless ABS(basis2) is large enough to pull us back into the
+    // non-overflow/underflow region.
+    if (scaled & INT64_MIN) {
+        if (is_neg && (basis2 < 0))
+            return false; // certain underflow
+
+        if (!is_neg && (basis2 >= 0))
+            return false; // certain overflow
+
+        if (ABS(basis2) <= static_cast<int64_t>(scaled & INT64_MAX))
+            return false; // not enough
+
+        // Looks like we are OK
+        *out = (is_neg ? (-scaled) : scaled) + basis2;
+    } else {
+        // Scaled fits within signed bounds, so we just need to check for
+        // over/underflow for two signed integers.  Basically, if both scaled
+        // and basis2 have the same sign bit, and the result has a different
+        // sign bit, then we have under/overflow.  An easy way to compute this
+        // is
+        // (scaled_signbit XNOR basis_signbit) &&
+        // (scaled_signbit XOR res_signbit)
+        // ==
+        // (scaled_signbit XOR basis_signbit XOR 1) &&
+        // (scaled_signbit XOR res_signbit)
+
+        if (is_neg)
+            scaled = -scaled;
+        res = scaled + basis2;
+
+        if ((scaled ^ basis2 ^ INT64_MIN) & (scaled ^ res) & INT64_MIN)
+            return false;
+
+        *out = res;
+    }
+
+    return true;
+}
+
+bool LinearTransform::doForwardTransform(int64_t a_in, int64_t* b_out) const {
+    if (0 == a_to_b_denom)
+        return false;
+
+    return linear_transform_s64_to_s64(a_in,
+                                       a_zero,
+                                       a_to_b_numer,
+                                       a_to_b_denom,
+                                       b_zero,
+                                       b_out);
+}
+
+bool LinearTransform::doReverseTransform(int64_t b_in, int64_t* a_out) const {
+    if (0 == a_to_b_numer)
+        return false;
+
+    return linear_transform_s64_to_s64(b_in,
+                                       b_zero,
+                                       a_to_b_denom,
+                                       a_to_b_numer,
+                                       a_zero,
+                                       a_out);
+}
+
+template <class T> void LinearTransform::reduce(T* N, T* D) {
+    T a, b;
+    if (!N || !D || !(*D)) {
+        assert(false);
+        return;
+    }
+
+    a = *N;
+    b = *D;
+
+    if (a == 0) {
+        *D = 1;
+        return;
+    }
+
+    // This implements Euclid's method to find GCD.
+    if (a < b) {
+        T tmp = a;
+        a = b;
+        b = tmp;
+    }
+
+    while (1) {
+        // a is now the greater of the two.
+        const T remainder = a % b;
+        if (remainder == 0) {
+            *N /= b;
+            *D /= b;
+            return;
+        }
+        // by swapping remainder and b, we are guaranteeing that a is
+        // still the greater of the two upon entrance to the loop.
+        a = b;
+        b = remainder;
+    }
+};
+
+template void LinearTransform::reduce<uint64_t>(uint64_t* N, uint64_t* D);
+template void LinearTransform::reduce<uint32_t>(uint32_t* N, uint32_t* D);
+
+void LinearTransform::reduce(int32_t* N, uint32_t* D) {
+    if (N && D && *D) {
+        if (*N < 0) {
+            *N = -(*N);
+            reduce(reinterpret_cast<uint32_t*>(N), D);
+            *N = -(*N);
+        } else {
+            reduce(reinterpret_cast<uint32_t*>(N), D);
+        }
+    }
+}
+
+}  // namespace android
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 15bb1d2..50312e7 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -316,6 +316,10 @@
 #if defined(HAVE_PTHREADS)
     pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup);
     if (gDoSchedulingGroup) {
+        // set_sched_policy does not support tid == 0
+        if (tid == 0) {
+            tid = androidGetTid();
+        }
         if (set_sched_policy(tid, (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
                                           SP_BACKGROUND : SP_FOREGROUND)) {
             return PERMISSION_DENIED;
@@ -842,6 +846,25 @@
     return mStatus;
 }
 
+status_t Thread::join()
+{
+    Mutex::Autolock _l(mLock);
+    if (mThread == getThreadId()) {
+        LOGW(
+        "Thread (this=%p): don't call join() from this "
+        "Thread object's thread. It's a guaranteed deadlock!",
+        this);
+
+        return WOULD_BLOCK;
+    }
+
+    while (mRunning == true) {
+        mThreadExitedCondition.wait(mLock);
+    }
+
+    return mStatus;
+}
+
 bool Thread::exitPending() const
 {
     Mutex::Autolock _l(mLock);
diff --git a/location/java/android/location/Country.java b/location/java/android/location/Country.java
index 3c05403..939bd4a 100755
--- a/location/java/android/location/Country.java
+++ b/location/java/android/location/Country.java
@@ -19,6 +19,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Locale;
+
 /**
  * This class wraps the country information.
  *
@@ -74,7 +76,7 @@
                 || source > COUNTRY_SOURCE_LOCALE) {
             throw new IllegalArgumentException();
         }
-        mCountryIso = countryIso.toLowerCase();
+        mCountryIso = countryIso.toUpperCase(Locale.US);
         mSource = source;
     }
 
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index ffc3346..29dec63 100755
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -205,7 +205,7 @@
             mNiNotification.defaults &= ~Notification.DEFAULT_SOUND;
         }        
 
-        mNiNotification.flags = Notification.FLAG_ONGOING_EVENT;
+        mNiNotification.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_AUTO_CANCEL;
         mNiNotification.tickerText = getNotifTicker(notif, mContext);
 
         // if not to popup dialog immediately, pending intent will open the dialog
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 7634c6c..816d215 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -104,10 +104,9 @@
     public static final int FILE_TYPE_MS_POWERPOINT = 106;
     public static final int FILE_TYPE_ZIP           = 107;
     
-    static class MediaFileType {
-    
-        int fileType;
-        String mimeType;
+    public static class MediaFileType {
+        public final int fileType;
+        public final String mimeType;
         
         MediaFileType(int fileType, String mimeType) {
             this.fileType = fileType;
@@ -214,7 +213,7 @@
         addFileType("PNG", FILE_TYPE_PNG, "image/png", MtpConstants.FORMAT_PNG);
         addFileType("BMP", FILE_TYPE_BMP, "image/x-ms-bmp", MtpConstants.FORMAT_BMP);
         addFileType("WBMP", FILE_TYPE_WBMP, "image/vnd.wap.wbmp");
-        addFileType("WEBP", FILE_TYPE_WBMP, "image/webp");
+        addFileType("WEBP", FILE_TYPE_WEBP, "image/webp");
  
         addFileType("M3U", FILE_TYPE_M3U, "audio/x-mpegurl", MtpConstants.FORMAT_M3U_PLAYLIST);
         addFileType("M3U", FILE_TYPE_M3U, "application/x-mpegurl", MtpConstants.FORMAT_M3U_PLAYLIST);
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 7ebedaf..10694c3 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -453,5 +453,10 @@
      * @hide
      */
     public static final int METADATA_KEY_TIMED_TEXT_LANGUAGES      = 21;
+    /**
+     * If this key exists the media is drm-protected.
+     * @hide
+     */
+    public static final int METADATA_KEY_IS_DRM          = 22;
     // Add more here...
 }
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 33312d1..482b437 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -611,15 +611,11 @@
      * needed.  Not calling this method when playing back a video will
      * result in only the audio track being played.
      *
-     * @param sh the SurfaceHolder to use for video display
-     */
-    /*
-     * This portion of comment has a non-Javadoc prefix so as not to refer to a
-     * hidden method. When unhidden, merge it with the previous javadoc comment.
-     *
      * Either a surface or surface texture must be set if a display or video sink
      * is needed.  Not calling this method or {@link #setTexture(SurfaceTexture)}
      * when playing back a video will result in only the audio track being played.
+     *
+     * @param sh the SurfaceHolder to use for video display
      */
     public void setDisplay(SurfaceHolder sh) {
         mSurfaceHolder = sh;
@@ -648,7 +644,8 @@
      * SurfaceTexture set as the video sink have an unspecified zero point,
      * and cannot be directly compared between different media sources or different
      * instances of the same media source, or across multiple runs of the same
-     * program.
+     * program.  The timestamp is normally monotonically increasing and unaffected
+     * by time-of-day adjustments, but is reset when the position is set.
      */
     public void setTexture(SurfaceTexture st) {
         ParcelSurfaceTexture pst = null;
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index dd45111..e3cbd57 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -16,17 +16,16 @@
 
 package android.media;
 
-import android.media.CamcorderProfile;
 import android.hardware.Camera;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.util.Log;
 import android.view.Surface;
-import java.io.IOException;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
+
 import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
 import java.lang.ref.WeakReference;
 
 /**
@@ -112,7 +111,8 @@
     /**
      * Sets a Camera to use for recording. Use this function to switch
      * quickly between preview and capture mode without a teardown of
-     * the camera object. Must call before prepare().
+     * the camera object. {@link android.hardware.Camera#unlock()} should be
+     * called before this. Must call before prepare().
      *
      * @param c the Camera to use for recording
      */
@@ -718,6 +718,12 @@
      * Begins capturing and encoding data to the file specified with
      * setOutputFile(). Call this after prepare().
      *
+     * <p>Since API level 13, if applications set a camera via
+     * {@link #setCamera(Camera)}, the apps can use the camera after this method
+     * call. The apps do not need to lock the camera again. However, if this
+     * method fails, the apps should still lock the camera back. The apps should
+     * not start another recording session during recording.
+     *
      * @throws IllegalStateException if it is called before
      * prepare().
      */
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 790eaa3..e8ddd2d 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -101,6 +101,8 @@
  * Java MyMediaScanner handleStringTag.
  * Once MediaScanner processFile returns, an entry is inserted in to the database.
  *
+ * The MediaScanner class is not thread-safe, so it should only be used in a single threaded manner.
+ *
  * {@hide}
  */
 public class MediaScanner
@@ -368,6 +370,34 @@
         }
     }
 
+    private class FileInserter {
+
+        ContentValues[] mValues = new ContentValues[1000];
+        int mIndex = 0;
+
+        public Uri insert(ContentValues values) {
+            if (mIndex == mValues.length) {
+                flush();
+            }
+            mValues[mIndex++] = values;
+            // URI not needed when doing bulk inserts
+            return null;
+        }
+
+        public void flush() {
+            while (mIndex < mValues.length) {
+                mValues[mIndex++] = null;
+            }
+            try {
+                mMediaProvider.bulkInsert(mFilesUri, mValues);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException in FileInserter.flush()", e);
+            }
+            mIndex = 0;
+        }
+    }
+    private FileInserter mFileInserter;
+
     // hashes file path to FileCacheEntry.
     // path should be lower case if mCaseInsensitivePaths is true
     private HashMap<String, FileCacheEntry> mFileCache;
@@ -422,6 +452,7 @@
         private long mFileSize;
         private String mWriter;
         private int mCompilation;
+        private boolean mIsDrm;
         private boolean mNoMedia;   // flag to suppress file from appearing in media tables
 
         public FileCacheEntry beginFile(String path, String mimeType, long lastModified,
@@ -497,6 +528,7 @@
             mLastModified = lastModified;
             mWriter = null;
             mCompilation = 0;
+            mIsDrm = false;
 
             return entry;
         }
@@ -599,6 +631,8 @@
                 mWriter = value.trim();
             } else if (name.equalsIgnoreCase("compilation")) {
                 mCompilation = parseSubstring(value, 0, 0);
+            } else if (name.equalsIgnoreCase("isdrm")) {
+                mIsDrm = (parseSubstring(value, 0, 0) == 1);
             }
         }
 
@@ -671,6 +705,7 @@
             map.put(MediaStore.MediaColumns.DATE_MODIFIED, mLastModified);
             map.put(MediaStore.MediaColumns.SIZE, mFileSize);
             map.put(MediaStore.MediaColumns.MIME_TYPE, mMimeType);
+            map.put(MediaStore.MediaColumns.IS_DRM, mIsDrm);
 
             if (!mNoMedia) {
                 if (MediaFile.isVideoFileType(mFileType)) {
@@ -800,37 +835,31 @@
                 }
             }
 
-            Uri tableUri = mFilesUri;
-            if (!mNoMedia) {
-                if (MediaFile.isVideoFileType(mFileType)) {
-                    tableUri = mVideoUri;
-                } else if (MediaFile.isImageFileType(mFileType)) {
-                    tableUri = mImagesUri;
-                } else if (MediaFile.isAudioFileType(mFileType)) {
-                    tableUri = mAudioUri;
-                }
-            }
             Uri result = null;
             if (rowId == 0) {
                 if (mMtpObjectHandle != 0) {
                     values.put(MediaStore.MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, mMtpObjectHandle);
                 }
-                if (tableUri == mFilesUri) {
-                    int format = entry.mFormat;
-                    if (format == 0) {
-                        format = MediaFile.getFormatCode(entry.mPath, mMimeType);
-                    }
-                    values.put(Files.FileColumns.FORMAT, format);
+                int format = entry.mFormat;
+                if (format == 0) {
+                    format = MediaFile.getFormatCode(entry.mPath, mMimeType);
                 }
+                values.put(Files.FileColumns.FORMAT, format);
+
                 // new file, insert it
-                result = mMediaProvider.insert(tableUri, values);
+                if (mFileInserter != null) {
+                    result = mFileInserter.insert(values);
+                } else {
+                    result = mMediaProvider.insert(mFilesUri, values);
+                }
+
                 if (result != null) {
                     rowId = ContentUris.parseId(result);
                     entry.mRowId = rowId;
                 }
             } else {
                 // updated file
-                result = ContentUris.withAppendedId(tableUri, rowId);
+                result = ContentUris.withAppendedId(mFilesUri, rowId);
                 // path should never change, and we want to avoid replacing mixed cased paths
                 // with squashed lower case paths
                 values.remove(MediaStore.MediaColumns.DATA);
@@ -849,7 +878,7 @@
                                         new String[] { genre }, null);
                         if (cursor == null || cursor.getCount() == 0) {
                             // genre does not exist, so create the genre in the genre table
-                            values.clear();
+                            values = new ContentValues();
                             values.put(MediaStore.Audio.Genres.NAME, genre);
                             uri = mMediaProvider.insert(mGenresUri, values);
                         } else {
@@ -871,7 +900,7 @@
 
                 if (uri != null) {
                     // add entry to audio_genre_map
-                    values.clear();
+                    values = new ContentValues();
                     values.put(MediaStore.Audio.Genres.Members.AUDIO_ID, Long.valueOf(rowId));
                     mMediaProvider.insert(uri, values);
                 }
@@ -880,19 +909,19 @@
             if (notifications && !mDefaultNotificationSet) {
                 if (TextUtils.isEmpty(mDefaultNotificationFilename) ||
                         doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) {
-                    setSettingIfNotSet(Settings.System.NOTIFICATION_SOUND, tableUri, rowId);
+                    setSettingIfNotSet(Settings.System.NOTIFICATION_SOUND, mFilesUri, rowId);
                     mDefaultNotificationSet = true;
                 }
             } else if (ringtones && !mDefaultRingtoneSet) {
                 if (TextUtils.isEmpty(mDefaultRingtoneFilename) ||
                         doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) {
-                    setSettingIfNotSet(Settings.System.RINGTONE, tableUri, rowId);
+                    setSettingIfNotSet(Settings.System.RINGTONE, mFilesUri, rowId);
                     mDefaultRingtoneSet = true;
                 }
             } else if (alarms && !mDefaultAlarmSet) {
                 if (TextUtils.isEmpty(mDefaultAlarmAlertFilename) ||
                         doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)) {
-                    setSettingIfNotSet(Settings.System.ALARM_ALERT, tableUri, rowId);
+                    setSettingIfNotSet(Settings.System.ALARM_ALERT, mFilesUri, rowId);
                     mDefaultAlarmSet = true;
                 }
             }
@@ -1147,10 +1176,6 @@
             mPlaylistsUri = Playlists.getContentUri(volumeName);
 
             mCaseInsensitivePaths = true;
-            if (!Process.supportsProcesses()) {
-                // Simulator uses host file system, so it should be case sensitive.
-                mCaseInsensitivePaths = false;
-            }
         }
     }
 
@@ -1160,10 +1185,14 @@
             initialize(volumeName);
             prescan(null, true);
             long prescan = System.currentTimeMillis();
+            mFileInserter = new FileInserter();
 
             for (int i = 0; i < directories.length; i++) {
                 processDirectory(directories[i], mClient);
             }
+            mFileInserter.flush();
+            mFileInserter = null;
+
             long scan = System.currentTimeMillis();
             postscan(directories);
             long end = System.currentTimeMillis();
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 8481410..9c0819f 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -487,7 +487,7 @@
     private Cursor getInternalRingtones() {
         return query(
                 MediaStore.Audio.Media.INTERNAL_CONTENT_URI, INTERNAL_COLUMNS,
-                constructBooleanTrueWhereClause(mFilterColumns),
+                constructBooleanTrueWhereClause(mFilterColumns, mIncludeDrm),
                 null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
     }
     
@@ -506,7 +506,7 @@
                     status.equals(Environment.MEDIA_MOUNTED_READ_ONLY))
                 ? query(
                     MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, MEDIA_COLUMNS,
-                    constructBooleanTrueWhereClause(mFilterColumns), null,
+                    constructBooleanTrueWhereClause(mFilterColumns, mIncludeDrm), null,
                     MediaStore.Audio.Media.DEFAULT_SORT_ORDER)
                 : null;
     }
@@ -536,11 +536,13 @@
      * @param columns The columns that must be true.
      * @return The where clause.
      */
-    private static String constructBooleanTrueWhereClause(List<String> columns) {
+    private static String constructBooleanTrueWhereClause(List<String> columns, boolean includeDrm) {
         
         if (columns == null) return null;
         
         StringBuilder sb = new StringBuilder();
+        sb.append("(");
+
         for (int i = columns.size() - 1; i >= 0; i--) {
             sb.append(columns.get(i)).append("=1 or ");
         }
@@ -549,7 +551,18 @@
             // Remove last ' or '
             sb.setLength(sb.length() - 4);
         }
-        
+
+        sb.append(")");
+
+        if (!includeDrm) {
+            // If not DRM files should be shown, the where clause
+            // will be something like "(is_notification=1) and is_drm=0"
+            sb.append(" and ");
+            sb.append(MediaStore.MediaColumns.IS_DRM);
+            sb.append("=0");
+        }
+
+
         return sb.toString();
     }
     
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index 29c4b89..0d2bcd5 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -957,12 +957,8 @@
 
         public static final int FADE_FROM_BLACK = 8;
 
-        public static final int CURTAIN_OPENING = 9;
-
         public static final int FADE_TO_BLACK = 16;
 
-        public static final int CURTAIN_CLOSING = 17;
-
         public static final int EXTERNAL = 256;
 
         public static final int BLACK_AND_WHITE = 257;
diff --git a/media/java/android/mtp/MtpPropertyGroup.java b/media/java/android/mtp/MtpPropertyGroup.java
index b75b11a..76c8569 100644
--- a/media/java/android/mtp/MtpPropertyGroup.java
+++ b/media/java/android/mtp/MtpPropertyGroup.java
@@ -330,7 +330,6 @@
             }
 
             int count = (c == null ? 1 : c.getCount());
-            Log.d(TAG, "count: " + count);
             MtpPropertyList result = new MtpPropertyList(count * mProperties.length,
                     MtpConstants.RESPONSE_OK);
 
diff --git a/media/java/android/mtp/MtpStorage.java b/media/java/android/mtp/MtpStorage.java
index 7932d34..da190a6 100644
--- a/media/java/android/mtp/MtpStorage.java
+++ b/media/java/android/mtp/MtpStorage.java
@@ -32,6 +32,7 @@
     private final String mDescription;
     private final long mReserveSpace;
     private final boolean mRemovable;
+    private final long mMaxFileSize;
 
     public MtpStorage(StorageVolume volume) {
         mStorageId = volume.getStorageId();
@@ -39,6 +40,7 @@
         mDescription = volume.getDescription();
         mReserveSpace = volume.getMtpReserveSpace();
         mRemovable = volume.isRemovable();
+        mMaxFileSize = volume.getMaxFileSize();
     }
 
     /**
@@ -98,4 +100,13 @@
     public final boolean isRemovable() {
         return mRemovable;
     }
+
+   /**
+     * Returns maximum file size for the storage, or zero if it is unbounded.
+     *
+     * @return maximum file size
+     */
+    public long getMaxFileSize() {
+        return mMaxFileSize;
+    }
 }
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 2f7d7ee..12391c8 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -158,7 +158,7 @@
     }
     sp<Camera> c = get_native_camera(env, camera, NULL);
     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
-    process_media_recorder_call(env, mr->setCamera(c->remote()),
+    process_media_recorder_call(env, mr->setCamera(c->remote(), c->getRecordingProxy()),
             "java/lang/RuntimeException", "setCamera failed.");
 }
 
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index 9151799..d0d2d1e 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -45,7 +45,6 @@
     jfieldID    context;
 };
 static fields_t fields;
-static Mutex sLock;
 
 class MyMediaScannerClient : public MediaScannerClient
 {
@@ -159,13 +158,11 @@
     return ((JNIEnv *)env)->ExceptionCheck();
 }
 
-// Call this method with sLock hold
 static MediaScanner *getNativeScanner_l(JNIEnv* env, jobject thiz)
 {
     return (MediaScanner *) env->GetIntField(thiz, fields.context);
 }
 
-// Call this method with sLock hold
 static void setNativeScanner_l(JNIEnv* env, jobject thiz, MediaScanner *s)
 {
     env->SetIntField(thiz, fields.context, (int)s);
@@ -176,7 +173,6 @@
         JNIEnv *env, jobject thiz, jstring path, jobject client)
 {
     LOGV("processDirectory");
-    Mutex::Autolock l(sLock);
     MediaScanner *mp = getNativeScanner_l(env, thiz);
     if (mp == NULL) {
         jniThrowException(env, kRunTimeException, "No scanner available");
@@ -243,7 +239,6 @@
         JNIEnv *env, jobject thiz, jstring locale)
 {
     LOGV("setLocale");
-    Mutex::Autolock l(sLock);
     MediaScanner *mp = getNativeScanner_l(env, thiz);
     if (mp == NULL) {
         jniThrowException(env, kRunTimeException, "No scanner available");
@@ -268,7 +263,6 @@
         JNIEnv *env, jobject thiz, jobject fileDescriptor)
 {
     LOGV("extractAlbumArt");
-    Mutex::Autolock l(sLock);
     MediaScanner *mp = getNativeScanner_l(env, thiz);
     if (mp == NULL) {
         jniThrowException(env, kRunTimeException, "No scanner available");
@@ -339,7 +333,6 @@
 android_media_MediaScanner_native_finalize(JNIEnv *env, jobject thiz)
 {
     LOGV("native_finalize");
-    Mutex::Autolock l(sLock);
     MediaScanner *mp = getNativeScanner_l(env, thiz);
     if (mp == 0) {
         return;
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index aaf85c3..446b630 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -48,6 +48,7 @@
 static jfieldID field_MtpStorage_description;
 static jfieldID field_MtpStorage_reserveSpace;
 static jfieldID field_MtpStorage_removable;
+static jfieldID field_MtpStorage_maxFileSize;
 
 static Mutex sMutex;
 
@@ -228,12 +229,14 @@
         jstring description = (jstring)env->GetObjectField(jstorage, field_MtpStorage_description);
         jlong reserveSpace = env->GetLongField(jstorage, field_MtpStorage_reserveSpace);
         jboolean removable = env->GetBooleanField(jstorage, field_MtpStorage_removable);
+        jlong maxFileSize = env->GetLongField(jstorage, field_MtpStorage_maxFileSize);
 
         const char *pathStr = env->GetStringUTFChars(path, NULL);
         if (pathStr != NULL) {
             const char *descriptionStr = env->GetStringUTFChars(description, NULL);
             if (descriptionStr != NULL) {
-                MtpStorage* storage = new MtpStorage(storageID, pathStr, descriptionStr, reserveSpace, removable);
+                MtpStorage* storage = new MtpStorage(storageID, pathStr, descriptionStr,
+                        reserveSpace, removable, maxFileSize);
                 thread->addStorage(storage);
                 env->ReleaseStringUTFChars(path, pathStr);
                 env->ReleaseStringUTFChars(description, descriptionStr);
@@ -312,6 +315,11 @@
         LOGE("Can't find MtpStorage.mRemovable");
         return -1;
     }
+    field_MtpStorage_maxFileSize = env->GetFieldID(clazz, "mMaxFileSize", "J");
+    if (field_MtpStorage_maxFileSize == NULL) {
+        LOGE("Can't find MtpStorage.mMaxFileSize");
+        return -1;
+    }
     clazz_MtpStorage = (jclass)env->NewGlobalRef(clazz);
 
     clazz = env->FindClass("android/mtp/MtpServer");
diff --git a/media/jni/audioeffect/Android.mk b/media/jni/audioeffect/Android.mk
index 4c5cf71..3e493b1 100644
--- a/media/jni/audioeffect/Android.mk
+++ b/media/jni/audioeffect/Android.mk
@@ -12,6 +12,9 @@
 	libnativehelper \
 	libmedia
 
+LOCAL_C_INCLUDES := \
+	system/media/audio_effects/include
+
 LOCAL_MODULE:= libaudioeffect_jni
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/jni/mediaeditor/VideoEditorClasses.cpp b/media/jni/mediaeditor/VideoEditorClasses.cpp
index d43a562..277e16c 100755
--- a/media/jni/mediaeditor/VideoEditorClasses.cpp
+++ b/media/jni/mediaeditor/VideoEditorClasses.cpp
@@ -378,9 +378,7 @@
 {
     VIDEOEDIT_JAVA_CONSTANT_INIT("NONE",            M4VSS3GPP_kVideoEffectType_None),
     VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_FROM_BLACK", M4VSS3GPP_kVideoEffectType_FadeFromBlack),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("CURTAIN_OPENING", M4VSS3GPP_kVideoEffectType_CurtainOpening),
     VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_TO_BLACK",   M4VSS3GPP_kVideoEffectType_FadeToBlack),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("CURTAIN_CLOSING", M4VSS3GPP_kVideoEffectType_CurtainClosing),
     VIDEOEDIT_JAVA_CONSTANT_INIT("EXTERNAL",        M4VSS3GPP_kVideoEffectType_External),
     VIDEOEDIT_JAVA_CONSTANT_INIT("BLACK_AND_WHITE", M4xVSS_kVideoEffectType_BlackAndWhite),
     VIDEOEDIT_JAVA_CONSTANT_INIT("PINK",            M4xVSS_kVideoEffectType_Pink),
diff --git a/media/jni/mediaeditor/VideoEditorOsal.cpp b/media/jni/mediaeditor/VideoEditorOsal.cpp
index 53e7de1..a8c08ac 100755
--- a/media/jni/mediaeditor/VideoEditorOsal.cpp
+++ b/media/jni/mediaeditor/VideoEditorOsal.cpp
@@ -166,7 +166,6 @@
     VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_NO_SUPPORTED_VIDEO_STREAM_IN_FILE        ),
     VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INTERNAL_STATE                           ),
     VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_LUMA_FILTER_ERROR                        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_CURTAIN_FILTER_ERROR                     ),
     VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_TRANSITION_FILTER_ERROR                  ),
     VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_DECODER_INIT_FAILED                ),
     VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_DECODED_PCM_SIZE_ISSUE             ),
diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk
index 99cfdfa..ab13605 100644
--- a/media/libeffects/lvm/wrapper/Android.mk
+++ b/media/libeffects/lvm/wrapper/Android.mk
@@ -30,7 +30,8 @@
 LOCAL_C_INCLUDES += \
 	$(LOCAL_PATH)/Bundle \
 	$(LOCAL_PATH)/../lib/Common/lib/ \
-	$(LOCAL_PATH)/../lib/Bundle/lib/
+	$(LOCAL_PATH)/../lib/Bundle/lib/ \
+	system/media/audio_effects/include
 
 
 include $(BUILD_SHARED_LIBRARY)
@@ -64,6 +65,6 @@
     $(LOCAL_PATH)/Reverb \
     $(LOCAL_PATH)/../lib/Common/lib/ \
     $(LOCAL_PATH)/../lib/Reverb/lib/ \
-
+    system/media/audio_effects/include
 
 include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
index 2b51029..5634ca1 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -17,9 +17,9 @@
 #ifndef ANDROID_EFFECTBUNDLE_H_
 #define ANDROID_EFFECTBUNDLE_H_
 
-#include <media/EffectEqualizerApi.h>
-#include <media/EffectBassBoostApi.h>
-#include <media/EffectVirtualizerApi.h>
+#include <audio_effects/effect_bassboost.h>
+#include <audio_effects/effect_equalizer.h>
+#include <audio_effects/effect_virtualizer.h>
 #include <LVM.h>
 #include <limits.h>
 
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h
index 093992b..7c15b18 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h
@@ -17,8 +17,8 @@
 #ifndef ANDROID_EFFECTREVERB_H_
 #define ANDROID_EFFECTREVERB_H_
 
-#include <media/EffectEnvironmentalReverbApi.h>
-#include <media/EffectPresetReverbApi.h>
+#include <audio_effects/effect_environmentalreverb.h>
+#include <audio_effects/effect_presetreverb.h>
 
 #if __cplusplus
 extern "C" {
diff --git a/media/libeffects/testlibs/Android.mk_ b/media/libeffects/testlibs/Android.mk_
index 98d477b..249ebf4 100644
--- a/media/libeffects/testlibs/Android.mk_
+++ b/media/libeffects/testlibs/Android.mk_
@@ -23,6 +23,7 @@
 endif
 
 LOCAL_C_INCLUDES := \
+	system/media/audio_effects/include \
 	$(call include-path-for, graphics corecg)
 
 LOCAL_MODULE_TAGS := optional
@@ -58,7 +59,8 @@
 endif
 
 LOCAL_C_INCLUDES := \
-	$(call include-path-for, graphics corecg)
+	$(call include-path-for, graphics corecg) \
+	system/media/audio_effects/include
 
 LOCAL_MODULE_TAGS := optional
 
diff --git a/media/libeffects/testlibs/EffectEqualizer.cpp b/media/libeffects/testlibs/EffectEqualizer.cpp
index 43dfa82..c2ffce5 100644
--- a/media/libeffects/testlibs/EffectEqualizer.cpp
+++ b/media/libeffects/testlibs/EffectEqualizer.cpp
@@ -26,7 +26,8 @@
 #include "AudioEqualizer.h"
 #include "AudioBiquadFilter.h"
 #include "AudioFormatAdapter.h"
-#include <media/EffectEqualizerApi.h>
+#include <audio_effects/effect_equalizer.h>
+
 
 // effect_handle_t interface implementation for equalizer effect
 extern "C" const struct effect_interface_s gEqualizerInterface;
diff --git a/media/libeffects/testlibs/EffectReverb.h b/media/libeffects/testlibs/EffectReverb.h
index a239814..8e2cc31 100644
--- a/media/libeffects/testlibs/EffectReverb.h
+++ b/media/libeffects/testlibs/EffectReverb.h
@@ -17,8 +17,8 @@
 #ifndef ANDROID_EFFECTREVERB_H_
 #define ANDROID_EFFECTREVERB_H_
 
-#include <media/EffectEnvironmentalReverbApi.h>
-#include <media/EffectPresetReverbApi.h>
+#include <audio_effects/effect_environmentalreverb.h>
+#include <audio_effects/effect_presetreverb.h>
 
 
 /*------------------------------------
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
index 3a0f438..dff585f 100644
--- a/media/libeffects/visualizer/Android.mk
+++ b/media/libeffects/visualizer/Android.mk
@@ -23,8 +23,8 @@
 endif
 
 LOCAL_C_INCLUDES := \
-	$(call include-path-for, graphics corecg)
-
+	$(call include-path-for, graphics corecg) \
+	system/media/audio_effects/include
 
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index 80d1f69..aeebd4d 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -21,7 +21,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <new>
-#include <media/EffectVisualizerApi.h>
+#include <audio_effects/effect_visualizer.h>
 
 
 extern "C" {
@@ -375,7 +375,7 @@
         p->status = 0;
         *replySize = sizeof(effect_param_t) + sizeof(uint32_t);
         if (p->psize != sizeof(uint32_t) ||
-            *(uint32_t *)p->data != VISU_PARAM_CAPTURE_SIZE) {
+            *(uint32_t *)p->data != VISUALIZER_PARAM_CAPTURE_SIZE) {
             p->status = -EINVAL;
             break;
         }
@@ -394,7 +394,7 @@
         effect_param_t *p = (effect_param_t *)pCmdData;
         if (p->psize != sizeof(uint32_t) ||
             p->vsize != sizeof(uint32_t) ||
-            *(uint32_t *)p->data != VISU_PARAM_CAPTURE_SIZE) {
+            *(uint32_t *)p->data != VISUALIZER_PARAM_CAPTURE_SIZE) {
             *(int32_t *)pReplyData = -EINVAL;
             break;;
         }
@@ -407,9 +407,9 @@
         break;
 
 
-    case VISU_CMD_CAPTURE:
+    case VISUALIZER_CMD_CAPTURE:
         if (pReplyData == NULL || *replySize != pContext->mCaptureSize) {
-            LOGV("VISU_CMD_CAPTURE() error *replySize %d pContext->mCaptureSize %d",
+            LOGV("VISUALIZER_CMD_CAPTURE() error *replySize %d pContext->mCaptureSize %d",
                     *replySize, pContext->mCaptureSize);
             return -EINVAL;
         }
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 121e38a4..f7c54fa 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -68,6 +68,7 @@
     $(call include-path-for, graphics corecg) \
     $(TOP)/frameworks/base/include/media/stagefright/openmax \
     external/icu4c/common \
-    external/expat/lib
+    external/expat/lib \
+    system/media/audio_effects/include
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 59cd1b7..a44ef5a 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -60,12 +60,13 @@
     {
     }
 
-    status_t setCamera(const sp<ICamera>& camera)
+    status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy)
     {
-        LOGV("setCamera(%p)", camera.get());
+        LOGV("setCamera(%p,%p)", camera.get(), proxy.get());
         Parcel data, reply;
         data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
         data.writeStrongBinder(camera->asBinder());
+        data.writeStrongBinder(proxy->asBinder());
         remote()->transact(SET_CAMERA, data, &reply);
         return reply.readInt32();
     }
@@ -434,7 +435,9 @@
             LOGV("SET_CAMERA");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
             sp<ICamera> camera = interface_cast<ICamera>(data.readStrongBinder());
-            reply->writeInt32(setCamera(camera));
+            sp<ICameraRecordingProxy> proxy =
+                interface_cast<ICameraRecordingProxy>(data.readStrongBinder());
+            reply->writeInt32(setCamera(camera, proxy));
             return NO_ERROR;
         } break;
         default:
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
index 366707c..bf40481 100644
--- a/media/libmedia/Visualizer.cpp
+++ b/media/libmedia/Visualizer.cpp
@@ -143,7 +143,7 @@
 
     p->psize = sizeof(uint32_t);
     p->vsize = sizeof(uint32_t);
-    *(int32_t *)p->data = VISU_PARAM_CAPTURE_SIZE;
+    *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE;
     *((int32_t *)p->data + 1)= size;
     status_t status = setParameter(p);
 
@@ -171,7 +171,7 @@
     status_t status = NO_ERROR;
     if (mEnabled) {
         uint32_t replySize = mCaptureSize;
-        status = command(VISU_CMD_CAPTURE, 0, NULL, &replySize, waveform);
+        status = command(VISUALIZER_CMD_CAPTURE, 0, NULL, &replySize, waveform);
         LOGV("getWaveForm() command returned %d", status);
         if (replySize == 0) {
             status = NOT_ENOUGH_DATA;
@@ -276,7 +276,7 @@
 
     p->psize = sizeof(uint32_t);
     p->vsize = sizeof(uint32_t);
-    *(int32_t *)p->data = VISU_PARAM_CAPTURE_SIZE;
+    *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE;
     status_t status = getParameter(p);
 
     if (status == NO_ERROR) {
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 0100a17..9e4edd0 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -28,9 +28,9 @@
 
 namespace android {
 
-status_t MediaRecorder::setCamera(const sp<ICamera>& camera)
+status_t MediaRecorder::setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy)
 {
-    LOGV("setCamera(%p)", camera.get());
+    LOGV("setCamera(%p,%p)", camera.get(), proxy.get());
     if(mMediaRecorder == NULL) {
         LOGE("media recorder is not initialized yet");
         return INVALID_OPERATION;
@@ -40,7 +40,7 @@
         return INVALID_OPERATION;
     }
 
-    status_t ret = mMediaRecorder->setCamera(camera);
+    status_t ret = mMediaRecorder->setCamera(camera, proxy);
     if (OK != ret) {
         LOGV("setCamera failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index a77dff1..1e7c969 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -250,7 +250,11 @@
         const KeyedVector<String8, String8> *headers, int audioSessionId)
 {
     int32_t connId = android_atomic_inc(&mNextConnId);
-    sp<Client> c = new Client(this, pid, connId, client, audioSessionId);
+
+    sp<Client> c = new Client(
+            this, pid, connId, client, audioSessionId,
+            IPCThreadState::self()->getCallingUid());
+
     LOGV("Create new client(%d) from pid %d, url=%s, connId=%d, audioSessionId=%d",
             connId, pid, url, connId, audioSessionId);
     if (NO_ERROR != c->setDataSource(url, headers))
@@ -268,7 +272,11 @@
         int fd, int64_t offset, int64_t length, int audioSessionId)
 {
     int32_t connId = android_atomic_inc(&mNextConnId);
-    sp<Client> c = new Client(this, pid, connId, client, audioSessionId);
+
+    sp<Client> c = new Client(
+            this, pid, connId, client, audioSessionId,
+            IPCThreadState::self()->getCallingUid());
+
     LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld, audioSessionId=%d",
             connId, pid, fd, offset, length, audioSessionId);
     if (NO_ERROR != c->setDataSource(fd, offset, length)) {
@@ -286,7 +294,10 @@
         pid_t pid, const sp<IMediaPlayerClient> &client,
         const sp<IStreamSource> &source, int audioSessionId) {
     int32_t connId = android_atomic_inc(&mNextConnId);
-    sp<Client> c = new Client(this, pid, connId, client, audioSessionId);
+
+    sp<Client> c = new Client(
+            this, pid, connId, client, audioSessionId,
+            IPCThreadState::self()->getCallingUid());
 
     LOGV("Create new client(%d) from pid %d, audioSessionId=%d",
          connId, pid, audioSessionId);
@@ -496,8 +507,10 @@
     mClients.remove(client);
 }
 
-MediaPlayerService::Client::Client(const sp<MediaPlayerService>& service, pid_t pid,
-        int32_t connId, const sp<IMediaPlayerClient>& client, int audioSessionId)
+MediaPlayerService::Client::Client(
+        const sp<MediaPlayerService>& service, pid_t pid,
+        int32_t connId, const sp<IMediaPlayerClient>& client,
+        int audioSessionId, uid_t uid)
 {
     LOGV("Client(%d) constructor", connId);
     mPid = pid;
@@ -507,6 +520,7 @@
     mLoop = false;
     mStatus = NO_INIT;
     mAudioSessionId = audioSessionId;
+    mUID = uid;
 
 #if CALLBACK_ANTAGONIZER
     LOGD("create Antagonizer");
@@ -671,6 +685,9 @@
     if (p == NULL) {
         p = android::createPlayer(playerType, this, notify);
     }
+
+    p->setUID(mUID);
+
     return p;
 }
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 8bab471..e32b92a 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -306,7 +306,8 @@
                                         pid_t pid,
                                         int32_t connId,
                                         const sp<IMediaPlayerClient>& client,
-                                        int audioSessionId);
+                                        int audioSessionId,
+                                        uid_t uid);
                                 Client();
         virtual                 ~Client();
 
@@ -336,6 +337,7 @@
                     bool                        mLoop;
                     int32_t                     mConnId;
                     int                         mAudioSessionId;
+                    uid_t                       mUID;
 
         // Metadata filters.
         media::Metadata::Filter mMetadataAllow;  // protected by mLock
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 29cc019..115db1a 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -57,7 +57,8 @@
     return ok;
 }
 
-status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera)
+status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera,
+                                        const sp<ICameraRecordingProxy>& proxy)
 {
     LOGV("setCamera");
     Mutex::Autolock lock(mLock);
@@ -65,7 +66,7 @@
         LOGE("recorder is not initialized");
         return NO_INIT;
     }
-    return mRecorder->setCamera(camera);
+    return mRecorder->setCamera(camera, proxy);
 }
 
 status_t MediaRecorderClient::setPreviewSurface(const sp<Surface>& surface)
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index fded98e..bbca529 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -24,11 +24,13 @@
 
 class MediaRecorderBase;
 class MediaPlayerService;
+class ICameraRecordingProxy;
 
 class MediaRecorderClient : public BnMediaRecorder
 {
 public:
-    virtual     status_t        setCamera(const sp<ICamera>& camera);
+    virtual     status_t        setCamera(const sp<ICamera>& camera,
+                                          const sp<ICameraRecordingProxy>& proxy);
     virtual     status_t        setPreviewSurface(const sp<Surface>& surface);
     virtual     status_t        setVideoSource(int vs);
     virtual     status_t        setAudioSource(int as);
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index 870e290..40e055c 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -47,6 +47,12 @@
     return OK;
 }
 
+status_t StagefrightPlayer::setUID(uid_t uid) {
+    mPlayer->setUID(uid);
+
+    return OK;
+}
+
 status_t StagefrightPlayer::setDataSource(
         const char *url, const KeyedVector<String8, String8> *headers) {
     return mPlayer->setDataSource(url, headers);
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index 85a546d..cbc6d49 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -31,6 +31,8 @@
 
     virtual status_t initCheck();
 
+    virtual status_t setUID(uid_t uid);
+
     virtual status_t setDataSource(
             const char *url, const KeyedVector<String8, String8> *headers);
 
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 978571c..223e0be 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -198,14 +198,20 @@
     return OK;
 }
 
-status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) {
+status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera,
+                                        const sp<ICameraRecordingProxy> &proxy) {
     LOGV("setCamera");
     if (camera == 0) {
         LOGE("camera is NULL");
         return BAD_VALUE;
     }
+    if (proxy == 0) {
+        LOGE("camera proxy is NULL");
+        return BAD_VALUE;
+    }
 
     mCamera = camera;
+    mCameraProxy = proxy;
     return OK;
 }
 
@@ -1130,10 +1136,69 @@
         clipVideoFrameRate();
         clipVideoFrameWidth();
         clipVideoFrameHeight();
+        setDefaultProfileIfNecessary();
     }
     return OK;
 }
 
+// Set to use AVC baseline profile if the encoding parameters matches
+// CAMCORDER_QUALITY_LOW profile; this is for the sake of MMS service.
+void StagefrightRecorder::setDefaultProfileIfNecessary() {
+    LOGV("setDefaultProfileIfNecessary");
+
+    camcorder_quality quality = CAMCORDER_QUALITY_LOW;
+
+    int64_t durationUs   = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "duration", mCameraId, quality) * 1000000LL;
+
+    int fileFormat       = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "file.format", mCameraId, quality);
+
+    int videoCodec       = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "vid.codec", mCameraId, quality);
+
+    int videoBitRate     = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "vid.bps", mCameraId, quality);
+
+    int videoFrameRate   = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "vid.fps", mCameraId, quality);
+
+    int videoFrameWidth  = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "vid.width", mCameraId, quality);
+
+    int videoFrameHeight = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "vid.height", mCameraId, quality);
+
+    int audioCodec       = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "aud.codec", mCameraId, quality);
+
+    int audioBitRate     = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "aud.bps", mCameraId, quality);
+
+    int audioSampleRate  = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "aud.hz", mCameraId, quality);
+
+    int audioChannels    = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "aud.ch", mCameraId, quality);
+
+    if (durationUs == mMaxFileDurationUs &&
+        fileFormat == mOutputFormat &&
+        videoCodec == mVideoEncoder &&
+        videoBitRate == mVideoBitRate &&
+        videoFrameRate == mFrameRate &&
+        videoFrameWidth == mVideoWidth &&
+        videoFrameHeight == mVideoHeight &&
+        audioCodec == mAudioEncoder &&
+        audioBitRate == mAudioBitRate &&
+        audioSampleRate == mSampleRate &&
+        audioChannels == mAudioChannels) {
+        if (videoCodec == VIDEO_ENCODER_H264) {
+            LOGI("Force to use AVC baseline profile");
+            setParamVideoEncoderProfile(OMX_VIDEO_AVCProfileBaseline);
+        }
+    }
+}
+
 status_t StagefrightRecorder::checkAudioEncoderCapabilities() {
     clipAudioBitRate();
     clipAudioSampleRate();
@@ -1235,15 +1300,17 @@
     videoSize.height = mVideoHeight;
     if (mCaptureTimeLapse) {
         mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera(
-                mCamera, mCameraId,
+                mCamera, mCameraProxy, mCameraId,
                 videoSize, mFrameRate, mPreviewSurface,
                 mTimeBetweenTimeLapseFrameCaptureUs);
         *cameraSource = mCameraSourceTimeLapse;
     } else {
         *cameraSource = CameraSource::CreateFromCamera(
-                mCamera, mCameraId, videoSize, mFrameRate,
+                mCamera, mCameraProxy, mCameraId, videoSize, mFrameRate,
                 mPreviewSurface, true /*storeMetaDataInVideoBuffers*/);
     }
+    mCamera.clear();
+    mCameraProxy.clear();
     if (*cameraSource == NULL) {
         return UNKNOWN_ERROR;
     }
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index aa67aa7..034b373 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -27,6 +27,7 @@
 namespace android {
 
 class Camera;
+class ICameraRecordingProxy;
 class CameraSource;
 class CameraSourceTimeLapse;
 class MediaSourceSplitter;
@@ -48,7 +49,7 @@
     virtual status_t setVideoEncoder(video_encoder ve);
     virtual status_t setVideoSize(int width, int height);
     virtual status_t setVideoFrameRate(int frames_per_second);
-    virtual status_t setCamera(const sp<ICamera>& camera);
+    virtual status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
     virtual status_t setPreviewSurface(const sp<Surface>& surface);
     virtual status_t setOutputFile(const char *path);
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
@@ -66,6 +67,7 @@
 
 private:
     sp<ICamera> mCamera;
+    sp<ICameraRecordingProxy> mCameraProxy;
     sp<Surface> mPreviewSurface;
     sp<IMediaRecorderClient> mListener;
     sp<MediaWriter> mWriter, mWriterAux;
@@ -172,6 +174,7 @@
     void clipAudioBitRate();
     void clipAudioSampleRate();
     void clipNumberOfAudioChannels();
+    void setDefaultProfileIfNecessary();
 
     StagefrightRecorder(const StagefrightRecorder &);
     StagefrightRecorder &operator=(const StagefrightRecorder &);
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index b3b3af5..5a5330d 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -35,8 +35,11 @@
 
 NuPlayer::HTTPLiveSource::HTTPLiveSource(
         const char *url,
-        const KeyedVector<String8, String8> *headers)
+        const KeyedVector<String8, String8> *headers,
+        bool uidValid, uid_t uid)
     : mURL(url),
+      mUIDValid(uidValid),
+      mUID(uid),
       mFlags(0),
       mEOS(false),
       mOffset(0) {
@@ -65,7 +68,8 @@
     mLiveLooper->start();
 
     mLiveSession = new LiveSession(
-            (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0);
+            (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0,
+            mUIDValid, mUID);
 
     mLiveLooper->registerHandler(mLiveSession);
 
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
index 7a337e9..36c67c5 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
@@ -29,7 +29,9 @@
 struct NuPlayer::HTTPLiveSource : public NuPlayer::Source {
     HTTPLiveSource(
             const char *url,
-            const KeyedVector<String8, String8> *headers);
+            const KeyedVector<String8, String8> *headers,
+            bool uidValid = false,
+            uid_t uid = 0);
 
     virtual void start();
 
@@ -54,6 +56,8 @@
 
     AString mURL;
     KeyedVector<String8, String8> mExtraHeaders;
+    bool mUIDValid;
+    uid_t mUID;
     uint32_t mFlags;
     bool mEOS;
     off64_t mOffset;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index effa703..b06f20d 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -44,7 +44,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 NuPlayer::NuPlayer()
-    : mAudioEOS(false),
+    : mUIDValid(false),
+      mAudioEOS(false),
       mVideoEOS(false),
       mScanSourcesPending(false),
       mScanSourcesGeneration(0),
@@ -57,6 +58,11 @@
 NuPlayer::~NuPlayer() {
 }
 
+void NuPlayer::setUID(uid_t uid) {
+    mUIDValid = true;
+    mUID = uid;
+}
+
 void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
     mDriver = driver;
 }
@@ -72,7 +78,7 @@
         const char *url, const KeyedVector<String8, String8> *headers) {
     sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
 
-    msg->setObject("source", new HTTPLiveSource(url, headers));
+    msg->setObject("source", new HTTPLiveSource(url, headers, mUIDValid, mUID));
     msg->post();
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index fb5b001..cf9185b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -33,6 +33,8 @@
 struct NuPlayer : public AHandler {
     NuPlayer();
 
+    void setUID(uid_t uid);
+
     void setDriver(const wp<NuPlayerDriver> &driver);
 
     void setDataSource(const sp<IStreamSource> &source);
@@ -84,6 +86,8 @@
     };
 
     wp<NuPlayerDriver> mDriver;
+    bool mUIDValid;
+    uid_t mUID;
     sp<Source> mSource;
     sp<NativeWindowWrapper> mNativeWindow;
     sp<MediaPlayerBase::AudioSink> mAudioSink;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index e1213f4..7cd8b6c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -55,6 +55,12 @@
     return OK;
 }
 
+status_t NuPlayerDriver::setUID(uid_t uid) {
+    mPlayer->setUID(uid);
+
+    return OK;
+}
+
 status_t NuPlayerDriver::setDataSource(
         const char *url, const KeyedVector<String8, String8> *headers) {
     CHECK_EQ((int)mState, (int)UNINITIALIZED);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 145fd80..1bb7ca2 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -28,6 +28,8 @@
 
     virtual status_t initCheck();
 
+    virtual status_t setUID(uid_t uid);
+
     virtual status_t setDataSource(
             const char *url, const KeyedVector<String8, String8> *headers);
 
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index d628301..d4d07b2 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -29,6 +29,7 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/NativeWindowWrapper.h>
 #include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
 
 #include <surfaceflinger/Surface.h>
 #include <gui/SurfaceTextureClient.h>
@@ -401,11 +402,22 @@
         CHECK(mem.get() != NULL);
 
         IOMX::buffer_id buffer;
-#if 0
-        err = mOMX->allocateBufferWithBackup(mNode, portIndex, mem, &buffer);
-#else
-        err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
-#endif
+
+        if (!strcasecmp(
+                    mComponentName.c_str(), "OMX.TI.DUCATI1.VIDEO.DECODER")) {
+            if (portIndex == kPortIndexInput && i == 0) {
+                // Only log this warning once per allocation round.
+
+                LOGW("OMX.TI.DUCATI1.VIDEO.DECODER requires the use of "
+                     "OMX_AllocateBuffer instead of the preferred "
+                     "OMX_UseBuffer. Vendor must fix this.");
+            }
+
+            err = mOMX->allocateBufferWithBackup(
+                    mNode, portIndex, mem, &buffer);
+        } else {
+            err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
+        }
 
         if (err != OK) {
             return err;
@@ -891,6 +903,7 @@
     CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
            || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
            || format.eColorFormat == OMX_COLOR_FormatCbYCrY
+           || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
            || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
 
     return mOMX->setParameter(
@@ -1177,6 +1190,17 @@
             CHECK(msg->findInt32("data1", &data1));
             CHECK(msg->findInt32("data2", &data2));
 
+            if (event == OMX_EventCmdComplete
+                    && data1 == OMX_CommandFlush
+                    && data2 == (int32_t)OMX_ALL) {
+                // Use of this notification is not consistent across
+                // implementations. We'll drop this notification and rely
+                // on flush-complete notifications on the individual port
+                // indices instead.
+
+                return true;
+            }
+
             return onOMXEvent(
                     static_cast<OMX_EVENTTYPE>(event),
                     static_cast<OMX_U32>(data1),
@@ -1639,27 +1663,33 @@
     AString mime;
     CHECK(msg->findString("mime", &mime));
 
-    AString componentName;
-
-    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
-        componentName = "OMX.Nvidia.h264.decode";
-    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
-        componentName = "OMX.google.aac.decoder";
-    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_MPEG)) {
-        componentName = "OMX.Nvidia.mp3.decoder";
-    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG2)) {
-        componentName = "OMX.Nvidia.mpeg2v.decode";
-    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
-        componentName = "OMX.google.mpeg4.decoder";
-    } else {
-        TRESPASS();
-    }
+    Vector<String8> matchingCodecs;
+    OMXCodec::findMatchingCodecs(
+            mime.c_str(),
+            false, // createEncoder
+            NULL,  // matchComponentName
+            0,     // flags
+            &matchingCodecs);
 
     sp<CodecObserver> observer = new CodecObserver;
+    IOMX::node_id node = NULL;
 
-    IOMX::node_id node;
-    CHECK_EQ(omx->allocateNode(componentName.c_str(), observer, &node),
-             (status_t)OK);
+    AString componentName;
+
+    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
+            ++matchIndex) {
+        componentName = matchingCodecs.itemAt(matchIndex).string();
+
+        status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
+
+        if (err == OK) {
+            break;
+        }
+
+        node = NULL;
+    }
+
+    CHECK(node != NULL);
 
     sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
     observer->setNotificationMessage(notify);
@@ -2100,6 +2130,7 @@
             return BaseState::onOMXEvent(event, data1, data2);
     }
 }
+
 void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
     if (mCodec->allYourBuffersAreBelongToUs()) {
         CHECK_EQ(mCodec->mOMX->sendCommand(
@@ -2263,6 +2294,11 @@
             if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
                 CHECK(!mFlushComplete[data2]);
                 mFlushComplete[data2] = true;
+
+                if (mFlushComplete[kPortIndexInput]
+                        && mFlushComplete[kPortIndexOutput]) {
+                    changeStateIfWeOwnAllBuffers();
+                }
             } else {
                 CHECK_EQ(data2, OMX_ALL);
                 CHECK(mFlushComplete[kPortIndexInput]);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index aa7edcc..77c25d1 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -128,6 +128,9 @@
     }
 
     virtual void render(MediaBuffer *buffer) {
+        int64_t timeUs;
+        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+        native_window_set_buffers_timestamp(mNativeWindow.get(), timeUs * 1000);
         status_t err = mNativeWindow->queueBuffer(
                 mNativeWindow.get(), buffer->graphicBuffer().get());
         if (err != 0) {
@@ -180,6 +183,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 AwesomePlayer::AwesomePlayer()
     : mQueueStarted(false),
+      mUIDValid(false),
       mTimeSource(NULL),
       mVideoRendererIsPreview(false),
       mAudioPlayer(NULL),
@@ -243,6 +247,13 @@
     mListener = listener;
 }
 
+void AwesomePlayer::setUID(uid_t uid) {
+    LOGI("AwesomePlayer running on behalf of uid %d", uid);
+
+    mUID = uid;
+    mUIDValid = true;
+}
+
 status_t AwesomePlayer::setDataSource(
         const char *uri, const KeyedVector<String8, String8> *headers) {
     Mutex::Autolock autoLock(mLock);
@@ -1928,6 +1939,10 @@
                     ? HTTPBase::kFlagIncognito
                     : 0);
 
+        if (mUIDValid) {
+            mConnectingDataSource->setUID(mUID);
+        }
+
         mLock.unlock();
         status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
         mLock.lock();
@@ -2009,6 +2024,10 @@
         mRTSPController = new ARTSPController(mLooper);
         mConnectingRTSPController = mRTSPController;
 
+        if (mUIDValid) {
+            mConnectingRTSPController->setUID(mUID);
+        }
+
         mLock.unlock();
         status_t err = mRTSPController->connect(mUri.string());
         mLock.lock();
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 61bb2a8..c7e7ced 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -115,19 +115,20 @@
     size.height = -1;
 
     sp<ICamera> camera;
-    return new CameraSource(camera, 0, size, -1, NULL, false);
+    return new CameraSource(camera, NULL, 0, size, -1, NULL, false);
 }
 
 // static
 CameraSource *CameraSource::CreateFromCamera(
     const sp<ICamera>& camera,
+    const sp<ICameraRecordingProxy>& proxy,
     int32_t cameraId,
     Size videoSize,
     int32_t frameRate,
     const sp<Surface>& surface,
     bool storeMetaDataInVideoBuffers) {
 
-    CameraSource *source = new CameraSource(camera, cameraId,
+    CameraSource *source = new CameraSource(camera, proxy, cameraId,
                     videoSize, frameRate, surface,
                     storeMetaDataInVideoBuffers);
     return source;
@@ -135,6 +136,7 @@
 
 CameraSource::CameraSource(
     const sp<ICamera>& camera,
+    const sp<ICameraRecordingProxy>& proxy,
     int32_t cameraId,
     Size videoSize,
     int32_t frameRate,
@@ -153,13 +155,13 @@
       mNumGlitches(0),
       mGlitchDurationThresholdUs(200000),
       mCollectStats(false) {
-
     mVideoSize.width  = -1;
     mVideoSize.height = -1;
 
-    mInitCheck = init(camera, cameraId,
+    mInitCheck = init(camera, proxy, cameraId,
                     videoSize, frameRate,
                     storeMetaDataInVideoBuffers);
+    if (mInitCheck != OK) releaseCamera();
 }
 
 status_t CameraSource::initCheck() const {
@@ -167,24 +169,32 @@
 }
 
 status_t CameraSource::isCameraAvailable(
-    const sp<ICamera>& camera, int32_t cameraId) {
+    const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+    int32_t cameraId) {
 
     if (camera == 0) {
         mCamera = Camera::connect(cameraId);
+        if (mCamera == 0) return -EBUSY;
+        // If proxy is not passed in by applications, still use the proxy of
+        // our own Camera to simplify the code.
+        mCameraRecordingProxy = mCamera->getRecordingProxy();
         mCameraFlags &= ~FLAGS_HOT_CAMERA;
     } else {
+        // We get the proxy from Camera, not ICamera. We need to get the proxy
+        // to the remote Camera owned by the application. Here mCamera is a
+        // local Camera object created by us. We cannot use the proxy from
+        // mCamera here.
         mCamera = Camera::create(camera);
+        if (mCamera == 0) return -EBUSY;
+        mCameraRecordingProxy = proxy;
         mCameraFlags |= FLAGS_HOT_CAMERA;
     }
 
-    // Is camera available?
-    if (mCamera == 0) {
-        LOGE("Camera connection could not be established.");
-        return -EBUSY;
-    }
-    if (!(mCameraFlags & FLAGS_HOT_CAMERA)) {
-        mCamera->lock();
-    }
+    mCamera->lock();
+    mDeathNotifier = new DeathNotifier();
+    // isBinderAlive needs linkToDeath to work.
+    mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
+
     return OK;
 }
 
@@ -286,7 +296,6 @@
     if (width != -1 && height != -1) {
         if (!isVideoSizeSupported(width, height, sizes)) {
             LOGE("Video dimension (%dx%d) is unsupported", width, height);
-            releaseCamera();
             return BAD_VALUE;
         }
         if (isSetVideoSizeSupportedByCamera) {
@@ -300,7 +309,6 @@
         // If one and only one of the width and height is -1
         // we reject such a request.
         LOGE("Requested video size (%dx%d) is not supported", width, height);
-        releaseCamera();
         return BAD_VALUE;
     } else {  // width == -1 && height == -1
         // Do not configure the camera.
@@ -318,7 +326,6 @@
         if (strstr(supportedFrameRates, buf) == NULL) {
             LOGE("Requested frame rate (%d) is not supported: %s",
                 frameRate, supportedFrameRates);
-            releaseCamera();
             return BAD_VALUE;
         }
 
@@ -447,6 +454,7 @@
  */
 status_t CameraSource::init(
         const sp<ICamera>& camera,
+        const sp<ICameraRecordingProxy>& proxy,
         int32_t cameraId,
         Size videoSize,
         int32_t frameRate,
@@ -454,8 +462,24 @@
 
     status_t err = OK;
     int64_t token = IPCThreadState::self()->clearCallingIdentity();
+    err = initWithCameraAccess(camera, proxy, cameraId,
+                               videoSize, frameRate,
+                               storeMetaDataInVideoBuffers);
+    IPCThreadState::self()->restoreCallingIdentity(token);
+    return err;
+}
 
-    if ((err  = isCameraAvailable(camera, cameraId)) != OK) {
+status_t CameraSource::initWithCameraAccess(
+        const sp<ICamera>& camera,
+        const sp<ICameraRecordingProxy>& proxy,
+        int32_t cameraId,
+        Size videoSize,
+        int32_t frameRate,
+        bool storeMetaDataInVideoBuffers) {
+    status_t err = OK;
+
+    if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) {
+        LOGE("Camera connection could not be established.");
         return err;
     }
     CameraParameters params(mCamera->getParameters());
@@ -494,8 +518,6 @@
         }
     }
 
-    IPCThreadState::self()->restoreCallingIdentity(token);
-
     int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
     if (glitchDurationUs > mGlitchDurationThresholdUs) {
         mGlitchDurationThresholdUs = glitchDurationUs;
@@ -517,12 +539,23 @@
 CameraSource::~CameraSource() {
     if (mStarted) {
         stop();
+    } else if (mInitCheck == OK) {
+        // Camera is initialized but because start() is never called,
+        // the lock on Camera is never released(). This makes sure
+        // Camera's lock is released in this case.
+        releaseCamera();
     }
 }
 
 void CameraSource::startCameraRecording() {
-    CHECK_EQ(OK, mCamera->startRecording());
-    CHECK(mCamera->recordingEnabled());
+    // Reset the identity to the current thread because media server owns the
+    // camera and recording is started by the applications. The applications
+    // will connect to the camera in ICameraRecordingProxy::startRecording.
+    int64_t token = IPCThreadState::self()->clearCallingIdentity();
+    mCamera->unlock();
+    mCamera.clear();
+    IPCThreadState::self()->restoreCallingIdentity(token);
+    CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this)));
 }
 
 status_t CameraSource::start(MetaData *meta) {
@@ -544,31 +577,35 @@
         mStartTimeUs = startTimeUs;
     }
 
-    // Call setListener first before calling startCameraRecording()
-    // to avoid recording frames being dropped.
-    int64_t token = IPCThreadState::self()->clearCallingIdentity();
-    mCamera->setListener(new CameraSourceListener(this));
     startCameraRecording();
-    IPCThreadState::self()->restoreCallingIdentity(token);
 
     mStarted = true;
     return OK;
 }
 
 void CameraSource::stopCameraRecording() {
-    mCamera->setListener(NULL);
-    mCamera->stopRecording();
+    mCameraRecordingProxy->stopRecording();
 }
 
 void CameraSource::releaseCamera() {
     LOGV("releaseCamera");
-    if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
-        LOGV("Camera was cold when we started, stopping preview");
-        mCamera->stopPreview();
+    if (mCamera != 0) {
+        int64_t token = IPCThreadState::self()->clearCallingIdentity();
+        if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
+            LOGV("Camera was cold when we started, stopping preview");
+            mCamera->stopPreview();
+            mCamera->disconnect();
+        } else {
+            // Unlock the camera so the application can lock it back.
+            mCamera->unlock();
+        }
+        mCamera.clear();
+        IPCThreadState::self()->restoreCallingIdentity(token);
     }
-    mCamera->unlock();
-    mCamera.clear();
-    mCamera = 0;
+    if (mCameraRecordingProxy != 0) {
+        mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier);
+        mCameraRecordingProxy.clear();
+    }
     mCameraFlags = 0;
 }
 
@@ -578,7 +615,6 @@
     mStarted = false;
     mFrameAvailableCondition.signal();
 
-    int64_t token = IPCThreadState::self()->clearCallingIdentity();
     releaseQueuedFrames();
     while (!mFramesBeingEncoded.empty()) {
         if (NO_ERROR !=
@@ -589,7 +625,6 @@
     }
     stopCameraRecording();
     releaseCamera();
-    IPCThreadState::self()->restoreCallingIdentity(token);
 
     if (mCollectStats) {
         LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
@@ -607,8 +642,8 @@
 }
 
 void CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
-    if (mCamera != NULL) {
-        mCamera->releaseRecordingFrame(frame);
+    if (mCameraRecordingProxy != NULL) {
+        mCameraRecordingProxy->releaseRecordingFrame(frame);
     }
 }
 
@@ -627,9 +662,7 @@
 }
 
 void CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
-    int64_t token = IPCThreadState::self()->clearCallingIdentity();
     releaseRecordingFrame(frame);
-    IPCThreadState::self()->restoreCallingIdentity(token);
 }
 
 void CameraSource::signalBufferReturned(MediaBuffer *buffer) {
@@ -669,7 +702,11 @@
         Mutex::Autolock autoLock(mLock);
         while (mStarted && mFramesReceived.empty()) {
             if (NO_ERROR !=
-                mFrameAvailableCondition.waitRelative(mLock, 3000000000LL)) {
+                mFrameAvailableCondition.waitRelative(mLock, 1000000000LL)) {
+                if (!mCameraRecordingProxy->asBinder()->isBinderAlive()) {
+                    LOGW("camera recording proxy is gone");
+                    return ERROR_END_OF_STREAM;
+                }
                 LOGW("Timed out waiting for incoming camera video frames: %lld us",
                     mLastFrameTimestampUs);
             }
@@ -745,4 +782,17 @@
     return mIsMetaDataStoredInVideoBuffers;
 }
 
+CameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
+    mSource = source;
+}
+
+void CameraSource::ProxyListener::dataCallbackTimestamp(
+        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
+    mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr);
+}
+
+void CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who) {
+    LOGI("Camera recording proxy died");
+}
+
 }  // namespace android
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index cc22574..fe78c46 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -39,6 +39,7 @@
 // static
 CameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(
         const sp<ICamera> &camera,
+        const sp<ICameraRecordingProxy> &proxy,
         int32_t cameraId,
         Size videoSize,
         int32_t videoFrameRate,
@@ -46,7 +47,7 @@
         int64_t timeBetweenTimeLapseFrameCaptureUs) {
 
     CameraSourceTimeLapse *source = new
-            CameraSourceTimeLapse(camera, cameraId,
+            CameraSourceTimeLapse(camera, proxy, cameraId,
                 videoSize, videoFrameRate, surface,
                 timeBetweenTimeLapseFrameCaptureUs);
 
@@ -61,12 +62,13 @@
 
 CameraSourceTimeLapse::CameraSourceTimeLapse(
         const sp<ICamera>& camera,
+        const sp<ICameraRecordingProxy>& proxy,
         int32_t cameraId,
         Size videoSize,
         int32_t videoFrameRate,
         const sp<Surface>& surface,
         int64_t timeBetweenTimeLapseFrameCaptureUs)
-    : CameraSource(camera, cameraId, videoSize, videoFrameRate, surface, true),
+    : CameraSource(camera, proxy, cameraId, videoSize, videoFrameRate, surface, true),
       mTimeBetweenTimeLapseFrameCaptureUs(timeBetweenTimeLapseFrameCaptureUs),
       mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate),
       mLastTimeLapseFrameRealTimestampUs(0),
@@ -315,7 +317,7 @@
         pthread_attr_destroy(&attr);
     } else {
         LOGV("start time lapse recording using video camera");
-        CHECK_EQ(OK, mCamera->startRecording());
+        CameraSource::startCameraRecording();
     }
 }
 
@@ -337,8 +339,7 @@
         // play the recording sound.
         mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0);
     } else {
-        mCamera->setListener(NULL);
-        mCamera->stopRecording();
+        CameraSource::stopCameraRecording();
     }
     if (mLastReadBufferCopy) {
         mLastReadBufferCopy->release();
@@ -347,9 +348,8 @@
 }
 
 void CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) {
-    if (!mUseStillCameraForTimeLapse &&
-        mCamera != NULL) {
-        mCamera->releaseRecordingFrame(frame);
+    if (!mUseStillCameraForTimeLapse) {
+        CameraSource::releaseRecordingFrame(frame);
     }
 }
 
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
index c0ae29d..0d24551 100644
--- a/media/libstagefright/HTTPBase.cpp
+++ b/media/libstagefright/HTTPBase.cpp
@@ -37,7 +37,8 @@
       mTotalTransferBytes(0),
       mPrevBandwidthMeasureTimeUs(0),
       mPrevEstimatedBandWidthKbps(0),
-      mBandWidthCollectFreqMs(5000) {
+      mBandWidthCollectFreqMs(5000),
+      mUIDValid(false) {
 }
 
 // static
@@ -119,4 +120,19 @@
     return OK;
 }
 
+void HTTPBase::setUID(uid_t uid) {
+    mUIDValid = true;
+    mUID = uid;
+}
+
+bool HTTPBase::getUID(uid_t *uid) const {
+    if (!mUIDValid) {
+        return false;
+    }
+
+    *uid = mUID;
+
+    return true;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/HTTPStream.cpp b/media/libstagefright/HTTPStream.cpp
index a156da6..d526ebd 100644
--- a/media/libstagefright/HTTPStream.cpp
+++ b/media/libstagefright/HTTPStream.cpp
@@ -43,6 +43,7 @@
 
 HTTPStream::HTTPStream()
     : mState(READY),
+      mUIDValid(false),
       mSocket(-1),
       mSSLContext(NULL),
       mSSL(NULL) {
@@ -57,6 +58,11 @@
     }
 }
 
+void HTTPStream::setUID(uid_t uid) {
+    mUIDValid = true;
+    mUID = uid;
+}
+
 static bool MakeSocketBlocking(int s, bool blocking) {
     // Make socket non-blocking.
     int flags = fcntl(s, F_GETFL, 0);
@@ -250,6 +256,10 @@
             continue;
         }
 
+        if (mUIDValid) {
+            RegisterSocketUser(mSocket, mUID);
+        }
+
         setReceiveTimeout(30);  // Time out reads after 30 secs by default.
 
         int s = mSocket;
@@ -596,5 +606,18 @@
     CHECK_EQ(0, setsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)));
 }
 
+// static
+void HTTPStream::RegisterSocketUser(int s, uid_t uid) {
+    // Lower bits MUST be 0.
+    static const uint64_t kTag = 0xdeadbeef00000000ll;
+
+    AString line = StringPrintf("t %d %llu %d", s, kTag, uid);
+
+    int fd = open("/proc/net/xt_qtaguid/ctrl", O_WRONLY);
+    write(fd, line.c_str(), line.size());
+    close(fd);
+    fd = -1;
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index 4e4f289..02eeb40 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -466,6 +466,8 @@
 
 MPEG2TSWriter::MPEG2TSWriter(int fd)
     : mFile(fdopen(dup(fd), "wb")),
+      mWriteCookie(NULL),
+      mWriteFunc(NULL),
       mStarted(false),
       mNumSourcesDone(0),
       mNumTSPacketsWritten(0),
@@ -475,6 +477,21 @@
 
 MPEG2TSWriter::MPEG2TSWriter(const char *filename)
     : mFile(fopen(filename, "wb")),
+      mWriteCookie(NULL),
+      mWriteFunc(NULL),
+      mStarted(false),
+      mNumSourcesDone(0),
+      mNumTSPacketsWritten(0),
+      mNumTSPacketsBeforeMeta(0) {
+    init();
+}
+
+MPEG2TSWriter::MPEG2TSWriter(
+        void *cookie,
+        ssize_t (*write)(void *cookie, const void *data, size_t size))
+    : mFile(NULL),
+      mWriteCookie(cookie),
+      mWriteFunc(write),
       mStarted(false),
       mNumSourcesDone(0),
       mNumTSPacketsWritten(0),
@@ -483,7 +500,7 @@
 }
 
 void MPEG2TSWriter::init() {
-    CHECK(mFile != NULL);
+    CHECK(mFile != NULL || mWriteFunc != NULL);
 
     mLooper = new ALooper;
     mLooper->setName("MPEG2TSWriter");
@@ -502,8 +519,10 @@
     mLooper->unregisterHandler(mReflector->id());
     mLooper->stop();
 
-    fclose(mFile);
-    mFile = NULL;
+    if (mFile != NULL) {
+        fclose(mFile);
+        mFile = NULL;
+    }
 }
 
 status_t MPEG2TSWriter::addSource(const sp<MediaSource> &source) {
@@ -718,7 +737,7 @@
     static const unsigned kContinuityCounter = 5;
     buffer->data()[3] |= kContinuityCounter;
 
-    CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size());
+    CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
 }
 
 void MPEG2TSWriter::writeProgramMap() {
@@ -794,7 +813,7 @@
     *ptr++ = 0x00;
     *ptr++ = 0x00;
 
-    CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size());
+    CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
 }
 
 void MPEG2TSWriter::writeAccessUnit(
@@ -890,7 +909,7 @@
 
     memcpy(ptr, accessUnit->data(), copy);
 
-    CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size());
+    CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
 
     size_t offset = copy;
     while (offset < accessUnit->size()) {
@@ -923,7 +942,7 @@
         }
 
         memcpy(ptr, accessUnit->data() + offset, copy);
-        CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile),
+        CHECK_EQ(internalWrite(buffer->data(), buffer->size()),
                  buffer->size());
 
         offset += copy;
@@ -939,5 +958,13 @@
     }
 }
 
+ssize_t MPEG2TSWriter::internalWrite(const void *data, size_t size) {
+    if (mFile != NULL) {
+        return fwrite(data, 1, size, mFile);
+    }
+
+    return (*mWriteFunc)(mWriteCookie, data, size);
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 5582f92..73a05a5 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -387,10 +387,6 @@
     return mInitCheck;
 }
 
-void MPEG4Extractor::setDrmFlag(bool flag) {
-    mIsDrm = flag;
-}
-
 char* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
     if (mFirstSINF == NULL) {
         return NULL;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index f075699..eaad2c3 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -246,6 +246,7 @@
       mIsFileSizeLimitExplicitlyRequested(false),
       mPaused(false),
       mStarted(false),
+      mWriterThreadStarted(false),
       mOffset(0),
       mMdatOffset(0),
       mEstimatedMoovBoxSize(0),
@@ -269,6 +270,7 @@
       mIsFileSizeLimitExplicitlyRequested(false),
       mPaused(false),
       mStarted(false),
+      mWriterThreadStarted(false),
       mOffset(0),
       mMdatOffset(0),
       mEstimatedMoovBoxSize(0),
@@ -538,6 +540,9 @@
 
 void MPEG4Writer::stopWriterThread() {
     LOGD("Stopping writer thread");
+    if (!mWriterThreadStarted) {
+        return;
+    }
 
     {
         Mutex::Autolock autolock(mLock);
@@ -548,6 +553,7 @@
 
     void *dummy;
     pthread_join(mThread, &dummy);
+    mWriterThreadStarted = false;
     LOGD("Writer thread stopped");
 }
 
@@ -603,10 +609,25 @@
     writeInt32(0x40000000);  // w
 }
 
+void MPEG4Writer::release() {
+    close(mFd);
+    mFd = -1;
+    mInitCheck = NO_INIT;
+    mStarted = false;
+}
 
 status_t MPEG4Writer::stop() {
     if (mInitCheck != OK) {
         return OK;
+    } else {
+        if (!mWriterThreadStarted ||
+            !mStarted) {
+            if (mWriterThreadStarted) {
+                stopWriterThread();
+            }
+            release();
+            return OK;
+        }
     }
 
     status_t err = OK;
@@ -637,10 +658,7 @@
 
     // Do not write out movie header on error.
     if (err != OK) {
-        close(mFd);
-        mFd = -1;
-        mInitCheck = NO_INIT;
-        mStarted = false;
+        release();
         return err;
     }
 
@@ -688,11 +706,7 @@
 
     CHECK(mBoxes.empty());
 
-    close(mFd);
-    mFd = -1;
-    mInitCheck = NO_INIT;
-    mStarted = false;
-
+    release();
     return err;
 }
 
@@ -1415,6 +1429,7 @@
     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
     pthread_create(&mThread, &attr, ThreadWrapper, this);
     pthread_attr_destroy(&attr);
+    mWriterThreadStarted = true;
     return OK;
 }
 
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index af0131e..a8023df 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -116,8 +116,13 @@
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC_ADTS)) {
         ret = new AACExtractor(source);
     }
-    if (ret != NULL && isDrm) {
-        ret->getMetaData()->setInt32(kKeyIsDRM, 1);
+
+    if (ret != NULL) {
+       if (isDrm) {
+           ret->setDrmFlag(true);
+       } else {
+           ret->setDrmFlag(false);
+       }
     }
 
     return ret;
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index dac2ee4..2949767 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -140,6 +140,11 @@
         return ERROR_MALFORMED;
     }
 
+    uid_t uid;
+    if (getUID(&uid)) {
+        mHTTP.setUID(uid);
+    }
+
     return connect(host, port, path, https, headers, offset);
 }
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 314425f..06363ee 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -477,6 +477,15 @@
         const char *matchComponentName,
         uint32_t flags,
         const sp<ANativeWindow> &nativeWindow) {
+    int32_t requiresSecureBuffers;
+    if (source->getFormat()->findInt32(
+                kKeyRequiresSecureBuffers,
+                &requiresSecureBuffers)
+            && requiresSecureBuffers) {
+        flags |= kIgnoreCodecSpecificData;
+        flags |= kUseSecureInputBuffers;
+    }
+
     const char *mime;
     bool success = meta->findCString(kKeyMIMEType, &mime);
     CHECK(success);
@@ -530,17 +539,17 @@
             LOGV("Successfully allocated OMX node '%s'", componentName);
 
             sp<OMXCodec> codec = new OMXCodec(
-                    omx, node, quirks,
+                    omx, node, quirks, flags,
                     createEncoder, mime, componentName,
                     source, nativeWindow);
 
             observer->setCodec(codec);
 
-            err = codec->configureCodec(meta, flags);
+            err = codec->configureCodec(meta);
 
             if (err == OK) {
                 if (!strcmp("OMX.Nvidia.mpeg2v.decode", componentName)) {
-                    codec->mOnlySubmitOneBufferAtOneTime = true;
+                    codec->mFlags |= kOnlySubmitOneInputBufferAtOneTime;
                 }
 
                 return codec;
@@ -553,24 +562,11 @@
     return NULL;
 }
 
-status_t OMXCodec::configureCodec(const sp<MetaData> &meta, uint32_t flags) {
-    mIsMetaDataStoredInVideoBuffers = false;
-    if (flags & kStoreMetaDataInVideoBuffers) {
-        mIsMetaDataStoredInVideoBuffers = true;
-    }
+status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
+    LOGV("configureCodec protected=%d",
+         (mFlags & kEnableGrallocUsageProtected) ? 1 : 0);
 
-    mOnlySubmitOneBufferAtOneTime = false;
-    if (flags & kOnlySubmitOneInputBufferAtOneTime) {
-        mOnlySubmitOneBufferAtOneTime = true;
-    }
-
-    mEnableGrallocUsageProtected = false;
-    if (flags & kEnableGrallocUsageProtected) {
-        mEnableGrallocUsageProtected = true;
-    }
-    LOGV("configureCodec protected=%d", mEnableGrallocUsageProtected);
-
-    if (!(flags & kIgnoreCodecSpecificData)) {
+    if (!(mFlags & kIgnoreCodecSpecificData)) {
         uint32_t type;
         const void *data;
         size_t size;
@@ -745,7 +741,7 @@
 
     initOutputFormat(meta);
 
-    if ((flags & kClientNeedsFramebuffer)
+    if ((mFlags & kClientNeedsFramebuffer)
             && !strncmp(mComponentName, "OMX.SEC.", 8)) {
         OMX_INDEXTYPE index;
 
@@ -1299,13 +1295,6 @@
     h264type.nAllowedPictureTypes =
         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
 
-    h264type.nSliceHeaderSpacing = 0;
-    h264type.nBFrames = 0;   // No B frames support yet
-    h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
-    if (h264type.nPFrames == 0) {
-        h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
-    }
-
     // Check profile and level parameters
     CodecProfileLevel defaultProfileLevel, profileLevel;
     defaultProfileLevel.mProfile = h264type.eProfile;
@@ -1316,8 +1305,14 @@
     h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel);
 
     if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
+        h264type.nSliceHeaderSpacing = 0;
         h264type.bUseHadamard = OMX_TRUE;
         h264type.nRefFrames = 1;
+        h264type.nBFrames = 0;
+        h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+        if (h264type.nPFrames == 0) {
+            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
+        }
         h264type.nRefIdx10ActiveMinus1 = 0;
         h264type.nRefIdx11ActiveMinus1 = 0;
         h264type.bEntropyCodingCABAC = OMX_FALSE;
@@ -1468,7 +1463,8 @@
 }
 
 OMXCodec::OMXCodec(
-        const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
+        const sp<IOMX> &omx, IOMX::node_id node,
+        uint32_t quirks, uint32_t flags,
         bool isEncoder,
         const char *mime,
         const char *componentName,
@@ -1478,6 +1474,7 @@
       mOMXLivesLocally(omx->livesLocally(getpid())),
       mNode(node),
       mQuirks(quirks),
+      mFlags(flags),
       mIsEncoder(isEncoder),
       mMIME(strdup(mime)),
       mComponentName(strdup(componentName)),
@@ -1645,13 +1642,14 @@
         return allocateOutputBuffersFromNativeWindow();
     }
 
-    if (mEnableGrallocUsageProtected && portIndex == kPortIndexOutput) {
+    if ((mFlags & kEnableGrallocUsageProtected) && portIndex == kPortIndexOutput) {
         LOGE("protected output buffers must be stent to an ANativeWindow");
         return PERMISSION_DENIED;
     }
 
     status_t err = OK;
-    if (mIsMetaDataStoredInVideoBuffers && portIndex == kPortIndexInput) {
+    if ((mFlags & kStoreMetaDataInVideoBuffers)
+            && portIndex == kPortIndexInput) {
         err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
         if (err != OK) {
             LOGE("Storing meta data in video buffers is not supported");
@@ -1687,7 +1685,8 @@
 
         IOMX::buffer_id buffer;
         if (portIndex == kPortIndexInput
-                && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
+                && ((mQuirks & kRequiresAllocateBufferOnInputPorts)
+                    || (mFlags & kUseSecureInputBuffers))) {
             if (mOMXLivesLocally) {
                 mem.clear();
 
@@ -1748,6 +1747,31 @@
 
     // dumpPortStatus(portIndex);
 
+    if (portIndex == kPortIndexInput && (mFlags & kUseSecureInputBuffers)) {
+        Vector<MediaBuffer *> buffers;
+        for (size_t i = 0; i < def.nBufferCountActual; ++i) {
+            const BufferInfo &info = mPortBuffers[kPortIndexInput].itemAt(i);
+
+            MediaBuffer *mbuf = new MediaBuffer(info.mData, info.mSize);
+            buffers.push(mbuf);
+        }
+
+        status_t err = mSource->setBuffers(buffers);
+
+        if (err != OK) {
+            for (size_t i = 0; i < def.nBufferCountActual; ++i) {
+                buffers.editItemAt(i)->release();
+            }
+            buffers.clear();
+
+            CODEC_LOGE(
+                    "Codec requested to use secure input buffers but "
+                    "upstream source didn't support that.");
+
+            return err;
+        }
+    }
+
     return OK;
 }
 
@@ -1815,7 +1839,7 @@
         // XXX: Currently this error is logged, but not fatal.
         usage = 0;
     }
-    if (mEnableGrallocUsageProtected) {
+    if (mFlags & kEnableGrallocUsageProtected) {
         usage |= GRALLOC_USAGE_PROTECTED;
     }
 
@@ -1838,7 +1862,7 @@
         }
     }
 
-    LOGV("native_window_set_usage usage=0x%x", usage);
+    LOGV("native_window_set_usage usage=0x%lx", usage);
     err = native_window_set_usage(
             mNativeWindow.get(), usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
     if (err != 0) {
@@ -2067,7 +2091,12 @@
             } else if (mState != ERROR
                     && mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
                 CHECK_EQ((int)mPortStatus[kPortIndexInput], (int)ENABLED);
-                drainInputBuffer(&buffers->editItemAt(i));
+
+                if (mFlags & kUseSecureInputBuffers) {
+                    drainAnyInputBuffer();
+                } else {
+                    drainInputBuffer(&buffers->editItemAt(i));
+                }
             }
             break;
         }
@@ -2804,32 +2833,81 @@
 void OMXCodec::drainInputBuffers() {
     CHECK(mState == EXECUTING || mState == RECONFIGURING);
 
-    Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
-    for (size_t i = 0; i < buffers->size(); ++i) {
-        BufferInfo *info = &buffers->editItemAt(i);
-
-        if (info->mStatus != OWNED_BY_US) {
-            continue;
+    if (mFlags & kUseSecureInputBuffers) {
+        Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
+        for (size_t i = 0; i < buffers->size(); ++i) {
+            if (!drainAnyInputBuffer()
+                    || (mFlags & kOnlySubmitOneInputBufferAtOneTime)) {
+                break;
+            }
         }
+    } else {
+        Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
+        for (size_t i = 0; i < buffers->size(); ++i) {
+            BufferInfo *info = &buffers->editItemAt(i);
 
-        if (!drainInputBuffer(info)) {
-            break;
-        }
+            if (info->mStatus != OWNED_BY_US) {
+                continue;
+            }
 
-        if (mOnlySubmitOneBufferAtOneTime) {
-            break;
+            if (!drainInputBuffer(info)) {
+                break;
+            }
+
+            if (mFlags & kOnlySubmitOneInputBufferAtOneTime) {
+                break;
+            }
         }
     }
 }
 
+bool OMXCodec::drainAnyInputBuffer() {
+    return drainInputBuffer((BufferInfo *)NULL);
+}
+
+OMXCodec::BufferInfo *OMXCodec::findInputBufferByDataPointer(void *ptr) {
+    Vector<BufferInfo> *infos = &mPortBuffers[kPortIndexInput];
+    for (size_t i = 0; i < infos->size(); ++i) {
+        BufferInfo *info = &infos->editItemAt(i);
+
+        if (info->mData == ptr) {
+            CODEC_LOGV(
+                    "input buffer data ptr = %p, buffer_id = %p",
+                    ptr,
+                    info->mBuffer);
+
+            return info;
+        }
+    }
+
+    TRESPASS();
+}
+
+OMXCodec::BufferInfo *OMXCodec::findEmptyInputBuffer() {
+    Vector<BufferInfo> *infos = &mPortBuffers[kPortIndexInput];
+    for (size_t i = 0; i < infos->size(); ++i) {
+        BufferInfo *info = &infos->editItemAt(i);
+
+        if (info->mStatus == OWNED_BY_US) {
+            return info;
+        }
+    }
+
+    TRESPASS();
+}
+
 bool OMXCodec::drainInputBuffer(BufferInfo *info) {
-    CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
+    if (info != NULL) {
+        CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
+    }
 
     if (mSignalledEOS) {
         return false;
     }
 
     if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
+        CHECK(!(mFlags & kUseSecureInputBuffers));
+
         const CodecSpecificData *specific =
             mCodecSpecificData[mCodecSpecificDataIndex];
 
@@ -2925,6 +3003,11 @@
             break;
         }
 
+        if (mFlags & kUseSecureInputBuffers) {
+            info = findInputBufferByDataPointer(srcBuffer->data());
+            CHECK(info != NULL);
+        }
+
         size_t remainingBytes = info->mSize - offset;
 
         if (srcBuffer->range_length() > remainingBytes) {
@@ -2960,14 +3043,24 @@
             releaseBuffer = false;
             info->mMediaBuffer = srcBuffer;
         } else {
-            if (mIsMetaDataStoredInVideoBuffers) {
+            if (mFlags & kStoreMetaDataInVideoBuffers) {
                 releaseBuffer = false;
                 info->mMediaBuffer = srcBuffer;
             }
-            memcpy((uint8_t *)info->mData + offset,
-                    (const uint8_t *)srcBuffer->data()
-                        + srcBuffer->range_offset(),
-                    srcBuffer->range_length());
+
+            if (mFlags & kUseSecureInputBuffers) {
+                // Data in "info" is already provided at this time.
+
+                releaseBuffer = false;
+
+                CHECK(info->mMediaBuffer == NULL);
+                info->mMediaBuffer = srcBuffer;
+            } else {
+                memcpy((uint8_t *)info->mData + offset,
+                        (const uint8_t *)srcBuffer->data()
+                            + srcBuffer->range_offset(),
+                        srcBuffer->range_length());
+            }
         }
 
         int64_t lastBufferTimeUs;
@@ -3036,6 +3129,16 @@
                info->mBuffer, offset,
                timestampUs, timestampUs / 1E6);
 
+    if (info == NULL) {
+        CHECK(mFlags & kUseSecureInputBuffers);
+        CHECK(signalEOS);
+
+        // This is fishy, there's still a MediaBuffer corresponding to this
+        // info available to the source at this point even though we're going
+        // to use it to signal EOS to the codec.
+        info = findEmptyInputBuffer();
+    }
+
     err = mOMX->emptyBuffer(
             mNode, info->mBuffer, 0, offset,
             flags, timestampUs);
@@ -4216,6 +4319,10 @@
                             mNode, OMX_IndexConfigCommonOutputCrop,
                             &rect, sizeof(rect));
 
+                CODEC_LOGI(
+                        "video dimensions are %ld x %ld",
+                        video_def->nFrameWidth, video_def->nFrameHeight);
+
                 if (err == OK) {
                     CHECK_GE(rect.nLeft, 0);
                     CHECK_GE(rect.nTop, 0);
@@ -4230,6 +4337,10 @@
                             rect.nTop,
                             rect.nLeft + rect.nWidth - 1,
                             rect.nTop + rect.nHeight - 1);
+
+                    CODEC_LOGI(
+                            "Crop rect is %ld x %ld @ (%ld, %ld)",
+                            rect.nWidth, rect.nHeight, rect.nLeft, rect.nTop);
                 } else {
                     mOutputFormat->setRect(
                             kKeyCropRect,
@@ -4238,7 +4349,6 @@
                             video_def->nFrameHeight - 1);
                 }
             }
-
             break;
         }
 
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index f82ff32..89faff7 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -158,6 +158,7 @@
                 { "duration", METADATA_KEY_DURATION },
                 { "writer", METADATA_KEY_WRITER },
                 { "compilation", METADATA_KEY_COMPILATION },
+                { "isdrm", METADATA_KEY_IS_DRM },
             };
             static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
 
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index de3957b..778c0b5 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -530,6 +530,11 @@
             }
         }
     }
+
+    // To check whether the media file is drm-protected
+    if (mExtractor->getDrmFlag()) {
+        mMetaData.add(METADATA_KEY_IS_DRM, String8("1"));
+    }
 }
 
 }  // namespace android
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
index ed6846c..f4b3668 100644
--- a/media/libstagefright/chromium_http/support.cpp
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -41,6 +41,7 @@
 static Mutex gNetworkThreadLock;
 static base::Thread *gNetworkThread = NULL;
 static scoped_refptr<net::URLRequestContext> gReqContext;
+static scoped_ptr<net::NetworkChangeNotifier> gNetworkChangeNotifier;
 
 static void InitializeNetworkThreadIfNecessary() {
     Mutex::Autolock autoLock(gNetworkThreadLock);
@@ -52,6 +53,8 @@
 
         gReqContext = new SfRequestContext;
 
+        gNetworkChangeNotifier.reset(net::NetworkChangeNotifier::Create());
+
         net::AndroidNetworkLibrary::RegisterSharedInstance(
                 new SfNetworkLibrary);
     }
@@ -112,31 +115,31 @@
 
     mUserAgent = ua.c_str();
 
-    net_log_ = new SfNetLog;
+    set_net_log(new SfNetLog());
 
-    host_resolver_ =
+    set_host_resolver(
         net::CreateSystemHostResolver(
                 net::HostResolver::kDefaultParallelism,
                 NULL /* resolver_proc */,
-                net_log_);
+                net_log()));
 
-    ssl_config_service_ =
-        net::SSLConfigService::CreateSystemSSLConfigService();
+    set_ssl_config_service(
+        net::SSLConfigService::CreateSystemSSLConfigService());
 
-    proxy_service_ = net::ProxyService::CreateWithoutProxyResolver(
-            new net::ProxyConfigServiceAndroid, net_log_);
+    set_proxy_service(net::ProxyService::CreateWithoutProxyResolver(
+        new net::ProxyConfigServiceAndroid, net_log()));
 
-    http_transaction_factory_ = new net::HttpCache(
-            host_resolver_,
+    set_http_transaction_factory(new net::HttpCache(
+            host_resolver(),
             new net::CertVerifier(),
-            dnsrr_resolver_,
-            dns_cert_checker_.get(),
-            proxy_service_.get(),
-            ssl_config_service_.get(),
-            net::HttpAuthHandlerFactory::CreateDefault(host_resolver_),
-            network_delegate_,
-            net_log_,
-            NULL);  // backend_factory
+            dnsrr_resolver(),
+            dns_cert_checker(),
+            proxy_service(),
+            ssl_config_service(),
+            net::HttpAuthHandlerFactory::CreateDefault(host_resolver()),
+            network_delegate(),
+            net_log(),
+            NULL));  // backend_factory
 }
 
 const std::string &SfRequestContext::GetUserAgent(const GURL &url) const {
diff --git a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
index e3292e6..0096760 100644
--- a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
+++ b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
@@ -475,7 +475,9 @@
         }
         status_t err = mSource->read(&mInputBuffer, options);
         if (err != OK) {
-            LOGE("Failed to read input video frame: %d", err);
+            if (err != ERROR_END_OF_STREAM) {
+                LOGE("Failed to read input video frame: %d", err);
+            }
             outputBuffer->release();
             return err;
         }
diff --git a/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
index 15ed219..d7249c1 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
@@ -398,10 +398,13 @@
     }
 
     // Ready for accepting an input video frame
-    if (OK != mSource->read(&mInputBuffer, options)) {
-        LOGE("Failed to read from data source");
+    status_t err = mSource->read(&mInputBuffer, options);
+    if (OK != err) {
+        if (err != ERROR_END_OF_STREAM) {
+            LOGE("Failed to read from data source");
+        }
         outputBuffer->release();
-        return UNKNOWN_ERROR;
+        return err;
     }
 
     if (mInputBuffer->size() - ((mVideoWidth * mVideoHeight * 3) >> 1) != 0) {
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
index 830d2e0..ec7bd1c 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
@@ -139,7 +139,8 @@
 }
 
 status_t SoftAVC::initDecoder() {
-    if (H264SwDecInit(&mHandle, 1) == H264SWDEC_OK) {
+    // Force decoder to output buffers in display order.
+    if (H264SwDecInit(&mHandle, 0) == H264SWDEC_OK) {
         return OK;
     }
     return UNKNOWN_ERROR;
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
index 3439efd..1cc85e8 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
@@ -52,7 +52,7 @@
         kInputPortIndex   = 0,
         kOutputPortIndex  = 1,
         kNumInputBuffers  = 8,
-        kNumOutputBuffers = 16,
+        kNumOutputBuffers = 2,
     };
 
     enum EOSStatus {
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index fd933cc..5cc3f78 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ColorConverter"
+#include <utils/Log.h>
+
 #include <media/stagefright/ColorConverter.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaErrors.h>
@@ -424,61 +428,30 @@
 
 status_t ColorConverter::convertTIYUV420PackedSemiPlanar(
         const BitmapParams &src, const BitmapParams &dst) {
-
-/*
-The TIYUV420PackedSemiPlanar format is same as YUV420PackedSemiPlanar but with
-additional padding as shown in the diagram below. The padded width and padded
-height is different for different compression formats and it is read from the
-codec. In this color conversion routine, the padded resolution is obtained from
-src bitmap.
-
- ------------------------------------
-|                                    |
-|                                    |
-|      -------------------------     |
-|     |                         |    |
-|     |                         |    |
-|     |          Y DATA         |    |
-|     |                         |    |
-|     |                         |    |
-|     |                         |    |
-|      -------------------------     |
-|                                    |
-|      ------------                  |
-|     |            |                 |
-|     |            |                 |
-|     |  UV DATA   |                 |
-|     |            |                 |
-|     |            |                 |
-|     |            |                 |
-|      ------------                  |
-|                                    |
-|                                    |
- ------------------------------------
-*/
-
-    LOGV("src.mCropLeft = %d src.mCropTop =%d src.mWidth = %d src.mHeight = %d"
-        " dst.mWidth = %d dst.mHeight = %d", src.mCropLeft , src.mCropTop,
-        src.mWidth, src.mHeight, dst.mWidth, dst.mHeight);
-
-    size_t offset = (src.mWidth * src.mCropTop) + src.mCropLeft;
-
     uint8_t *kAdjustedClip = initClip();
 
-    uint32_t *dst_ptr = (uint32_t *)dst.mBits;
+    if (!((dst.mWidth & 3) == 0
+            && (src.mCropLeft & 1) == 0
+            && src.cropWidth() == dst.cropWidth()
+            && src.cropHeight() == dst.cropHeight())) {
+        return ERROR_UNSUPPORTED;
+    }
+
+    uint32_t *dst_ptr = (uint32_t *)dst.mBits
+        + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2;
+
     const uint8_t *src_y = (const uint8_t *)src.mBits;
-    const uint8_t *src_u = (const uint8_t *)(src_y-offset) + (src.mWidth * src.mHeight);
-    src_u += ( ( src.mWidth * (src.mCropTop/2) ) + src.mCropLeft );
-    const uint8_t *src_v = src_u + 1;
 
-    for (size_t y = 0; y < dst.mHeight; ++y) {
-        for (size_t x = 0; x < dst.mWidth; x += 2) {
+    const uint8_t *src_u =
+        (const uint8_t *)src_y + src.mWidth * (src.mHeight - src.mCropTop / 2);
 
-            signed y1 = (signed)src_y[x] - 16;    //Y pixel
-            signed y2 = (signed)src_y[x + 1] - 16; //2nd Y pixel
+    for (size_t y = 0; y < src.cropHeight(); ++y) {
+        for (size_t x = 0; x < src.cropWidth(); x += 2) {
+            signed y1 = (signed)src_y[x] - 16;
+            signed y2 = (signed)src_y[x + 1] - 16;
 
-            signed u = (signed)src_u[x & ~1] - 128;   //U component
-            signed v = (signed)src_u[(x & ~1) + 1] - 128; //V component
+            signed u = (signed)src_u[x & ~1] - 128;
+            signed v = (signed)src_u[(x & ~1) + 1] - 128;
 
             signed u_b = u * 517;
             signed u_g = -u * 100;
@@ -502,19 +475,21 @@
 
             uint32_t rgb2 =
                 ((kAdjustedClip[r2] >> 3) << 11)
-                | ((kAdjustedClip[g1] >> 2) << 5)
-                | (kAdjustedClip[b1] >> 3);
+                | ((kAdjustedClip[g2] >> 2) << 5)
+                | (kAdjustedClip[b2] >> 3);
 
             dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
         }
 
-        src_y += src.mWidth; //increment Y-pixel line
-        if (y&1) {
-          src_u += src.mWidth; //increment U-V line
+        src_y += src.mWidth;
+
+        if (y & 1) {
+            src_u += src.mWidth;
         }
 
         dst_ptr += dst.mWidth / 2;
     }
+
     return OK;
 }
 
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index a4e8ee4..a4ca32d 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -50,6 +50,9 @@
         mCropBottom = mHeight - 1;
     }
 
+    mCropWidth = mCropRight - mCropLeft + 1;
+    mCropHeight = mCropBottom - mCropTop + 1;
+
     int32_t rotationDegrees;
     if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
         rotationDegrees = 0;
@@ -60,17 +63,18 @@
 
     switch (mColorFormat) {
         case OMX_COLOR_FormatYUV420Planar:
+        case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
         {
             halFormat = HAL_PIXEL_FORMAT_YV12;
-            bufWidth = (mWidth + 1) & ~1;
-            bufHeight = (mHeight + 1) & ~1;
+            bufWidth = (mCropWidth + 1) & ~1;
+            bufHeight = (mCropHeight + 1) & ~1;
             break;
         }
 
         default:
             halFormat = HAL_PIXEL_FORMAT_RGB_565;
-            bufWidth = mWidth;
-            bufHeight = mHeight;
+            bufWidth = mCropWidth;
+            bufHeight = mCropHeight;
 
             mConverter = new ColorConverter(
                     mColorFormat, OMX_COLOR_Format16bitRGB565);
@@ -79,8 +83,8 @@
     }
 
     CHECK(mNativeWindow != NULL);
-    CHECK(mWidth > 0);
-    CHECK(mHeight > 0);
+    CHECK(mCropWidth > 0);
+    CHECK(mCropHeight > 0);
     CHECK(mConverter == NULL || mConverter->isValid());
 
     CHECK_EQ(0,
@@ -109,14 +113,6 @@
         CHECK_EQ(0, native_window_set_buffers_transform(
                     mNativeWindow.get(), transform));
     }
-
-    android_native_rect_t crop;
-    crop.left = mCropLeft;
-    crop.top = mCropTop;
-    crop.right = mCropRight + 1;
-    crop.bottom = mCropBottom + 1;
-
-    CHECK_EQ(0, native_window_set_crop(mNativeWindow.get(), &crop));
 }
 
 SoftwareRenderer::~SoftwareRenderer() {
@@ -142,7 +138,7 @@
 
     GraphicBufferMapper &mapper = GraphicBufferMapper::get();
 
-    Rect bounds(mWidth, mHeight);
+    Rect bounds(mCropWidth, mCropHeight);
 
     void *dst;
     CHECK_EQ(0, mapper.lock(
@@ -152,13 +148,11 @@
         mConverter->convert(
                 data,
                 mWidth, mHeight,
-                0, 0, mWidth - 1, mHeight - 1,
+                mCropLeft, mCropTop, mCropRight, mCropBottom,
                 dst,
                 buf->stride, buf->height,
-                0, 0, mWidth - 1, mHeight - 1);
-    } else {
-        CHECK_EQ(mColorFormat, OMX_COLOR_FormatYUV420Planar);
-
+                0, 0, mCropWidth - 1, mCropHeight - 1);
+    } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar) {
         const uint8_t *src_y = (const uint8_t *)data;
         const uint8_t *src_u = (const uint8_t *)data + mWidth * mHeight;
         const uint8_t *src_v = src_u + (mWidth / 2 * mHeight / 2);
@@ -170,22 +164,57 @@
         uint8_t *dst_v = dst_y + dst_y_size;
         uint8_t *dst_u = dst_v + dst_c_size;
 
-        for (int y = 0; y < mHeight; ++y) {
-            memcpy(dst_y, src_y, mWidth);
+        for (int y = 0; y < mCropHeight; ++y) {
+            memcpy(dst_y, src_y, mCropWidth);
 
             src_y += mWidth;
             dst_y += buf->stride;
         }
 
-        for (int y = 0; y < (mHeight + 1) / 2; ++y) {
-            memcpy(dst_u, src_u, (mWidth + 1) / 2);
-            memcpy(dst_v, src_v, (mWidth + 1) / 2);
+        for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
+            memcpy(dst_u, src_u, (mCropWidth + 1) / 2);
+            memcpy(dst_v, src_v, (mCropWidth + 1) / 2);
 
             src_u += mWidth / 2;
             src_v += mWidth / 2;
             dst_u += dst_c_stride;
             dst_v += dst_c_stride;
         }
+    } else {
+        CHECK_EQ(mColorFormat, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar);
+
+        const uint8_t *src_y =
+            (const uint8_t *)data;
+
+        const uint8_t *src_uv =
+            (const uint8_t *)data + mWidth * (mHeight - mCropTop / 2);
+
+        uint8_t *dst_y = (uint8_t *)dst;
+
+        size_t dst_y_size = buf->stride * buf->height;
+        size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
+        size_t dst_c_size = dst_c_stride * buf->height / 2;
+        uint8_t *dst_v = dst_y + dst_y_size;
+        uint8_t *dst_u = dst_v + dst_c_size;
+
+        for (int y = 0; y < mCropHeight; ++y) {
+            memcpy(dst_y, src_y, mCropWidth);
+
+            src_y += mWidth;
+            dst_y += buf->stride;
+        }
+
+        for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
+            size_t tmp = (mCropWidth + 1) / 2;
+            for (size_t x = 0; x < tmp; ++x) {
+                dst_u[x] = src_uv[2 * x];
+                dst_v[x] = src_uv[2 * x + 1];
+            }
+
+            src_uv += mWidth;
+            dst_u += dst_c_stride;
+            dst_v += dst_c_stride;
+        }
     }
 
     CHECK_EQ(0, mapper.unlock(buf->handle));
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 165683e..8ecc17c 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -41,8 +41,10 @@
 
 const int64_t LiveSession::kMaxPlaylistAgeUs = 15000000ll;
 
-LiveSession::LiveSession(uint32_t flags)
+LiveSession::LiveSession(uint32_t flags, bool uidValid, uid_t uid)
     : mFlags(flags),
+      mUIDValid(uidValid),
+      mUID(uid),
       mDataSource(new LiveDataSource),
       mHTTPDataSource(
               HTTPBase::Create(
@@ -58,6 +60,9 @@
       mSeekDone(false),
       mDisconnectPending(false),
       mMonitorQueueGeneration(0) {
+    if (mUIDValid) {
+        mHTTPDataSource->setUID(mUID);
+    }
 }
 
 LiveSession::~LiveSession() {
@@ -408,13 +413,20 @@
         if (firstTime) {
             Mutex::Autolock autoLock(mLock);
 
-            int32_t targetDuration;
-            if (!mPlaylist->isComplete()
-                    || !mPlaylist->meta()->findInt32(
-                    "target-duration", &targetDuration)) {
+            if (!mPlaylist->isComplete()) {
                 mDurationUs = -1;
             } else {
-                mDurationUs = 1000000ll * targetDuration * mPlaylist->size();
+                mDurationUs = 0;
+                for (size_t i = 0; i < mPlaylist->size(); ++i) {
+                    sp<AMessage> itemMeta;
+                    CHECK(mPlaylist->itemAt(
+                                i, NULL /* uri */, &itemMeta));
+
+                    int64_t itemDurationUs;
+                    CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
+
+                    mDurationUs += itemDurationUs;
+                }
             }
         }
 
@@ -431,14 +443,26 @@
     bool bandwidthChanged = false;
 
     if (mSeekTimeUs >= 0) {
-        int32_t targetDuration;
-        if (mPlaylist->isComplete() &&
-                mPlaylist->meta()->findInt32(
-                    "target-duration", &targetDuration)) {
-            int64_t seekTimeSecs = (mSeekTimeUs + 500000ll) / 1000000ll;
-            int64_t index = seekTimeSecs / targetDuration;
+        if (mPlaylist->isComplete()) {
+            size_t index = 0;
+            int64_t segmentStartUs = 0;
+            while (index < mPlaylist->size()) {
+                sp<AMessage> itemMeta;
+                CHECK(mPlaylist->itemAt(
+                            index, NULL /* uri */, &itemMeta));
 
-            if (index >= 0 && index < mPlaylist->size()) {
+                int64_t itemDurationUs;
+                CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
+
+                if (mSeekTimeUs < segmentStartUs + itemDurationUs) {
+                    break;
+                }
+
+                segmentStartUs += itemDurationUs;
+                ++index;
+            }
+
+            if (index < mPlaylist->size()) {
                 int32_t newSeqNumber = firstSeqNumberInPlaylist + index;
 
                 if (newSeqNumber != mSeqNumber) {
@@ -652,6 +676,10 @@
                     ? HTTPBase::kFlagIncognito
                     : 0);
 
+        if (mUIDValid) {
+            keySource->setUID(mUID);
+        }
+
         status_t err = keySource->connect(keyURI.c_str());
 
         if (err == OK) {
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index 765f795..123fbf8 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -64,14 +64,21 @@
 }
 
 bool M3UParser::itemAt(size_t index, AString *uri, sp<AMessage> *meta) {
-    uri->clear();
-    if (meta) { *meta = NULL; }
+    if (uri) {
+        uri->clear();
+    }
+
+    if (meta) {
+        *meta = NULL;
+    }
 
     if (index >= mItems.size()) {
         return false;
     }
 
-    *uri = mItems.itemAt(index).mURI;
+    if (uri) {
+        *uri = mItems.itemAt(index).mURI;
+    }
 
     if (meta) {
         *meta = mItems.itemAt(index).mMeta;
diff --git a/media/libstagefright/include/ARTSPController.h b/media/libstagefright/include/ARTSPController.h
index ce7ffe5..2bd5be6 100644
--- a/media/libstagefright/include/ARTSPController.h
+++ b/media/libstagefright/include/ARTSPController.h
@@ -30,6 +30,8 @@
 struct ARTSPController : public MediaExtractor {
     ARTSPController(const sp<ALooper> &looper);
 
+    void setUID(uid_t uid);
+
     status_t connect(const char *url);
     void disconnect();
 
@@ -80,6 +82,9 @@
     sp<MyHandler> mHandler;
     sp<AHandlerReflector<ARTSPController> > mReflector;
 
+    bool mUIDValid;
+    uid_t mUID;
+
     void (*mSeekDoneCb)(void *);
     void *mSeekDoneCookie;
     int64_t mLastSeekCompletedTimeUs;
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index f6df380..e069b4d 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -62,6 +62,7 @@
     ~AwesomePlayer();
 
     void setListener(const wp<MediaPlayerBase> &listener);
+    void setUID(uid_t uid);
 
     status_t setDataSource(
             const char *uri,
@@ -150,6 +151,8 @@
     TimedEventQueue mQueue;
     bool mQueueStarted;
     wp<MediaPlayerBase> mListener;
+    bool mUIDValid;
+    uid_t mUID;
 
     sp<Surface> mSurface;
     sp<ANativeWindow> mNativeWindow;
diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h
index 3a7fbb6..2e25dd9 100644
--- a/media/libstagefright/include/HTTPBase.h
+++ b/media/libstagefright/include/HTTPBase.h
@@ -48,13 +48,15 @@
 
     virtual status_t setBandwidthStatCollectFreq(int32_t freqMs);
 
+    void setUID(uid_t uid);
+    bool getUID(uid_t *uid) const;
+
     static sp<HTTPBase> Create(uint32_t flags = 0);
 
 protected:
     void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
 
 private:
-
     struct BandwidthEntry {
         int64_t mDelayUs;
         size_t mNumBytes;
@@ -76,6 +78,8 @@
     int32_t mPrevEstimatedBandWidthKbps;
     int32_t mBandWidthCollectFreqMs;
 
+    bool mUIDValid;
+    uid_t mUID;
 
     DISALLOW_EVIL_CONSTRUCTORS(HTTPBase);
 };
diff --git a/media/libstagefright/include/HTTPStream.h b/media/libstagefright/include/HTTPStream.h
index 09e6a5f..88ba9d6 100644
--- a/media/libstagefright/include/HTTPStream.h
+++ b/media/libstagefright/include/HTTPStream.h
@@ -32,6 +32,8 @@
     HTTPStream();
     ~HTTPStream();
 
+    void setUID(uid_t uid);
+
     status_t connect(const char *server, int port = -1, bool https = false);
     status_t disconnect();
 
@@ -58,6 +60,8 @@
     // _excluding_ the termianting CRLF.
     status_t receive_line(char *line, size_t size);
 
+    static void RegisterSocketUser(int s, uid_t uid);
+
 private:
     enum State {
         READY,
@@ -67,6 +71,10 @@
 
     State mState;
     Mutex mLock;
+
+    bool mUIDValid;
+    uid_t mUID;
+
     int mSocket;
 
     KeyedVector<AString, AString> mHeaders;
diff --git a/media/libstagefright/include/LiveSession.h b/media/libstagefright/include/LiveSession.h
index 99abe64..188ef5e 100644
--- a/media/libstagefright/include/LiveSession.h
+++ b/media/libstagefright/include/LiveSession.h
@@ -35,7 +35,7 @@
         // Don't log any URLs.
         kFlagIncognito = 1,
     };
-    LiveSession(uint32_t flags = 0);
+    LiveSession(uint32_t flags = 0, bool uidValid = false, uid_t uid = 0);
 
     sp<DataSource> getDataSource();
 
@@ -77,6 +77,8 @@
     };
 
     uint32_t mFlags;
+    bool mUIDValid;
+    uid_t mUID;
 
     sp<LiveDataSource> mDataSource;
 
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 3bd4c7e..eae62c6 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -40,7 +40,6 @@
     virtual sp<MetaData> getMetaData();
 
     // for DRM
-    virtual void setDrmFlag(bool flag);
     virtual char* getDrmTrackInfo(size_t trackID, int *len);
 
 protected:
diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h
index 78037b97..8f2ea95 100644
--- a/media/libstagefright/include/SoftwareRenderer.h
+++ b/media/libstagefright/include/SoftwareRenderer.h
@@ -47,6 +47,7 @@
     sp<ANativeWindow> mNativeWindow;
     int32_t mWidth, mHeight;
     int32_t mCropLeft, mCropTop, mCropRight, mCropBottom;
+    int32_t mCropWidth, mCropHeight;
 
     SoftwareRenderer(const SoftwareRenderer &);
     SoftwareRenderer &operator=(const SoftwareRenderer &);
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index a404f1f..d4354db 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -485,24 +485,20 @@
     };
     static const MimeToURL kMimeToURL[] = {
         { "video/avc",
-          "file:///sdcard/media_api/video/H264_AAC.3gp" },
-        { "video/mp4v-es", "file:///sdcard/media_api/video/gingerkids.MP4" },
+          "file:///sdcard/media_api/video/H264_500_AAC_128.3gp" },
+        { "video/mp4v-es", "file:///sdcard/media_api/video/MPEG4_320_AAC_64.mp4" },
         { "video/3gpp",
           "file:///sdcard/media_api/video/H263_500_AMRNB_12.3gp" },
         { "audio/3gpp",
           "file:///sdcard/media_api/video/H263_500_AMRNB_12.3gp" },
-        { "audio/amr-wb",
-          "file:///sdcard/media_api/music/"
-          "AI_AMR-WB_12.65kbps(13kbps)_16khz_mono_NMC.awb" },
+        { "audio/amr-wb", NULL },
         { "audio/mp4a-latm",
-          "file:///sdcard/media_api/video/H264_AAC.3gp" },
+          "file:///sdcard/media_api/video/H263_56_AAC_24.3gp" },
         { "audio/mpeg",
-          "file:///sdcard/media_api/music/MP3CBR.mp3" },
-        { "audio/vorbis",
-          "file:///sdcard/media_api/metaDataTestMedias/OGG/"
-          "When You Say Nothing At All.ogg" },
+          "file:///sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_CBR.mp3" },
+        { "audio/vorbis", NULL },
         { "video/x-vnd.on2.vp8",
-          "file:///sdcard/media_api/webm/big-buck-bunny_trailer.webm" },
+          "file:///sdcard/media_api/video/big-buck-bunny_trailer.webm" },
         { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "file:///sdcard/M1F1-Alaw-AFsp.wav" },
         { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
           "file:///sdcard/M1F1-mulaw-AFsp.wav" },
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index c4e0cdc..072d6b2 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -34,13 +34,17 @@
 #include <openssl/md5.h>
 #include <sys/socket.h>
 
+#include "HTTPStream.h"
+
 namespace android {
 
 // static
 const int64_t ARTSPConnection::kSelectTimeoutUs = 1000ll;
 
-ARTSPConnection::ARTSPConnection()
-    : mState(DISCONNECTED),
+ARTSPConnection::ARTSPConnection(bool uidValid, uid_t uid)
+    : mUIDValid(uidValid),
+      mUID(uid),
+      mState(DISCONNECTED),
       mAuthType(NONE),
       mSocket(-1),
       mConnectionID(0),
@@ -246,6 +250,10 @@
 
     mSocket = socket(AF_INET, SOCK_STREAM, 0);
 
+    if (mUIDValid) {
+        HTTPStream::RegisterSocketUser(mSocket, mUID);
+    }
+
     MakeSocketBlocking(mSocket, false);
 
     struct sockaddr_in remote;
diff --git a/media/libstagefright/rtsp/ARTSPConnection.h b/media/libstagefright/rtsp/ARTSPConnection.h
index ac2e3ae..5cb84fd 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.h
+++ b/media/libstagefright/rtsp/ARTSPConnection.h
@@ -33,7 +33,7 @@
 };
 
 struct ARTSPConnection : public AHandler {
-    ARTSPConnection();
+    ARTSPConnection(bool uidValid = false, uid_t uid = 0);
 
     void connect(const char *url, const sp<AMessage> &reply);
     void disconnect(const sp<AMessage> &reply);
@@ -74,6 +74,8 @@
 
     static const int64_t kSelectTimeoutUs;
 
+    bool mUIDValid;
+    uid_t mUID;
     State mState;
     AString mUser, mPass;
     AuthType mAuthType;
diff --git a/media/libstagefright/rtsp/ARTSPController.cpp b/media/libstagefright/rtsp/ARTSPController.cpp
index 1328d2e..2ebae7e 100644
--- a/media/libstagefright/rtsp/ARTSPController.cpp
+++ b/media/libstagefright/rtsp/ARTSPController.cpp
@@ -28,6 +28,7 @@
 ARTSPController::ARTSPController(const sp<ALooper> &looper)
     : mState(DISCONNECTED),
       mLooper(looper),
+      mUIDValid(false),
       mSeekDoneCb(NULL),
       mSeekDoneCookie(NULL),
       mLastSeekCompletedTimeUs(-1) {
@@ -40,6 +41,11 @@
     mLooper->unregisterHandler(mReflector->id());
 }
 
+void ARTSPController::setUID(uid_t uid) {
+    mUIDValid = true;
+    mUID = uid;
+}
+
 status_t ARTSPController::connect(const char *url) {
     Mutex::Autolock autoLock(mLock);
 
@@ -49,7 +55,7 @@
 
     sp<AMessage> msg = new AMessage(kWhatConnectDone, mReflector->id());
 
-    mHandler = new MyHandler(url, mLooper);
+    mHandler = new MyHandler(url, mLooper, mUIDValid, mUID);
 
     mState = CONNECTING;
 
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index fd0505e..f03f7a2 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -301,9 +301,6 @@
 // static
 bool ASessionDescription::parseNTPRange(
         const char *s, float *npt1, float *npt2) {
-    *npt1 = 0.0f;
-    *npt2 = 0.0f;
-
     if (s[0] == '-') {
         return false;  // no start time available.
     }
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index f89f8e2..3188959 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -40,6 +40,8 @@
 #include <sys/socket.h>
 #include <netdb.h>
 
+#include "HTTPStream.h"
+
 // If no access units are received within 5 secs, assume that the rtp
 // stream has ended and signal end of stream.
 static int64_t kAccessUnitTimeoutUs = 5000000ll;
@@ -92,10 +94,14 @@
 }
 
 struct MyHandler : public AHandler {
-    MyHandler(const char *url, const sp<ALooper> &looper)
-        : mLooper(looper),
+    MyHandler(
+            const char *url, const sp<ALooper> &looper,
+            bool uidValid = false, uid_t uid = 0)
+        : mUIDValid(uidValid),
+          mUID(uid),
+          mLooper(looper),
           mNetLooper(new ALooper),
-          mConn(new ARTSPConnection),
+          mConn(new ARTSPConnection(mUIDValid, mUID)),
           mRTPConn(new ARTPConnection),
           mOriginalSessionURL(url),
           mSessionURL(url),
@@ -995,12 +1001,10 @@
         AString val;
         CHECK(GetAttribute(range.c_str(), "npt", &val));
 
-        bool seekable = true;
-
         float npt1, npt2;
         if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) {
             // This is a live stream and therefore not seekable.
-            seekable = false;
+            return;
         }
 
         i = response->mHeaders.indexOfKey("rtp-info");
@@ -1046,7 +1050,7 @@
             ++n;
         }
 
-        mSeekable = seekable;
+        mSeekable = true;
     }
 
     sp<APacketSource> getPacketSource(size_t index) {
@@ -1080,6 +1084,8 @@
         List<sp<ABuffer> > mPackets;
     };
 
+    bool mUIDValid;
+    uid_t mUID;
     sp<ALooper> mLooper;
     sp<ALooper> mNetLooper;
     sp<ARTSPConnection> mConn;
@@ -1174,6 +1180,11 @@
             ARTPConnection::MakePortPair(
                     &info->mRTPSocket, &info->mRTCPSocket, &rtpPort);
 
+            if (mUIDValid) {
+                HTTPStream::RegisterSocketUser(info->mRTPSocket, mUID);
+                HTTPStream::RegisterSocketUser(info->mRTCPSocket, mUID);
+            }
+
             request.append("Transport: RTP/AVP/UDP;unicast;client_port=");
             request.append(rtpPort);
             request.append("-");
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index bc04e8c..9085f10 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -871,6 +871,14 @@
     // check space first
     if (mSendObjectFileSize > storage->getFreeSpace())
         return MTP_RESPONSE_STORAGE_FULL;
+    uint64_t maxFileSize = storage->getMaxFileSize();
+    // check storage max file size
+    if (maxFileSize != 0) {
+        // if mSendObjectFileSize is 0xFFFFFFFF, then all we know is the file size
+        // is >= 0xFFFFFFFF
+        if (mSendObjectFileSize > maxFileSize || mSendObjectFileSize == 0xFFFFFFFF)
+            return MTP_RESPONSE_OBJECT_TOO_LARGE;
+    }
 
 LOGD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID);
     MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path,
diff --git a/media/mtp/MtpStorage.cpp b/media/mtp/MtpStorage.cpp
index fef8066..941e303 100644
--- a/media/mtp/MtpStorage.cpp
+++ b/media/mtp/MtpStorage.cpp
@@ -33,11 +33,13 @@
 namespace android {
 
 MtpStorage::MtpStorage(MtpStorageID id, const char* filePath,
-        const char* description, uint64_t reserveSpace, bool removable)
+        const char* description, uint64_t reserveSpace,
+        bool removable, uint64_t maxFileSize)
     :   mStorageID(id),
         mFilePath(filePath),
         mDescription(description),
         mMaxCapacity(0),
+        mMaxFileSize(maxFileSize),
         mReserveSpace(reserveSpace),
         mRemovable(removable)
 {
diff --git a/media/mtp/MtpStorage.h b/media/mtp/MtpStorage.h
index 3e4f40d..e5a2e57 100644
--- a/media/mtp/MtpStorage.h
+++ b/media/mtp/MtpStorage.h
@@ -31,6 +31,7 @@
     MtpString               mFilePath;
     MtpString               mDescription;
     uint64_t                mMaxCapacity;
+    uint64_t                mMaxFileSize;
     // amount of free space to leave unallocated
     uint64_t                mReserveSpace;
     bool                    mRemovable;
@@ -38,7 +39,7 @@
 public:
                             MtpStorage(MtpStorageID id, const char* filePath,
                                     const char* description, uint64_t reserveSpace,
-                                    bool removable);
+                                    bool removable, uint64_t maxFileSize);
     virtual                 ~MtpStorage();
 
     inline MtpStorageID     getStorageID() const { return mStorageID; }
@@ -50,6 +51,7 @@
     const char*             getDescription() const;
     inline const char*      getPath() const { return (const char *)mFilePath; }
     inline bool             isRemovable() const { return mRemovable; }
+    inline uint64_t         getMaxFileSize() const { return mMaxFileSize; }
 };
 
 }; // namespace android
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
index 0dadaa5..afe2001 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
@@ -1334,10 +1334,20 @@
     // TODO : remove TC_API_035
     @LargeTest
     public void testEffectKenBurn() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
+        // Test ken burn effect using a JPEG file.
+        testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.jpg",
+         "mediaImageItem1");
+
+        // Test ken burn effect using a PNG file
+        testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.png",
+         "mediaImageItem2");
+    }
+
+    private void testEffectKenBurn(final String imageItemFileName,
+     final String MediaId) throws Exception {
         final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
         final MediaImageItem mediaImageItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
+            mVideoEditorHelper.createMediaItem(mVideoEditor, MediaId,
             imageItemFileName, 5000, imageItemRenderingMode);
         mVideoEditor.addMediaItem(mediaImageItem);
 
@@ -1350,11 +1360,14 @@
         final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
             mediaImageItem, "KBOnM2", startRect, endRect, 500, 3000);
 
-        assertNotNull("EffectKenBurns", kbEffectOnMediaItem);
+        assertNotNull("EffectKenBurns: " + imageItemFileName,
+            kbEffectOnMediaItem);
+
         mediaImageItem.addEffect(kbEffectOnMediaItem);
-        assertEquals("KenBurn Start Rect", startRect,
+        assertEquals("KenBurn Start Rect: " + imageItemFileName, startRect,
             kbEffectOnMediaItem.getStartRect());
-        assertEquals("KenBurn End Rect", endRect,
+
+        assertEquals("KenBurn End Rect: " + imageItemFileName, endRect,
             kbEffectOnMediaItem.getEndRect());
     }
 
diff --git a/native/include/android/input.h b/native/include/android/input.h
index 26cac50..0d8ea28 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -404,7 +404,6 @@
     AMOTION_EVENT_BUTTON_TERTIARY = 1 << 2,
     AMOTION_EVENT_BUTTON_BACK = 1 << 3,
     AMOTION_EVENT_BUTTON_FORWARD = 1 << 4,
-    AMOTION_EVENT_BUTTON_ERASER = 1 << 5,
 };
 
 /*
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
index eb2f6f8..63c2de2 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
@@ -55,6 +55,64 @@
      */
     public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
 
+    /**
+     * Broadcast action: A filtered APDU was received.
+     *
+     * <p>This happens when an APDU of interest was matched by the Nfc adapter,
+     * for instance as the result of matching an externally-configured filter.
+     *
+     * <p>The filter configuration mechanism is not currently defined.
+     *
+     * <p>Always contains the extra field {@link EXTRA_APDU_BYTES}.
+     *
+     * @hide
+     */
+    public static final String ACTION_APDU_RECEIVED =
+        "com.android.nfc_extras.action.APDU_RECEIVED";
+
+    /**
+     * Mandatory byte array extra field in {@link #ACTION_APDU_RECEIVED}.
+     *
+     * <p>Contains the bytes of the received APDU.
+     *
+     * @hide
+     */
+    public static final String EXTRA_APDU_BYTES =
+        "com.android.nfc_extras.extra.APDU_BYTES";
+
+    /**
+     * Broadcast action: An EMV card removal event was detected.
+     *
+     * @hide
+     */
+    public static final String ACTION_EMV_CARD_REMOVAL =
+        "com.android.nfc_extras.action.EMV_CARD_REMOVAL";
+
+    /**
+     * Broadcast action: An adapter implementing MIFARE Classic via card
+     * emulation detected that a block has been accessed.
+     *
+     * <p>This may only be issued for the first block that the reader
+     * authenticates to.
+     *
+     * <p>May contain the extra field {@link #EXTRA_MIFARE_BLOCK}.
+     *
+     * @hide
+     */
+    public static final String ACTION_MIFARE_ACCESS_DETECTED =
+        "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED";
+
+    /**
+     * Optional integer extra field in {@link #ACTION_MIFARE_ACCESS_DETECTED}.
+     *
+     * <p>Provides the block number being accessed.  If not set, the block
+     * number being accessed is unknown.
+     *
+     * @hide
+     */
+    public static final String EXTRA_MIFARE_BLOCK =
+        "com.android.nfc_extras.extra.MIFARE_BLOCK";
+
     NfcExecutionEnvironment(NfcAdapterExtras extras) {
         mExtras = extras;
     }
diff --git a/opengl/tests/EGLTest/Android.mk b/opengl/tests/EGLTest/Android.mk
new file mode 100644
index 0000000..ab5f4bd
--- /dev/null
+++ b/opengl/tests/EGLTest/Android.mk
@@ -0,0 +1,41 @@
+# Build the unit tests.
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_MODULE := EGL_test
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+    EGL_test.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+	libEGL \
+	libcutils \
+	libstlport \
+	libutils \
+
+LOCAL_STATIC_LIBRARIES := \
+	libgtest \
+	libgtest_main \
+
+LOCAL_C_INCLUDES := \
+    bionic \
+    bionic/libstdc++/include \
+    external/gtest/include \
+    external/stlport/stlport \
+
+include $(BUILD_EXECUTABLE)
+
+endif
+
+# Include subdirectory makefiles
+# ============================================================
+
+# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
+# team really wants is to build the stuff defined by this makefile.
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
new file mode 100644
index 0000000..337ad33
--- /dev/null
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <utils/String8.h>
+
+#include <EGL/egl.h>
+
+namespace android {
+
+class EGLTest : public ::testing::Test {
+protected:
+    EGLDisplay mEglDisplay;
+
+protected:
+    EGLTest() :
+            mEglDisplay(EGL_NO_DISPLAY) {
+    }
+
+    virtual void SetUp() {
+        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        EGLint majorVersion;
+        EGLint minorVersion;
+        EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        RecordProperty("EglVersionMajor", majorVersion);
+        RecordProperty("EglVersionMajor", minorVersion);
+    }
+
+    virtual void TearDown() {
+        EGLBoolean success = eglTerminate(mEglDisplay);
+        ASSERT_EQ(EGL_TRUE, success);
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    }
+};
+
+TEST_F(EGLTest, DISABLED_EGLConfigEightBitFirst) {
+
+    EGLint numConfigs;
+    EGLConfig config;
+    EGLBoolean success;
+    EGLint attrs[] = {
+            EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
+            EGL_NONE
+    };
+
+    success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_GE(numConfigs, 1);
+
+    EGLint components[3];
+
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    EXPECT_GE(components[0], 8);
+    EXPECT_GE(components[1], 8);
+    EXPECT_GE(components[2], 8);
+}
+
+TEST_F(EGLTest, EGLConfigRGBA8888First) {
+
+    EGLint numConfigs;
+    EGLConfig config;
+    EGLBoolean success;
+    EGLint attrs[] = {
+            EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
+            EGL_RED_SIZE,           8,
+            EGL_GREEN_SIZE,         8,
+            EGL_BLUE_SIZE,          8,
+            EGL_ALPHA_SIZE,         8,
+            EGL_NONE
+    };
+
+    success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_GE(numConfigs, 1);
+
+    EGLint components[4];
+
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    EXPECT_GE(components[0], 8);
+    EXPECT_GE(components[1], 8);
+    EXPECT_GE(components[2], 8);
+    EXPECT_GE(components[3], 8);
+}
+
+
+}
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index e5f52e2..dd0d064 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -6,7 +6,6 @@
                  android:label="@string/app_label"
                  android:process="system"
                  android:backupAgent="SettingsBackupAgent"
-                 android:fullBackupAgent="SettingsBackupAgent"
                  android:killAfterRestore="false"
                  android:icon="@drawable/ic_launcher_settings">
                  
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 47ab150..afe4246 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -16,17 +16,6 @@
 
 package com.android.providers.settings;
 
-import com.android.internal.content.PackageHelper;
-import com.android.internal.telephony.BaseCommands;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.util.XmlUtils;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockPatternView;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.content.ComponentName;
 import android.content.ContentValues;
 import android.content.Context;
@@ -47,6 +36,17 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.content.PackageHelper;
+import com.android.internal.telephony.BaseCommands;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.util.XmlUtils;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 import java.util.HashSet;
 import java.util.List;
@@ -63,7 +63,7 @@
     // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
     // is properly propagated through your change.  Not doing so will result in a loss of user
     // settings.
-    private static final int DATABASE_VERSION = 65;
+    private static final int DATABASE_VERSION = 66;
 
     private Context mContext;
 
@@ -839,6 +839,28 @@
             upgradeVersion = 65;
         }
 
+        if (upgradeVersion == 65) {
+            /*
+             * Animations are removed from Settings. Turned on by default
+             */
+            db.beginTransaction();
+            SQLiteStatement stmt = null;
+            try {
+                db.execSQL("DELETE FROM system WHERE name='"
+                        + Settings.System.WINDOW_ANIMATION_SCALE + "'");
+                db.execSQL("DELETE FROM system WHERE name='"
+                        + Settings.System.TRANSITION_ANIMATION_SCALE + "'");
+                stmt = db.compileStatement("INSERT INTO system(name,value)"
+                        + " VALUES(?,?);");
+                loadDefaultAnimationSettings(stmt);
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+                if (stmt != null) stmt.close();
+            }
+            upgradeVersion = 66;
+        }
+
         // *** Remember to update DATABASE_VERSION above!
 
         if (upgradeVersion != currentVersion) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index a9aa31b..3a7a6e1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -36,7 +36,7 @@
 import android.app.backup.BackupDataInput;
 import android.app.backup.BackupDataOutput;
 import android.app.backup.BackupAgentHelper;
-import android.app.backup.FullBackup;
+import android.app.backup.FullBackupDataOutput;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
@@ -132,58 +132,22 @@
         byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
         byte[] wifiConfigData = getFileData(mWifiConfigFile);
 
-        // This same agent class is used for both full and incremental backups.  A full
-        // backup is flagged by a 'null' oldState argument.  In the case of a full backup,
-        // the output is structured as tarfile contents.
-        if (oldState != null) {
-            long[] stateChecksums = readOldChecksums(oldState);
+        long[] stateChecksums = readOldChecksums(oldState);
 
-            stateChecksums[STATE_SYSTEM] =
-                writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data);
-            stateChecksums[STATE_SECURE] =
-                writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
-            stateChecksums[STATE_LOCALE] =
-                writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
-            stateChecksums[STATE_WIFI_SUPPLICANT] =
-                writeIfChanged(stateChecksums[STATE_WIFI_SUPPLICANT], KEY_WIFI_SUPPLICANT,
-                        wifiSupplicantData, data);
-            stateChecksums[STATE_WIFI_CONFIG] =
-                writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData,
-                        data);
+        stateChecksums[STATE_SYSTEM] =
+            writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data);
+        stateChecksums[STATE_SECURE] =
+            writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
+        stateChecksums[STATE_LOCALE] =
+            writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
+        stateChecksums[STATE_WIFI_SUPPLICANT] =
+            writeIfChanged(stateChecksums[STATE_WIFI_SUPPLICANT], KEY_WIFI_SUPPLICANT,
+                    wifiSupplicantData, data);
+        stateChecksums[STATE_WIFI_CONFIG] =
+            writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData,
+                    data);
 
-            writeNewChecksums(stateChecksums, newState);
-        } else {
-            // Write the data to the staging file, then emit that as our tarfile
-            // representation of the backed-up settings.
-            String root = getFilesDir().getAbsolutePath();
-            File stage = new File(root, STAGE_FILE);
-            try {
-                FileOutputStream filestream = new FileOutputStream(stage);
-                BufferedOutputStream bufstream = new BufferedOutputStream(filestream);
-                DataOutputStream out = new DataOutputStream(bufstream);
-
-                out.writeInt(FULL_BACKUP_VERSION);
-
-                out.writeInt(systemSettingsData.length);
-                out.write(systemSettingsData);
-                out.writeInt(secureSettingsData.length);
-                out.write(secureSettingsData);
-                out.writeInt(locale.length);
-                out.write(locale);
-                out.writeInt(wifiSupplicantData.length);
-                out.write(wifiSupplicantData);
-                out.writeInt(wifiConfigData.length);
-                out.write(wifiConfigData);
-
-                out.flush();    // also flushes downstream
-
-                // now we're set to emit the tar stream
-                FullBackup.backupToTar(getPackageName(), FullBackup.DATA_TREE_TOKEN, null,
-                        root, stage.getAbsolutePath(), data);
-            } finally {
-                stage.delete();
-            }
-        }
+        writeNewChecksums(stateChecksums, newState);
     }
 
     @Override
@@ -221,6 +185,45 @@
     }
 
     @Override
+    public void onFullBackup(FullBackupDataOutput data)  throws IOException {
+        byte[] systemSettingsData = getSystemSettings();
+        byte[] secureSettingsData = getSecureSettings();
+        byte[] locale = mSettingsHelper.getLocaleData();
+        byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
+        byte[] wifiConfigData = getFileData(mWifiConfigFile);
+
+        // Write the data to the staging file, then emit that as our tarfile
+        // representation of the backed-up settings.
+        String root = getFilesDir().getAbsolutePath();
+        File stage = new File(root, STAGE_FILE);
+        try {
+            FileOutputStream filestream = new FileOutputStream(stage);
+            BufferedOutputStream bufstream = new BufferedOutputStream(filestream);
+            DataOutputStream out = new DataOutputStream(bufstream);
+
+            out.writeInt(FULL_BACKUP_VERSION);
+
+            out.writeInt(systemSettingsData.length);
+            out.write(systemSettingsData);
+            out.writeInt(secureSettingsData.length);
+            out.write(secureSettingsData);
+            out.writeInt(locale.length);
+            out.write(locale);
+            out.writeInt(wifiSupplicantData.length);
+            out.write(wifiSupplicantData);
+            out.writeInt(wifiConfigData.length);
+            out.write(wifiConfigData);
+
+            out.flush();    // also flushes downstream
+
+            // now we're set to emit the tar stream
+            fullBackupFile(stage, data);
+        } finally {
+            stage.delete();
+        }
+    }
+
+    @Override
     public void onRestoreFile(ParcelFileDescriptor data, long size,
             int type, String domain, String relpath, long mode, long mtime)
             throws IOException {
@@ -531,7 +534,12 @@
     private void restoreFileData(String filename, BackupDataInput data) {
         byte[] bytes = new byte[data.getDataSize()];
         if (bytes.length <= 0) return;
-        restoreFileData(filename, bytes, bytes.length);
+        try {
+            data.readEntityData(bytes, 0, data.getDataSize());
+            restoreFileData(filename, bytes, bytes.length);
+        } catch (IOException e) {
+            Log.w(TAG, "Unable to read file data for " + filename);
+        }
     }
 
     private void restoreFileData(String filename, byte[] bytes, int size) {
diff --git a/packages/SharedStorageBackup/AndroidManifest.xml b/packages/SharedStorageBackup/AndroidManifest.xml
index 258059c..39c36f1 100644
--- a/packages/SharedStorageBackup/AndroidManifest.xml
+++ b/packages/SharedStorageBackup/AndroidManifest.xml
@@ -23,7 +23,7 @@
 
     <application android:allowClearUserData="false"
                  android:permission="android.permission.CONFIRM_FULL_BACKUP"
-                 android:fullBackupAgent=".SharedStorageAgent"
+                 android:backupAgent=".SharedStorageAgent"
                  android:allowBackup="false" >
     </application>
 </manifest>
diff --git a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java
index b02ca2e..6c677b8 100644
--- a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java
+++ b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java
@@ -1,9 +1,10 @@
 package com.android.sharedstoragebackup;
 
-import android.app.backup.FullBackup;
 import android.app.backup.FullBackupAgent;
+import android.app.backup.FullBackup;
 import android.app.backup.BackupDataInput;
 import android.app.backup.BackupDataOutput;
+import android.app.backup.FullBackupDataOutput;
 import android.content.Context;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
@@ -30,9 +31,11 @@
         }
     }
 
+    /**
+     * Full backup of the shared-storage filesystem
+     */
     @Override
-    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
-            ParcelFileDescriptor newState) throws IOException {
+    public void onFullBackup(FullBackupDataOutput output) throws IOException {
         // If there are shared-storage volumes available, run the inherited directory-
         // hierarchy backup process on them.  By convention in the Storage Manager, the
         // "primary" shared storage volume is first in the list.
@@ -43,20 +46,12 @@
                 //     shared/N/path/to/file
                 // The restore will then extract to the given volume
                 String domain = FullBackup.SHARED_PREFIX + i;
-                processTree(null, domain, v.getPath(), null, data);
+                fullBackupFileTree(null, domain, v.getPath(), null, output);
             }
         }
     }
 
     /**
-     * Incremental onRestore() implementation is not used.
-     */
-    @Override
-    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
-            throws IOException {
-    }
-
-    /**
      * Full restore of one file to shared storage
      */
     @Override
@@ -88,6 +83,6 @@
             Slog.e(TAG, "Skipping data with malformed path " + relpath);
         }
 
-        FullBackup.restoreToFile(data, size, type, mode, mtime, outFile, false);
+        FullBackup.restoreFile(data, size, type, -1, mtime, outFile);
     }
 }
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 6d8eab6..26ea225 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -25,10 +25,11 @@
             android:exported="true"
             />
 
-        <activity android:name=".usb.UsbPreferenceActivity"
-             android:theme="@*android:style/Theme.Holo.Dialog.Alert"
-             android:excludeFromRecents="true">
-        </activity>
+        <!-- started from PhoneWindowManager
+             TODO: Should have an android:permission attribute -->
+        <service android:name=".screenshot.TakeScreenshotService"
+            android:exported="false" />
+
         <activity android:name=".usb.UsbStorageActivity"
                 android:excludeFromRecents="true">
         </activity>
diff --git a/packages/SystemUI/res/drawable-hdpi/alert_bar_background_normal.9.png b/packages/SystemUI/res/drawable-hdpi/alert_bar_background_normal.9.png
index bc127bd..a90c412 100644
--- a/packages/SystemUI/res/drawable-hdpi/alert_bar_background_normal.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/alert_bar_background_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/alert_bar_background_pressed.9.png b/packages/SystemUI/res/drawable-hdpi/alert_bar_background_pressed.9.png
index 59af804..9d6032c 100644
--- a/packages/SystemUI/res/drawable-hdpi/alert_bar_background_pressed.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/alert_bar_background_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png b/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
index 2c7a0d4..caa8795 100644
--- a/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
+++ b/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png
index baafed6..6f456f3 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png
index 175197b..e592ae6 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
index ec1feff..c1f87a7 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png
index c1f9a0f..2d16eda 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png
index 0ea3f40..0749413 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/global_screenshot_background.9.png b/packages/SystemUI/res/drawable-hdpi/global_screenshot_background.9.png
new file mode 100644
index 0000000..e14111d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/global_screenshot_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/hd_off.png b/packages/SystemUI/res/drawable-hdpi/hd_off.png
new file mode 100644
index 0000000..e7246cb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/hd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/hd_on.png b/packages/SystemUI/res/drawable-hdpi/hd_on.png
new file mode 100644
index 0000000..5360d42
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/hd_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png b/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
index ff34a7f..cbd72fb 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_dnd.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_dnd.png
index eb783df..2c48c97 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notification_dnd.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png
index c3e381e..165fa80 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
index d6c8a21..fd33ef3 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_off.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_off.png
new file mode 100644
index 0000000..a557164
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png
index 728a25d..7096b73 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default.png
new file mode 100644
index 0000000..48cab60
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default_land.png
new file mode 100644
index 0000000..000af5e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png
index ca8656c..ac5a97b 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default_land.png
new file mode 100644
index 0000000..c345e84
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default.png
index a4f4e87..a5a9652 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default_land.png
new file mode 100644
index 0000000..e77dfaf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png
index 299a0e7..e72fde8 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness_low.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness_low.png
new file mode 100644
index 0000000..b91be07
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness_low.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_gps_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_gps_on.png
index 029ea22..31e747e 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_gps_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_gps_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
new file mode 100644
index 0000000..5736d46
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png
index 06c9921..a90dc9b 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default_land.png
new file mode 100644
index 0000000..d686787
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default.png
new file mode 100644
index 0000000..7dfbc5f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default_land.png
new file mode 100644
index 0000000..8883601
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png
index 2249d01..2e5dc3c 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png
index ca3bb5d..a8f4daa 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png
index cb938fe..d23f9b7 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default_land.png
new file mode 100644
index 0000000..6d99ba5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd.png
new file mode 100644
index 0000000..13b969c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd_off.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd_off.png
new file mode 100644
index 0000000..25e7e6f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png
index 47b4ba2..2a94b5d 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png
index b2c4d45..cb3c433 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default_land.png
new file mode 100644
index 0000000..11ddf00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_lanscape.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_lanscape.png
new file mode 100644
index 0000000..da512e4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_lanscape.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_portrait.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_portrait.png
new file mode 100644
index 0000000..f2a7c6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_portrait.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png
index 20d28da..6208581 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_settings.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_settings.png
new file mode 100644
index 0000000..18fe5be
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png
index 7cb2643..ab581a1 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_off.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_off.png
new file mode 100644
index 0000000..0246cd4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_on.png
index 3be2eef..bec75e5 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png
index 88ac760..fe4d318 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_bg.9.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_bg.9.png
new file mode 100644
index 0000000..d5503f7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_bg_protect.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_bg_protect.png
new file mode 100644
index 0000000..a8f2236
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_bg_protect.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_normal.9.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_normal.9.png
new file mode 100644
index 0000000..b7ad39c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png
index 0c40c73..c93bd8c 100644
--- a/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_notify_bg.9.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_notify_bg.9.png
new file mode 100644
index 0000000..1680887
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_notify_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/pocket_drag_pattern.png b/packages/SystemUI/res/drawable-hdpi/pocket_drag_pattern.png
new file mode 100644
index 0000000..b436fc5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/pocket_drag_pattern.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recent_overlay.png b/packages/SystemUI/res/drawable-hdpi/recent_overlay.png
index fcf4417..ce48e0b 100644
--- a/packages/SystemUI/res/drawable-hdpi/recent_overlay.png
+++ b/packages/SystemUI/res/drawable-hdpi/recent_overlay.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png b/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png
index af36ac7..f10a487 100644
--- a/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png
+++ b/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png b/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png
index 18bd8b4..55f6aa1 100644
--- a/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png
+++ b/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png b/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png
index 993ccf4..19dae07 100644
--- a/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png
+++ b/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/scrubber_track_holo_dark.9.png b/packages/SystemUI/res/drawable-hdpi/scrubber_track_holo_dark.9.png
new file mode 100644
index 0000000..8811df5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/scrubber_track_holo_dark.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/shade_handlebar.9.png b/packages/SystemUI/res/drawable-hdpi/shade_handlebar.9.png
index f313ffb..0c12103 100644
--- a/packages/SystemUI/res/drawable-hdpi/shade_handlebar.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/shade_handlebar.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/shade_header_background.9.png b/packages/SystemUI/res/drawable-hdpi/shade_header_background.9.png
index 37b5fef..8fbe78e 100644
--- a/packages/SystemUI/res/drawable-hdpi/shade_header_background.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/shade_header_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png
index 4ec771a..ddbd3d7 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png
old mode 100755
new mode 100644
index 2ea2609..2fa0293
--- a/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..4cabd9e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..3d1e89d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..8a77137
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..dbfcfda
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..cb7a692
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..8d1b95c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..4d2b2f5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..aafc621
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..b6c7450
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..67eaebd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..14450ce
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..0578085
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..12a7ca8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..8ac9023
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..4debc5f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..92069c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..290e34b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png
index c9704fc..2538ab8 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png
index b37dd9f..cfc6344 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png
index 818e292..02757b1 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png
index 95866b1..4bfb8f2 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png
index 1aea612..ff4e040 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png
index 016b30b..71050c8 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png
index ec672eb..aa25d50 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png
old mode 100755
new mode 100644
index 27bab73..5641b7a
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..a6b0762
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_1x.png
index 0e6849b..6af7f65 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_3g.png
index a86a324..29d8f7b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png
index 425535e..e80265c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_e.png
index 24902d6..c7ff314 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_g.png
index 4160a95..2396c01 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_h.png
index d459ee3..5256041 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_1x.png
index 7b64751..5d728e7 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_3g.png
index d82930c..4b0472a 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png
index fcad363..b216c2a 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_e.png
old mode 100755
new mode 100644
index 8096846..d184206
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_g.png
index e94e146..fd2d6c1 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_h.png
index 8805a40..80ceea0 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_1x.png
index 07545d5..cdfa661 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_3g.png
index 7629cef..c8bd44f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png
index 4ff7db3..ecdd61f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_e.png
index 28578c6..c7c6a92 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_g.png
index d9f7a30..795e610 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_h.png
index 505ccd4..3b012cd 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_1x.png
index 783c2b6..ca435ce 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_3g.png
index 001eaea..63823be 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png
index 2c4a07f..b16455f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_e.png
index cbae7dc..db44420 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_g.png
index 11f3a5c..d99b977 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_h.png
index eb42294..72e5d5c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png
index 66fb60e..3405e1c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png
index 07ea499..940be0f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png
index 879c703..199e021 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png
index e39767a..50cbbba 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png
index 47c1fca..c571496 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png
old mode 100755
new mode 100644
index ac80dce..1920d0d
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png
index 61a7503..466c84c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_1x.png
index f88091b..2226bab 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png
index 95bb3cd..200b9a9 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png
index c5edf2c..5a592e3 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png
index 0ef4701..db40781 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_g.png
index 31b926b..6bf4841 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png
old mode 100755
new mode 100644
index ed02984..f323073
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png
index 0ee5b08..2650479 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png
index cac7802..d00f2af 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png
index ddf88be..a60e4e7 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png
index df6e195..00d9149 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png
index 4a2f867..cddd68c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png
old mode 100755
new mode 100644
index 2b4628f..e43e1a9
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png
index 765cdd7..5503df1 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png
index a0e59cf..081233b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0.png
index 1ef75d3..b30b240 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully.png
index 1ef75d3..b30b240 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1.png
index a7dc07e..d018f95 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully.png
index f1f4c4e..c4f34cb 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2.png
index 918a476..abdb7a6 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully.png
index 6e34e66..f4806cc 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3.png
index 5b2acc6..67aeef6 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully.png
index 3664ab4..fea1863 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4.png
index f1ff548..1bd644c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully.png
index b4fa481..46881b2 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png
index 5a741bb..3dfb469 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png
index 7ff375a..2506e58 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png
index c8ddfce..a59c844 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png
index 245677b..67f16b9 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png
index 6b6a6df..a59c844 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
index d17771e..2aeb84a 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
index b16e436..48f6122 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
index b595b60..4811a30 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png
index 76332c1..1439ece 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
index 0bd3ba3..3c25920 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png
index 3b8aff4..06c3369 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x.png
new file mode 100644
index 0000000..cac47a7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
index 473c74a..6d115b9 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png
index 54e02b5..a1a712f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
index ccd32fe..43803e4 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png
index 046c9a0..313f0f5 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
index 047e888..bff9fac 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png
index 21f90b0..75def49 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
index 80f5701..8316842 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png
index 1456eea..efbd535 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g.png
new file mode 100644
index 0000000..fabcd91
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
index 3b8fb13..6f2402d 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png
index a2675e9..e0dca0b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
index 9a6532a..0968cdd 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png
index 96a205f..54ee2e6 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g.png
new file mode 100644
index 0000000..c5301a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_edge.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_edge.png
new file mode 100644
index 0000000..36b7327
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_edge.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png
index 52e8a8e..a21c7ce 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_gprs.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_gprs.png
new file mode 100644
index 0000000..931997e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_gprs.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hsdpa.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hsdpa.png
new file mode 100644
index 0000000..54c0a07
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hsdpa.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png
index a7a3623..afec31d 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png
index 6429ffc..fa8ab31 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png
index 03d2147..686158b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png
index 9416793..0ec7307 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_roam.png
new file mode 100644
index 0000000..4d29193
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_tty_mode.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_tty_mode.png
index 4e161c6..a2aadd9 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_tty_mode.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_tty_mode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png
index c8cba34..8349da5 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png
index c0de67d..f06e5d1 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png
index 1647b21..c390437 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png
index f5b07e6..20cf07f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
index fbb31b8..f11b58e 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png
index c6267a4..76170a8 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png
index c1f2f97..15b0992 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png
index 5e42b55..97d35f3 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
index 8721d5c..8bea46d 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png
index bd400b5..17423d2 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png
old mode 100755
new mode 100644
index b8feac6..6d3151d
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png
index 4dab171..ae58b57 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
index 6854a2b..ad1245e 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png
index 9c868f1..00e5bb8 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png
old mode 100755
new mode 100644
index efff76c..cb67d57
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png
index e3a3cec..b036a89 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
index 3a5c7e2..117ac31 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png
index b9ba6d5..bdae6fb 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png
old mode 100755
new mode 100644
index dc1ce8e..df34c27
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png
index 0ad77f1..2b7d95f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
index 87d1944..6e5f131 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_expand_default.png b/packages/SystemUI/res/drawable-hdpi/status_bar_expand_default.png
new file mode 100644
index 0000000..017145e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_expand_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_expand_pressed.png b/packages/SystemUI/res/drawable-hdpi/status_bar_expand_pressed.png
new file mode 100644
index 0000000..7466d1d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_expand_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_ticker_tile.png b/packages/SystemUI/res/drawable-hdpi/status_bar_ticker_tile.png
new file mode 100644
index 0000000..772f77d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_ticker_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_veto_normal.png b/packages/SystemUI/res/drawable-hdpi/status_bar_veto_normal.png
index 3b7c9c7..90b4baf 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_veto_normal.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_veto_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_veto_pressed.png b/packages/SystemUI/res/drawable-hdpi/status_bar_veto_pressed.png
index 653acbb..bc7034a 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_veto_pressed.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_veto_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png b/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png
index a933833..6eaf6c9 100644
--- a/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/title_bar_portrait.9.png b/packages/SystemUI/res/drawable-hdpi/title_bar_portrait.9.png
index 70f7cc2..da1b637 100644
--- a/packages/SystemUI/res/drawable-hdpi/title_bar_portrait.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/title_bar_portrait.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png b/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png
index e6dab63..374873c 100644
--- a/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/app_icon.png b/packages/SystemUI/res/drawable-large-hdpi/app_icon.png
new file mode 100644
index 0000000..52354bd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/app_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-large-hdpi/recents_bg_protect_tile.png
new file mode 100644
index 0000000..ce01276
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-large-hdpi/recents_blue_glow.9.png
new file mode 100644
index 0000000..1848fcd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_blue_glow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-large-hdpi/recents_callout_line.png
new file mode 100644
index 0000000..61a3f87
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_callout_line.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg.png
new file mode 100644
index 0000000..b6aca49
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg_press.png b/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg_press.png
new file mode 100644
index 0000000..226aaac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg_press.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_1x.png
index 1629575..0809456 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_3g.png
index e87bcec..0e8ec07 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_4g.png
index fd44002..f9d2737 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_e.png
index e455ad6..f5b2c9a 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_g.png
index 6613585..eb1b18a 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_h.png
index 7502a54..1abe28a 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_4g.png
index 5f88279..e896cbb 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_4g.png
index 8c04bd6..b44123c 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_4g.png
index 456d0b6..6f59975 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_roam.png
index 1309176..d0cc579 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_roam.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_1x.png
index 810714e..903b03e 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_3g.png
index 72176ba..9578a21 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_4g.png
index 82a2bf0..c5e5cda 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_e.png
index 1e6c604..0730e3e 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_g.png
index 13aee06..eafed59 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_h.png
index 76c48a8..ea66c75 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_4g.png
index 456d0b6..6f59975 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_4g.png
index 456d0b6..6f59975 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_4g.png
index 456d0b6..6f59975 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/app_icon.png b/packages/SystemUI/res/drawable-large-mdpi/app_icon.png
new file mode 100644
index 0000000..001811f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/app_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-large-mdpi/recents_bg_protect_tile.png
new file mode 100644
index 0000000..3d0fbf2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-large-mdpi/recents_blue_glow.9.png
new file mode 100644
index 0000000..4362836
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_blue_glow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-large-mdpi/recents_callout_line.png
new file mode 100644
index 0000000..f4ccd7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_callout_line.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg.png
new file mode 100644
index 0000000..6392fa1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg_press.png b/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg_press.png
new file mode 100644
index 0000000..f6ee596
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg_press.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_1x.png
index 73cdabe..a885aab 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_3g.png
index b5a39cc..32f08c8 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_4g.png
index 6de880c..0111893 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_e.png
index 2dbbfc0..a9c547e 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_g.png
index a45f011..6801953 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_h.png
index 517a6bb..3ae2537 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_4g.png
index 821d00e..8a9f2e2 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_4g.png
index 4cdce84..8c5c482 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_4g.png
index 5a2662a..b28bf04 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_roam.png
index 5226c1c..36c2cf8 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_roam.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_1x.png
index a845648..aee1eed 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_3g.png
index 1d15587..30884a9 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_4g.png
index 52d5736..ce91aa9 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_e.png
index 79a2a05..82a4f61 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_g.png
index b032594..55b6b38 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_h.png
index c4abcc9..519154d 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_4g.png
index 5a2662a..b28bf04 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_4g.png
index 5a2662a..b28bf04 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_4g.png
index 5a2662a..b28bf04 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..a39e5e0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..ffe4546
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..a78cd14
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..a43ba99
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..cfeb769
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..b39d233
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_4g.png
new file mode 100644
index 0000000..5e0617f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_4g.png
new file mode 100644
index 0000000..da2926f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..41fd66c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..745717b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..1deb1f2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..2dce223
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..e13e73f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..6c9193b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..e9bb9c2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/alert_bar_background_normal.9.png b/packages/SystemUI/res/drawable-mdpi/alert_bar_background_normal.9.png
index 258de13..b94b144 100644
--- a/packages/SystemUI/res/drawable-mdpi/alert_bar_background_normal.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/alert_bar_background_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/alert_bar_background_pressed.9.png b/packages/SystemUI/res/drawable-mdpi/alert_bar_background_pressed.9.png
index 258de13..b94b144 100644
--- a/packages/SystemUI/res/drawable-mdpi/alert_bar_background_pressed.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/alert_bar_background_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png b/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png
index 7417afc..3de53d8 100644
--- a/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png
+++ b/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png
index bcedd5f..9b59b05 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png
index ac6260f..b517af6 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
index 4ee1b3f..019f33a 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png
index 25e38f4..6ce1bd3 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png
index cc209c6..0633543 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/global_screenshot_background.9.png b/packages/SystemUI/res/drawable-mdpi/global_screenshot_background.9.png
new file mode 100644
index 0000000..e14111d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/global_screenshot_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/hd_off.png b/packages/SystemUI/res/drawable-mdpi/hd_off.png
index ad09eef..6c01b8a 100644
--- a/packages/SystemUI/res/drawable-mdpi/hd_off.png
+++ b/packages/SystemUI/res/drawable-mdpi/hd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/hd_on.png b/packages/SystemUI/res/drawable-mdpi/hd_on.png
index 1471c13..de878ef 100644
--- a/packages/SystemUI/res/drawable-mdpi/hd_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/hd_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png b/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
index b08ad3b..7651331 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notification_dnd.png b/packages/SystemUI/res/drawable-mdpi/ic_notification_dnd.png
index 3f88968..8a4ef86 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notification_dnd.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png
index e0f67e8..ba0ca70 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png b/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png
index 1a3063c..667b13d 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_off.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_off.png
new file mode 100644
index 0000000..6d8b923
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png
index f8d7008..c33271b 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default.png
new file mode 100644
index 0000000..2ed5df4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default_land.png
new file mode 100644
index 0000000..c877f72
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
index 91fd0e8..5ab09f0 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default_land.png
new file mode 100644
index 0000000..d63b42a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
index 7b54daf..14d1ca9 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default_land.png
new file mode 100644
index 0000000..14d437e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png
index 55b767f..4dbca6d 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness_low.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness_low.png
new file mode 100644
index 0000000..91e1429
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness_low.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_gps_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_gps_on.png
index 1e39fdc..08d60d1 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_gps_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_gps_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png
new file mode 100644
index 0000000..77924f0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
index accdcfd..62ca427 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default_land.png
new file mode 100644
index 0000000..74d2590
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png
new file mode 100644
index 0000000..1b884ed
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default_land.png
new file mode 100644
index 0000000..e5711eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
index 7d381dd..45183b0 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png
index 954621b..8169fba 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png
index 0d58c3a..6d4d55d 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default_land.png
new file mode 100644
index 0000000..6619393
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd.png
new file mode 100644
index 0000000..c046f58
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd_off.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd_off.png
new file mode 100644
index 0000000..6b72be2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png
index 7928104..238df06 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
index 88f0a44..ff698fb 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default_land.png
new file mode 100644
index 0000000..6cc8031
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png
new file mode 100644
index 0000000..540af65
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_portrait.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_portrait.png
new file mode 100644
index 0000000..268a9bf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_portrait.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png
index d338fc0..2536d92 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_settings.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_settings.png
new file mode 100644
index 0000000..06e09e7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png
index c888c21..897d216 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_off.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_off.png
new file mode 100644
index 0000000..a11dabb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_on.png
index 70f72fa..16215bd 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png
index f2d0cd9..44e3577 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_bg.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_bg.9.png
index 22d6c79..8725e58 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_bg.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_bg_protect.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_bg_protect.png
index 24166da..f7225ed 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_bg_protect.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_bg_protect.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png
index 2266d15..2dcb659 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png
index 4fb1cf1..e7ed68b 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_notify_bg.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_notify_bg.9.png
index b389a35..e346167 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_notify_bg.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_notify_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/pocket_drag_pattern.png b/packages/SystemUI/res/drawable-mdpi/pocket_drag_pattern.png
index abde010..3370aeb 100644
--- a/packages/SystemUI/res/drawable-mdpi/pocket_drag_pattern.png
+++ b/packages/SystemUI/res/drawable-mdpi/pocket_drag_pattern.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recent_overlay.png b/packages/SystemUI/res/drawable-mdpi/recent_overlay.png
index 4dfa3d9..33eabb2 100644
--- a/packages/SystemUI/res/drawable-mdpi/recent_overlay.png
+++ b/packages/SystemUI/res/drawable-mdpi/recent_overlay.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recent_rez_border.png b/packages/SystemUI/res/drawable-mdpi/recent_rez_border.png
index ad025f5..5da42a3 100644
--- a/packages/SystemUI/res/drawable-mdpi/recent_rez_border.png
+++ b/packages/SystemUI/res/drawable-mdpi/recent_rez_border.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png b/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png
index 7e679ed..2b8768b 100644
--- a/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png
+++ b/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png b/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png
index 621e980..0672564 100644
--- a/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png
+++ b/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png b/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png
index baf70cd..511d5c3 100644
--- a/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/shade_handlebar.9.png b/packages/SystemUI/res/drawable-mdpi/shade_handlebar.9.png
index 9cbd9fe..d9598ae 100644
--- a/packages/SystemUI/res/drawable-mdpi/shade_handlebar.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/shade_handlebar.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/shade_header_background.9.png b/packages/SystemUI/res/drawable-mdpi/shade_header_background.9.png
index fa9a90c..761ef05 100644
--- a/packages/SystemUI/res/drawable-mdpi/shade_header_background.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/shade_header_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png
index 3a50987..364cf75 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png
index 5bde4e5..d7a48f2 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..95a797d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..6184516
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..cfbdb09
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..218a0a6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..6072855
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..fdfbd33
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..99f9120
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..7903132
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..ec514af
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..3ef6ce4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..cd748ef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..5cbc673
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..2005d00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..e94765e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..31b1b25
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..f06e81f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..b544180
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png
index f615835..44b4272 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png
index f784e7e..83edad5 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png
index c77e61e..24fd220 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png
index b9f721a..a409313 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png
index cff969e..d4f75cb 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png
index d2d7ab3..115ea1a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png
index 83ce6d0..13b1c23 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png
index abe511f..400869e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..6234c9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png
index d685af8..cde53f5 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png
index 8c697a1..9e1f8dc 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png
index 9a4b807..13d9ae3 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png
index eb11d04..e53ddac 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png
index 6e54de0..3146ebf 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png
index 5bfb33b..432bb20 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png
index 119067b..50756bc 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png
index a70cc2e..f8c4a65 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png
index ea3dba7..a278ed9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png
index 53221b9..14b2a21 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png
index 11d44d0..8072951 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png
index 9defd79..da4e7bb 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png
index 136576d..68330a9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png
index 26ca31f..c65b161 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png
index de8c5ee..a26a05e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png
index 64dbf3c..afae625 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png
index 34923fb..1f88c31 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png
index 506b5c6..d2a5340 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png
index 163976f..9f0941a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png
index a6af649..c568da6 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png
index 0c08e52..c22ae56 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png
index 1d02edb..345f351 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png
index edc9536..4f931e0 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png
index 8376817..2897ddb 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png
index ecef547..0a58322 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png
index a7c48b6..3a9af15 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png
index f4bcd9a..260634a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png
index b46bb3a..2521f00 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png
index e8b70f2..441af6e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png
index 4e23c4e..65a74aa 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png
index ced9175..addfcf2 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png
index 92d4a19..b87ce50 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png
index a208736..9b8e776 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png
index f407bc9..6a3c498 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_e.png
index 5bf6aca..07c9218 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png
index b8a65c2..c612b94 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png
index a978b68..7c66e93 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png
index 710dd52..c76490a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png
index a7b35e4..a2fff6f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png
index bb05449..1259050 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png
index a144222..bd08b97 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png
index b0eafb6..0c3c0ed 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png
index f6b83d0..40e6f7e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png
index c9da7b9..81c0c10 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png
index bb41db0..6ac52f9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0.png
index 7f6fa9c..f8c4b81 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully.png
index 7f6fa9c..f8c4b81 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1.png
index ca20839..d5a768c 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully.png
index 1ad5d8b..a697fa66 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2.png
index 6eba560..018c951 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully.png
index f2358dd..95b5d3d 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3.png
index 1ebe23e..922790e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully.png
index 468ad7d..df74fc3 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4.png
index d9f2a0d..2a527c9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully.png
index 290822a..bf88418 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png
index e0a3141..8e04b25 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png
index 116b8e2..44bd99f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png
old mode 100755
new mode 100644
index 827d84a..876d9ee
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png
old mode 100755
new mode 100644
index d62502d..436f16d
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png
old mode 100755
new mode 100644
index edc6023..876d9ee
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
index 3aa22f5..d52cb1a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png
index 9216030..0cfdca0 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
index 1afd107..4b805c4 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png
index 0de5760..7bbfbd1 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
index 3af5991..ef8ac73 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png
index e042696..60b75ef 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png
index 25ca124..632127a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
index 49b0175..0b48667 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png
index 88b08c8..0fba69d 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
index 496df52..b0182a0 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png
index 940adf0..da8a957 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
index fab2e10..db75f74 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png
index 3f4dedd..e19bf64 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
index ff474b6..9e22573 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png
index 83045ce..8387514 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png
index 2725ed2..a0c3bc7 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
index 409bb31..504990e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png
index f5c0aa3..35f7741 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
index 38c7f07..d35736e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png
index 429e818..a8820e9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png
index ade3716..3416151 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png
index 83cb820..435d25d 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png
index 174d65c..0e1964c 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png
index 9c3c44c..68f4530 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png
index 08b975a..584e703 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png
index 5799ad2..b114fea 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png
index ec617d7..de3f56f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png
index 5d9957a..b65df27 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png
index 1260c59..7f7074e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png
index ae9dc40..2b4af59 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_tty_mode.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_tty_mode.png
index ed157a8..fb70ba8 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_tty_mode.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_tty_mode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png
index 0ec4c64..ca3d5bf 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png
index 60dc8a6..a17e1d7 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png
index fe2ba7a..b5ab8b3 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png
index 150a6c7..8e9c451 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
index 76f86dc..25e9394 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png
index 42a798a..0478d70 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png
index 1f0dd89..6de73be 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png
index 1643e6e..e78a0b1 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
index 5e7ae35..02d4b3f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png
index 06ae2ca..24c75ec 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png
index b861bc9..108c054 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png
index 8f1831d..7027dc4 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
index 8f16376..a9d22d6 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png
index 12138d3..b0e83dc 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png
index 67f46d3..0ed3c8f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png
index 11fd5e9..01945ff 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
index 165348c..dc36e0e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png
index 8bbc5ba..725a507 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png
index d53d3bc..f3fd89a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png
index c817598..193af25 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
new file mode 100644
index 0000000..22215ab
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png
index ce64926..1fd5dd3 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png
index c63c426..b2edd46 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_ticker_tile.png b/packages/SystemUI/res/drawable-mdpi/status_bar_ticker_tile.png
index 85394fa..0eb71d0 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_ticker_tile.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_ticker_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_veto_normal.png b/packages/SystemUI/res/drawable-mdpi/status_bar_veto_normal.png
index 3b7c9c7..90b4baf 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_veto_normal.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_veto_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png
index 653acbb..bc7034a 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png b/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png
index 6c588f7..6f19bf4 100644
--- a/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/title_bar_portrait.9.png b/packages/SystemUI/res/drawable-mdpi/title_bar_portrait.9.png
index 13b18d8..9de8324 100644
--- a/packages/SystemUI/res/drawable-mdpi/title_bar_portrait.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/title_bar_portrait.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png b/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png
index dbcefee..75a020c 100644
--- a/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/bg_scrim_notification.png b/packages/SystemUI/res/drawable-nodpi/bg_scrim_notification.png
index 6e13ebe..4d5135e 100644
--- a/packages/SystemUI/res/drawable-nodpi/bg_scrim_notification.png
+++ b/packages/SystemUI/res/drawable-nodpi/bg_scrim_notification.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_glow_back.png b/packages/SystemUI/res/drawable-nodpi/notify_glow_back.png
old mode 100755
new mode 100644
index 7d17a54..269049e
--- a/packages/SystemUI/res/drawable-nodpi/notify_glow_back.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_glow_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_bottom.png b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_bottom.png
index d960c78..e7828c9 100644
--- a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_bottom.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_bottom.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_left.png b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_left.png
old mode 100755
new mode 100644
index 3e46370..0e8c25c
--- a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_left.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_left.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_top.png b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_top.png
old mode 100755
new mode 100644
index afc91b9..536357a
--- a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_top.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_top.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_panel_bg.png b/packages/SystemUI/res/drawable-nodpi/notify_panel_bg.png
old mode 100755
new mode 100644
index 7086def..1ea924f
--- a/packages/SystemUI/res/drawable-nodpi/notify_panel_bg.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_panel_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/panel_notification.png b/packages/SystemUI/res/drawable-nodpi/panel_notification.png
new file mode 100644
index 0000000..275e492
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/panel_notification.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_diagram.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_diagram.png
new file mode 100644
index 0000000..03f4732
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_diagram.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_bottom.9.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_bottom.9.png
new file mode 100644
index 0000000..7bfdb46
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_bottom.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_top.9.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_top.9.png
new file mode 100644
index 0000000..4e20851
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_top.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_icon.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_icon.png
new file mode 100644
index 0000000..1c1b26b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_off.png
new file mode 100644
index 0000000..ed968c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_on.png
new file mode 100644
index 0000000..31ac35d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default.png
new file mode 100644
index 0000000..5641b2b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default_land.png
new file mode 100644
index 0000000..1ea83fc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default.png
new file mode 100644
index 0000000..4cb305d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default_land.png
new file mode 100644
index 0000000..85df060
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default.png
new file mode 100644
index 0000000..0019a32
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default_land.png
new file mode 100644
index 0000000..dc08550
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness.png
new file mode 100644
index 0000000..bc024da
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness_low.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness_low.png
new file mode 100644
index 0000000..03885fa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness_low.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_gps_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_gps_on.png
new file mode 100644
index 0000000..92e86c6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_gps_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png
new file mode 100644
index 0000000..2e6e3ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default.png
new file mode 100644
index 0000000..31d35c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default_land.png
new file mode 100644
index 0000000..334213b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default.png
new file mode 100644
index 0000000..dd98b0b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default_land.png
new file mode 100644
index 0000000..94acf9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png
new file mode 100644
index 0000000..155c788
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png
new file mode 100644
index 0000000..e84f3fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default.png
new file mode 100644
index 0000000..7c21c48
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default_land.png
new file mode 100644
index 0000000..1fe6b91
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd.png
new file mode 100644
index 0000000..4fc936b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd_off.png
new file mode 100644
index 0000000..27357ea
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_quicksettings.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_quicksettings.png
new file mode 100644
index 0000000..bbf5f7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_quicksettings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default.png
new file mode 100644
index 0000000..f0cc341
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default_land.png
new file mode 100644
index 0000000..7e8504c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_lanscape.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_lanscape.png
new file mode 100644
index 0000000..53c7094
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_lanscape.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_portrait.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_portrait.png
new file mode 100644
index 0000000..a882b94
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_portrait.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_on.png
new file mode 100644
index 0000000..b375396
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_settings.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_settings.png
new file mode 100644
index 0000000..fdcf409
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_shadow.9.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_shadow.9.png
new file mode 100644
index 0000000..792bac4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_off.png
new file mode 100644
index 0000000..31b4663
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_on.png
new file mode 100644
index 0000000..45b5bf3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_wifi_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_wifi_on.png
new file mode 100644
index 0000000..54e3d1e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_wifi_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..bcea4f9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..d915a9d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..6cf2053
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..d4a2068
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..4be3873
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..31e4813
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..032fa29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..52ad541
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..d7248b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..5d1a99c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..b342507
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..b618f75
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..11946cd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..e227309
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..4b0838c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..ecd4396e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..8c5465a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png
new file mode 100644
index 0000000..9e7992a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth_connected.png
new file mode 100644
index 0000000..ccf5b0e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..04918c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..34da296
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..f6cb0ce
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..eb4927a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..14087e4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..87b67b3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..33fa2ae
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..a84382f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..b59a72e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..c7927d9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..eddb4eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..2759a8e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..f129965
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..1abe164
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..06dc700
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..d1ae45d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..0c93241
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..3be20a2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..502382e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..b423454
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..b084871
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..8cbaff3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..0e53656
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..55c66b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..103927b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..2a0c21a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..23dfd7a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..1258359
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..32c1432
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..b56be83
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..cd37477
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_1x.png
new file mode 100644
index 0000000..347b219
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_3g.png
new file mode 100644
index 0000000..ef5b653
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_4g.png
new file mode 100644
index 0000000..cd96a4a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_e.png
new file mode 100644
index 0000000..02461a9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_g.png
new file mode 100644
index 0000000..033267f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_h.png
new file mode 100644
index 0000000..73ae175
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inadnout_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inadnout_e.png
new file mode 100644
index 0000000..1355da1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inadnout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_1x.png
new file mode 100644
index 0000000..ceb316c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_3g.png
new file mode 100644
index 0000000..ff4a0b3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_4g.png
new file mode 100644
index 0000000..b2ebf40
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_e.png
new file mode 100644
index 0000000..7f833ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_g.png
new file mode 100644
index 0000000..b47e4c3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_h.png
new file mode 100644
index 0000000..4f88492
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_1x.png
new file mode 100644
index 0000000..7f7e1ef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_3g.png
new file mode 100644
index 0000000..f0ab081
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_4g.png
new file mode 100644
index 0000000..e556da1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_e.png
new file mode 100644
index 0000000..a28d771
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_g.png
new file mode 100644
index 0000000..7be9754
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_h.png
new file mode 100644
index 0000000..16271a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_gps_acquiring.png
new file mode 100644
index 0000000..263c591
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_gps_acquiring.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_no_sim.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_no_sim.png
new file mode 100644
index 0000000..edff8db
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_no_sim.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0.png
new file mode 100644
index 0000000..e7938f1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully.png
new file mode 100644
index 0000000..e7938f1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1.png
new file mode 100644
index 0000000..33fda46
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully.png
new file mode 100644
index 0000000..1d5484b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2.png
new file mode 100644
index 0000000..478b293
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully.png
new file mode 100644
index 0000000..b9cff0e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3.png
new file mode 100644
index 0000000..4945e23
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully.png
new file mode 100644
index 0000000..a55ecd8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4.png
new file mode 100644
index 0000000..0641c9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully.png
new file mode 100644
index 0000000..d0eebb6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png
new file mode 100644
index 0000000..cd89105
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png
new file mode 100644
index 0000000..e85d643
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_0.png
new file mode 100644
index 0000000..51b291c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim0.png
new file mode 100644
index 0000000..23d30fe
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim1.png
new file mode 100644
index 0000000..51b291c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0.png
new file mode 100644
index 0000000..726f7ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png
new file mode 100644
index 0000000..ec4f934
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png
new file mode 100644
index 0000000..a77c8a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png
new file mode 100644
index 0000000..fb98eef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully.png
new file mode 100644
index 0000000..1527803
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_flowing.png
new file mode 100644
index 0000000..b86d47a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1x.png
new file mode 100644
index 0000000..e487f5e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png
new file mode 100644
index 0000000..64ddafd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_flowing.png
new file mode 100644
index 0000000..7269f96
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully.png
new file mode 100644
index 0000000..6cf7a28
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_flowing.png
new file mode 100644
index 0000000..f57e62d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png
new file mode 100644
index 0000000..0bc3d0b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_flowing.png
new file mode 100644
index 0000000..3d513fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully.png
new file mode 100644
index 0000000..34ec231
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_flowing.png
new file mode 100644
index 0000000..32556f9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3g.png
new file mode 100644
index 0000000..15d0f2f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png
new file mode 100644
index 0000000..c7c1e3e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_flowing.png
new file mode 100644
index 0000000..afac648
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully.png
new file mode 100644
index 0000000..6e4dc8c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_flowing.png
new file mode 100644
index 0000000..60c0e7f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4g.png
new file mode 100644
index 0000000..90ca4e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_edge.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_edge.png
new file mode 100644
index 0000000..befa1eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_edge.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_flightmode.png
new file mode 100644
index 0000000..419afa0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_gprs.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_gprs.png
new file mode 100644
index 0000000..93af4fa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_gprs.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_hsdpa.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_hsdpa.png
new file mode 100644
index 0000000..c3f9e5d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_hsdpa.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_in.png
new file mode 100644
index 0000000..b20c61b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_inout.png
new file mode 100644
index 0000000..b51178d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png
new file mode 100644
index 0000000..0df470a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_out.png
new file mode 100644
index 0000000..485d407
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_roam.png
new file mode 100644
index 0000000..19cf3b0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_tty_mode.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_tty_mode.png
new file mode 100644
index 0000000..d28972f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_tty_mode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_in.png
new file mode 100644
index 0000000..6ed28c6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_inout.png
new file mode 100644
index 0000000..4f462ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_out.png
new file mode 100644
index 0000000..66d8f80
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_0.png
new file mode 100644
index 0000000..b2b2ace
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1.png
new file mode 100644
index 0000000..5212337
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_flowing.png
new file mode 100644
index 0000000..d8d5e8f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully.png
new file mode 100644
index 0000000..43e590b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully_flowing.png
new file mode 100644
index 0000000..2b0b54f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2.png
new file mode 100644
index 0000000..e900d6b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_flowing.png
new file mode 100644
index 0000000..85c65b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully.png
new file mode 100644
index 0000000..990734c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully_flowing.png
new file mode 100644
index 0000000..a7e9aaf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3.png
new file mode 100644
index 0000000..d982c1f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_flowing.png
new file mode 100644
index 0000000..21aba7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully.png
new file mode 100644
index 0000000..daf2750
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully_flowing.png
new file mode 100644
index 0000000..41db8dc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4.png
new file mode 100644
index 0000000..b93e9ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_flowing.png
new file mode 100644
index 0000000..ae95d26
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..576f120
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully_flowing.png
new file mode 100644
index 0000000..4ad2c5c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/app_icon.png b/packages/SystemUI/res/drawable-xlarge-hdpi/app_icon.png
new file mode 100644
index 0000000..52354bd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/app_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_bg_protect_tile.png
new file mode 100644
index 0000000..ce01276
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_blue_glow.9.png
new file mode 100644
index 0000000..1848fcd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_blue_glow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_callout_line.png
new file mode 100644
index 0000000..846bc49
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_callout_line.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg.png
new file mode 100644
index 0000000..a983e12
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg_press.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg_press.png
new file mode 100644
index 0000000..7c6e44e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg_press.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..a08c5f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..6aa38bc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..36c26b6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..55940d2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..f65ef5b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..8a0f4e7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..2d81b22
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..4c08cff
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..27d3b50
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..f017dd1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..6cd2c71
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..76195ca
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..fb097b0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..04740b8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..147d256
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..de808a2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..d19d6ee
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth.png
new file mode 100644
index 0000000..4bce24d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth_connected.png
new file mode 100644
index 0000000..0467e12
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..0809456
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..0e8ec07
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..f9d2737
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..f5b2c9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..eb1b18a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..1abe28a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_4g.png
new file mode 100644
index 0000000..e896cbb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_4g.png
new file mode 100644
index 0000000..b44123c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_4g.png
new file mode 100644
index 0000000..6f59975
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..d0cc579
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..903b03e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..9578a21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..c5e5cda
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..0730e3e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..eafed59
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..ea66c75
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..6f59975
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..6f59975
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..6f59975
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0.png
new file mode 100644
index 0000000..8a9deea
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1.png
new file mode 100644
index 0000000..11ee533
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1_fully.png
new file mode 100644
index 0000000..43edb8c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2.png
new file mode 100644
index 0000000..7919030
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2_fully.png
new file mode 100644
index 0000000..0699681
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3.png
new file mode 100644
index 0000000..9504838
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3_fully.png
new file mode 100644
index 0000000..db8bedb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4.png
new file mode 100644
index 0000000..89e1b2c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4_fully.png
new file mode 100644
index 0000000..88f720d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_flightmode.png
new file mode 100644
index 0000000..89fcbd4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_in.png
new file mode 100644
index 0000000..0ec439c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_inout.png
new file mode 100644
index 0000000..4b22619
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_out.png
new file mode 100644
index 0000000..9b8c889
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_in.png
new file mode 100644
index 0000000..e601a90
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_inout.png
new file mode 100644
index 0000000..b65c93f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_out.png
new file mode 100644
index 0000000..80fdafe
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_0.png
new file mode 100644
index 0000000..c54f630
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1.png
new file mode 100644
index 0000000..8cfc59b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1_fully.png
new file mode 100644
index 0000000..3381016
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2.png
new file mode 100644
index 0000000..0a77e7b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2_fully.png
new file mode 100644
index 0000000..660b3a0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3.png
new file mode 100644
index 0000000..0c278ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3_fully.png
new file mode 100644
index 0000000..921d88b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4.png
new file mode 100644
index 0000000..4c6c08e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..de32ddd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/app_icon.png b/packages/SystemUI/res/drawable-xlarge-mdpi/app_icon.png
new file mode 100644
index 0000000..001811f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/app_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png
new file mode 100644
index 0000000..3d0fbf2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_blue_glow.9.png
new file mode 100644
index 0000000..4362836
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_blue_glow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_callout_line.png
new file mode 100644
index 0000000..f4ccd7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_callout_line.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png
new file mode 100644
index 0000000..6392fa1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg_press.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg_press.png
new file mode 100644
index 0000000..f6ee596
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg_press.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..5087adb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..4c212e7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..bf23074
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..45dcf77
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..a2848de
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..89c998b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..9269d6e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..344ae30
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..13b5cae
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..6647559
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..a0e67c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..9a75c24
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..a1f73c2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..6b17f1c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..9553580
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..8507f39
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..6966cec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth.png
new file mode 100644
index 0000000..84ce77f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth_connected.png
new file mode 100644
index 0000000..b8670f2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..a885aab
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..32f08c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..0111893
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..a9c547e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..6801953
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..3ae2537
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_4g.png
new file mode 100644
index 0000000..8a9f2e2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_4g.png
new file mode 100644
index 0000000..8c5c482
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_4g.png
new file mode 100644
index 0000000..b28bf04
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..36c2cf8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..aee1eed
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..30884a9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..ce91aa9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..82a4f61
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..55b6b38
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..519154d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..b28bf04
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..b28bf04
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..b28bf04
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0.png
new file mode 100644
index 0000000..2de4515
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1.png
new file mode 100644
index 0000000..cdbab37
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1_fully.png
new file mode 100644
index 0000000..ec398cb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2.png
new file mode 100644
index 0000000..b1f16d6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2_fully.png
new file mode 100644
index 0000000..e15a12b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3.png
new file mode 100644
index 0000000..90a1a3d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3_fully.png
new file mode 100644
index 0000000..21d944a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4.png
new file mode 100644
index 0000000..9b2263f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4_fully.png
new file mode 100644
index 0000000..ca36237
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_flightmode.png
new file mode 100644
index 0000000..2cea010
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_in.png
new file mode 100644
index 0000000..3d22838
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_inout.png
new file mode 100644
index 0000000..3bee795
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_out.png
new file mode 100644
index 0000000..ad6bdce
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_in.png
new file mode 100644
index 0000000..6d68d4e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_inout.png
new file mode 100644
index 0000000..04ddb65
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_out.png
new file mode 100644
index 0000000..830b006
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_0.png
new file mode 100644
index 0000000..f3be79b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1.png
new file mode 100644
index 0000000..7f33567
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1_fully.png
new file mode 100644
index 0000000..471a900
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2.png
new file mode 100644
index 0000000..b153c83
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2_fully.png
new file mode 100644
index 0000000..3a5ddb7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3.png
new file mode 100644
index 0000000..609117c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3_fully.png
new file mode 100644
index 0000000..d8cd1fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4.png
new file mode 100644
index 0000000..806b43b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..f699434
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..64d8b5e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..4e718b0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..7306b48
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..f414632
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..9e7a84a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..e17ce98
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..861b0b7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..fe1330b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..d459a00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..debd23e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..69ba222
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..7d862bb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..6687c82
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..8438e76
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..1842da2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..f9d2754
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..892ba42
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth.png
new file mode 100644
index 0000000..73e0886
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth_connected.png
new file mode 100644
index 0000000..dc3aae3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..9d0fe7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..d3f6f55
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..7170a84
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..febf958
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..4da4f54
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..e775572
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_4g.png
new file mode 100644
index 0000000..5e0617f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_4g.png
new file mode 100644
index 0000000..da2926f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..fef89cf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..c543b9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..3395fff
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..612843d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..9de3703
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..dabfec5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..0ca6fbf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0.png
new file mode 100644
index 0000000..b9410f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1.png
new file mode 100644
index 0000000..aa73096
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1_fully.png
new file mode 100644
index 0000000..b534296
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2.png
new file mode 100644
index 0000000..a33c488
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2_fully.png
new file mode 100644
index 0000000..fdd9c92
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3.png
new file mode 100644
index 0000000..5454b49
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3_fully.png
new file mode 100644
index 0000000..e338fd9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4.png
new file mode 100644
index 0000000..549b7d2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4_fully.png
new file mode 100644
index 0000000..9779320
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_flightmode.png
new file mode 100644
index 0000000..5ca5827
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_in.png
new file mode 100644
index 0000000..174ef2d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_inout.png
new file mode 100644
index 0000000..3e9dece
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_out.png
new file mode 100644
index 0000000..8952833
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_in.png
new file mode 100644
index 0000000..180a13b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_inout.png
new file mode 100644
index 0000000..b9efa16
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_out.png
new file mode 100644
index 0000000..d8493ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_0.png
new file mode 100644
index 0000000..885831e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1.png
new file mode 100644
index 0000000..03fcf54
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1_fully.png
new file mode 100644
index 0000000..9bf7bec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2.png
new file mode 100644
index 0000000..15a82ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2_fully.png
new file mode 100644
index 0000000..eb9ce59
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3.png
new file mode 100644
index 0000000..1c62fe3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3_fully.png
new file mode 100644
index 0000000..09cdfc4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4.png
new file mode 100644
index 0000000..5447a85
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..04187de
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
index 4a80489..efdd9ac 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
@@ -22,11 +22,11 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/recents_root"
     android:layout_height="match_parent"
-    android:layout_width="wrap_content">
+    android:layout_width="match_parent">
 
     <FrameLayout
         android:id="@+id/recents_bg_protect"
-        android:background="@drawable/recents_bg_protect_tile"
+        android:background="@drawable/status_bar_recents_background"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_alignParentBottom="true"
@@ -38,7 +38,6 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="bottom|right"
-            android:background="@drawable/recents_blue_glow"
             android:orientation="horizontal"
             android:clipToPadding="false"
             android:clipChildren="false"
@@ -78,6 +77,7 @@
         android:layout_alignParentBottom="true"
         android:layout_alignParentLeft="true"
         android:background="@drawable/ic_sysbar_back_ime"
+        android:visibility="gone"
     />
 
 </com.android.systemui.recent.RecentsPanelView>
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
index 9391f9d..28ef239 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
@@ -26,25 +26,20 @@
 
     <FrameLayout
         android:id="@+id/recents_bg_protect"
-        android:background="@drawable/recents_bg_protect_tile"
+        android:background="@drawable/status_bar_recents_background"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_alignParentBottom="true"
-        android:paddingBottom="@*android:dimen/status_bar_height"
-        android:clipToPadding="false"
-        android:clipChildren="false">
+        android:layout_alignParentBottom="true">
 
         <LinearLayout android:id="@+id/recents_glow"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginBottom="0dp"
             android:layout_gravity="bottom"
-            android:background="@drawable/recents_blue_glow"
             android:orientation="horizontal"
-            android:clipToPadding="false"
             android:clipChildren="false"
-            >
-            <com.android.systemui.recent.RecentsVerticalScrollView android:id="@+id/recents_container"
+            android:layout_marginTop="@*android:dimen/status_bar_height">
+            <com.android.systemui.recent.RecentsVerticalScrollView
+                android:id="@+id/recents_container"
                 android:layout_width="@dimen/status_bar_recents_width"
                 android:layout_height="wrap_content"
                 android:layout_marginRight="0dp"
@@ -52,7 +47,7 @@
                 android:stackFromBottom="true"
                 android:fadingEdge="vertical"
                 android:scrollbars="none"
-                android:fadingEdgeLength="20dip"
+                android:fadingEdgeLength="@*android:dimen/status_bar_height"
                 android:listSelector="@drawable/recents_thumbnail_bg_selector"
                 android:layout_gravity="bottom|left"
                 android:clipToPadding="false"
@@ -79,6 +74,7 @@
         android:layout_alignParentBottom="true"
         android:layout_alignParentLeft="true"
         android:background="@drawable/ic_sysbar_back_ime"
+        android:visibility="gone"
     />
 
 </com.android.systemui.recent.RecentsPanelView>
diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml
new file mode 100644
index 0000000..6cb8799
--- /dev/null
+++ b/packages/SystemUI/res/layout/global_screenshot.xml
@@ -0,0 +1,40 @@
+<?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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <ImageView android:id="@+id/global_screenshot_background"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#FF000000"
+        android:visibility="gone" />
+    <FrameLayout
+        android:id="@+id/global_screenshot_container"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:background="@drawable/global_screenshot_background"
+        android:visibility="gone">
+        <ImageView android:id="@+id/global_screenshot"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:adjustViewBounds="true" />
+    </FrameLayout>
+    <ImageView android:id="@+id/global_screenshot_flash"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#FFFFFFFF"
+        android:visibility="gone" />
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index b97c6a5..51e7d97 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -25,106 +25,145 @@
     android:layout_width="match_parent"
     >
 
-    <FrameLayout
-        android:id="@+id/background"
+    <FrameLayout android:id="@+id/rot0"
         android:layout_height="match_parent"
         android:layout_width="match_parent"
         android:background="#FF000000"
         >
 
-        <LinearLayout android:id="@+id/rot0"
+        <LinearLayout
             android:layout_height="match_parent"
             android:layout_width="match_parent"
-            android:paddingLeft="8dip"
-            android:paddingRight="8dip"
             android:orientation="horizontal"
             >
 
             <!-- navigation controls -->
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
-                android:layout_width="wrap_content"
+            <View
+                android:layout_width="40dp"
                 android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_back"
+                android:layout_weight="0"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
+                android:layout_width="80dp"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_back_default"
                 systemui:keyCode="4"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
                 android:layout_weight="1"
                 />
             <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
-                android:layout_width="wrap_content"
+                android:layout_width="80dp"
                 android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_home"
+                android:src="@drawable/ic_sysbar_home_default"
                 systemui:keyCode="3"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
                 android:layout_weight="1"
                 />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                android:layout_width="wrap_content"
+            <ImageView android:id="@+id/recent_apps"
+                android:layout_width="80dp"
                 android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_menu"
+                android:src="@drawable/ic_sysbar_recent_default"
+                android:layout_weight="0"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
+                android:layout_width="40dp"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_sysbar_menu_default"
                 systemui:keyCode="82"
-                android:layout_weight="1"
+                android:layout_weight="0"
+                android:visibility="invisible"
                 />
         </LinearLayout>
 
-        <LinearLayout android:id="@+id/rot90"
-            android:layout_height="match_parent"
+        <View android:id="@+id/deadzone"
+            android:layout_height="@dimen/navigation_bar_deadzone_size"
             android:layout_width="match_parent"
-            android:orientation="vertical"
-            android:visibility="gone"
-            >
-
-            <!-- navigation controls -->
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:src="@drawable/ic_sysbar_menu"
-                systemui:keyCode="82"
-                android:layout_weight="1"
-                />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:src="@drawable/ic_sysbar_home"
-                systemui:keyCode="3"
-                android:layout_weight="1"
-                />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:src="@drawable/ic_sysbar_back"
-                systemui:keyCode="4"
-                android:layout_weight="1"
-                />
-        </LinearLayout>
-
-        <LinearLayout android:id="@+id/rot270"
-            android:layout_height="match_parent"
-            android:layout_width="match_parent"
-            android:orientation="vertical"
-            android:visibility="gone"
-            >
-
-            <!-- navigation controls -->
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:src="@drawable/ic_sysbar_back"
-                systemui:keyCode="4"
-                android:layout_weight="1"
-                />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:src="@drawable/ic_sysbar_home"
-                systemui:keyCode="3"
-                android:layout_weight="1"
-                />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:src="@drawable/ic_sysbar_menu"
-                systemui:keyCode="82"
-                android:layout_weight="1"
-                />
-        </LinearLayout>
-    
+            android:layout_gravity="top"
+            android:clickable="true"
+            />
     </FrameLayout>
+
+    <FrameLayout android:id="@+id/rot90"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:background="#FF000000"
+        android:visibility="gone"
+        android:paddingTop="24dp"
+        >
+
+        <LinearLayout 
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:orientation="vertical"
+            >
+            
+            <!-- navigation controls -->
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
+                android:layout_height="40dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_menu_default_land"
+                systemui:keyCode="82"
+                android:layout_weight="0"
+                android:visibility="invisible"
+                />
+            <ImageView android:id="@+id/recent_apps"
+                android:layout_height="80dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_recent_default_land"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_height="match_parent"
+                android:layout_width="match_parent"
+                android:layout_weight="1"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
+                android:layout_height="80dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_home_default_land"
+                systemui:keyCode="3"
+                android:layout_weight="0"
+                />
+            <View 
+                android:layout_height="match_parent"
+                android:layout_width="match_parent"
+                android:layout_weight="1"
+                />
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
+                android:layout_height="80dp"
+                android:layout_width="match_parent"
+                android:src="@drawable/ic_sysbar_back_default_land"
+                systemui:keyCode="4"
+                android:layout_weight="0"
+                />
+            <View
+                android:layout_height="40dp"
+                android:layout_width="match_parent"
+                android:layout_weight="0"
+                />
+        </LinearLayout>
+
+        <View android:id="@+id/deadzone"
+            android:layout_width="@dimen/navigation_bar_deadzone_size"
+            android:layout_height="match_parent"
+            android:layout_gravity="left"
+            android:clickable="true"
+            />
+    </FrameLayout>
+
+    <!-- not used -->
+    <View android:id="@+id/rot270"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:visibility="gone"
+        />
+
 </com.android.systemui.statusbar.phone.NavigationBarView>
diff --git a/packages/SystemUI/res/layout/usb_preference_buttons.xml b/packages/SystemUI/res/layout/usb_preference_buttons.xml
deleted file mode 100644
index babe07e..0000000
--- a/packages/SystemUI/res/layout/usb_preference_buttons.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<!-- Check box that is displayed in the activity resolver UI for the user
-     to make their selection the preferred activity. -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:paddingLeft="14dip"
-    android:paddingRight="15dip"
-    android:orientation="vertical">
-
-    <Button
-        android:id="@+id/mtp_ptp_button"
-        android:text="@string/use_ptp_button_title"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:focusable="true"
-        android:clickable="true" />
-
-    <Button
-        android:id="@+id/installer_cd_button"
-        android:text="@string/installer_cd_button_title"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:focusable="true"
-        android:clickable="true" />
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index c0c39d2..bf18e3b 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -77,12 +77,8 @@
     <skip />
     <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
     <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 7b37070..7e15fe0 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -77,12 +77,8 @@
     <skip />
     <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
     <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 1555048..d8aa61f 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"عرض"</string>
     <string name="always_use_device" msgid="1450287437017315906">"الاستخدام بشكل افتراضي لجهاز USB هذا"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"الاستخدام بشكل افتراضي لملحق USB هذا"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"تكبير/تصغير لملء الشاشة"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"توسيع بملء الشاشة"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"تكبير/تصغير التوافق"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"عند تصميم تطبيق لشاشة أصغر، سيظهر عنصر تحكم في التكبير/التصغير بجوار الساعة."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 1d7f558..20748ee 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Преглед"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Използване по подразб. за това USB устройство"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Използване по подразб. за този аксесоар за USB"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Мащаб – запълва екрана"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Разпъване – запълва екрана"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Промяна на мащаба за съвместимост"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Когато дадено приложение е създадено за по-малък екран, до часовника ще се покаже управление за промяна на мащаба."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index d27cb81..c346184 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Mostra"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utilitza de manera predet. per al dispositiu USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utilitza de manera predet. per a l\'accessori USB"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zoom per omplir pantalla"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Estira per omplir pant."</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom de compatibilitat"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Quan una aplicació s\'hagi dissenyat per a una pantalla més petita, apareixerà un control de zoom al costat del rellotge."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index e82ad34..692dd4c 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Zobrazit"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pro toto zařízení USB použít jako výchozí"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pro toto periferní zařízení USB použít jako výchozí"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Přiblížit na celou obrazovku"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Na celou obrazovku"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilní přiblížení"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Pokud je aplikace navržena pro menší obrazovku, zobrazí se vedle hodin ovládací prvek přiblížení."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 2cdd3cc..bd1bd02 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Vis"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Brug som standard til denne USB-enhed"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Brug som standard til dette USB-tilbehør"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zoom til fuld skærm"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Stræk til fuld skærm"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilitetszoom"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Når en app er udviklet til en mindre skærm, vises der en zoomfunktion ved uret."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 6dc11d1..ed0bfa4 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Anzeigen"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Standardmäßig für dieses USB-Gerät verwenden"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Standardmäßig für dieses USB-Zubehör verwenden"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zoom auf Bildschirmgröße"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Auf Bildschirmgröße anpassen"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilitätszoom"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Wenn eine App für einen kleineren Bildschirm ausgelegt ist, wird ein Zoom-Steuerelement neben der Uhr angezeigt."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 6fd21ce..1d907c5 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Προβολή"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Χρήση από προεπιλογή για αυτή τη συσκευή USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Χρήση από προεπιλογή για αυτό το εξάρτημα USB"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Ζουμ σε πλήρη οθόνη"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Προβoλή σε πλήρη οθ."</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Ζουμ για συμβατότητα"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Όταν μια εφαρμογή έχει σχεδιαστεί για προβολή σε μικρότερη οθόνη, δίπλα από το ρολόι θα εμφανιστεί ένα στοιχείο ελέγχου ζουμ."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index a7962d2..cda0718 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -57,12 +57,8 @@
     <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string>
     <string name="compat_mode_help_header" msgid="7020175705401506719">"Compatibility Zoom"</string>
     <string name="compat_mode_help_body" msgid="4946726776359270040">"When an app was designed for a smaller screen, a zoom control will appear by the clock."</string>
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index a730459..fd16ccf 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Ver"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Se usa de forma predeterminada para este dispositivo USB."</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Se usa de forma predeterminada para este accesorio USB."</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ocupar la pantalla"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Estirar p/ ocupar la pantalla"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom de compatibilidad"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Cuando una aplicación fue diseñada para una pantalla más pequeña, aparece un control de zoom junto al reloj."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 3a489da..a57258a 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Ver"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Usar de forma predeterminada para este dispositivo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Usar de forma predeterminada para este accesorio USB"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ajustar"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Expandir para ajustar"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom de compatibilidad"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Si la aplicación se ha diseñado para una pantalla más pequeña, aparecerá un control de zoom junto al reloj."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 04e5d5f..95f1c75 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"مشاهده"</string>
     <string name="always_use_device" msgid="1450287437017315906">"استفاده به صورت پیش فرض برای این دستگاه USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"استفاده به صورت پیش فرض برای این دستگاه USB"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"بزرگنمایی برای پر کردن صفحه"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"گسترده کردن برای پر کردن صفحه"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"بزرگنمایی سازگاری"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"اگر یک برنامه برای صفحه کوچک تری طراحی شده باشد، یک کنترل بزرگنمایی توسط ساعت نشان داده می شود."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 0e20ecb..7bf504f 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Näytä"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Käytä oletuksena tällä USB-laitteella"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Käytä oletuksena tällä USB-lisälaitteella"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zoomaa koko näyttöön"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Venytä koko näyttöön"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Yhteensopivuustilan zoomaus"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Jos sovellus on suunniteltu pienemmälle näytölle, kellon viereen tulee näkyviin zoomaussäädin."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index d765570..c1daaa5 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Afficher"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utiliser par défaut pour ce périphérique USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utiliser par défaut pour cet accessoire USB"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zoomer pour remplir l\'écran"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Étirer pour remplir l\'écran"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom de compatibilité"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Si une application a été conçue pour un écran plus petit, une commande de zoom s\'affiche à côté de l\'horloge."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 9eccc49..decaacd 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Prikaži"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Koristi se prema zadanim postavkama za ovaj USB uređaj"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Koristi se prema zadanim postavkama za ovaj USB pribor"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zumiraj i ispuni zaslon"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Rastegni i ispuni zaslon"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilni zum"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Kada je aplikacija dizajnirana za manji zaslon, kontrole zumiranja prikazuju se pored sata."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 22b9bbb..696566f 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Megtekintés"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Alapértelmezett használat ehhez az USB-eszközhöz"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Alapértelmezett használat ehhez az USB-kiegészítőhöz"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Nagyítás a kitöltéshez"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Nyújtás kitöltéshez"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilitás -- nagyítás/kicsinyítés"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Ha egy alkalmazást kisebb képernyőre terveztek, akkor a nagyítás/kicsinyítés vezérlője az óra mellett jelenik meg."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 14ee7b6..78f29c1 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Lihat"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gunakan secara bawaan untuk perangkat USB ini"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gunakan secara bawaan untuk aksesori USB ini"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Perbesar utk mengisi layar"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Rentangkn utk mngisi layar"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom Kompatibilitas"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Saat apl dirancang untuk layar yang lebih kecil, kontrol zoom akan tampil di dekat jam."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index b85175f..8c6cd6d 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Visualizza"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Usa per impostazione predef. per dispositivo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Usa per impostazione predef. per accessorio USB"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zoom per riempire schermo"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Estendi per riemp. schermo"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom compatibilità"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Se un\'applicazione è stata progettata per uno schermo più piccolo, accanto all\'orologio viene visualizzato un controllo dello zoom."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 8f0a95a..511d49e 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"הצג"</string>
     <string name="always_use_device" msgid="1450287437017315906">"השתמש כברירת מחדל עבור התקן USB זה"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"השתמש כברירת מחדל עבור אביזר USB זה"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"הגדל תצוגה כדי למלא את המסך"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"מתח כדי למלא את המסך"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"שינוי מרחק מתצוגה לתאימות"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"כאשר יישום מיועד למסך קטן יותר, פקד של מרחק מתצוגה יופיע ליד השעון."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 39bf1f1..88611dd 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"表示"</string>
     <string name="always_use_device" msgid="1450287437017315906">"このUSBデバイスにデフォルトで使用する"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"このUSBアクセサリにデフォルトで使用する"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"画面サイズに合わせて拡大"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"画面サイズに合わせて拡大"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"互換ズーム"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"より小型の画面向けのアプリの場合は、ズームコントロールが時計のそばに表示されます。"</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 516bc63..4cc668a 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"보기"</string>
     <string name="always_use_device" msgid="1450287437017315906">"이 USB 기기에 기본값으로 사용"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"이 USB 액세서리에 기본값으로 사용"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"전체화면 모드로 확대"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"전체화면 모드로 확대"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"호환성 확대/축소"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"앱이 작은 화면에 맞도록 설계된 경우 시계 옆에 확대/축소 컨트롤이 표시됩니다."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 3e2733c..fbdba57 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Žiūrėti"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Šiam USB įreng. naudoti pagal numat. nustatymus"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Šiam USB priedui naudoti pagal numat. nustatymus"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Keisti mast., kad atit. ekr."</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Ištempti, kad atit. ekr."</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Suderinamumo mastelio keitimas"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Kai programa bus pritaikyta mažesniam ekranui, mastelio keitimo valdiklis bus parodytas šalia laikrodžio."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index a899170..37e3f92 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Skatīt"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pēc noklusējuma izmantot šai USB ierīcei"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pēc noklusējuma izmantot šim USB piederumam"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Tālumm., lai aizp. ekr."</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Stiepiet, lai aizp. ekr."</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Saderības tālummaiņa"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Ja lietotne ir paredzēta mazākam ekrānam, blakus pulkstenim tiks parādīta tālummaiņas vadīkla."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 06527d2..c24a8fb 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -61,12 +61,8 @@
     <skip />
     <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
     <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 90dee30..df92a70 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Vis"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Bruk som standard for denne USB-enheten"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Bruk som standard for dette USB-tilbehøret"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zoom for å fylle skjermen"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Strekk for å fylle skjerm"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilitets-zooming"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Når en app er utformet for en mindre skjerm, vises det en zoomkontroll ved klokken."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 92af8fd..518402f 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -39,7 +39,7 @@
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Meldingen"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recent"</string>
-    <string name="recent_tasks_empty" msgid="1905484479067697884">"Geen recente toepassingen."</string>
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Geen recente apps."</string>
     <string name="recent_tasks_app_label" msgid="3796483981246752469">"Apps"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth getetherd"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Invoermethoden configureren"</string>
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Weergeven"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Standaard gebruiken voor dit USB-apparaat"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Standaard gebruiken voor dit USB-accessoire"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zoom om scherm te vullen"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Rek uit v. schermvulling"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Compatibiliteitszoom"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Wanneer een app is ontworpen voor een kleiner scherm, wordt naast de klok een zoomknop weergegeven."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 14269df..c59df62 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Wyświetl"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Używaj domyślnie dla tego urządzenia USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Używaj domyślnie dla tego akcesorium USB"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Powiększ, aby wypełnić ekran"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Rozciągnij, aby wypełnić ekran"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Powiększenie w trybie zgodności"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Jeśli aplikacja została przystosowana do mniejszego ekranu, obok zegara zostanie wyświetlony element sterujący powiększeniem."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index eadfa4c..ee79283 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Ver"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utilizar por predefinição para este aparelho USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utilizar por predefinição para este acessório USB"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para preencher o ecrã"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Esticar p. caber em ec. int."</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Compatibilidade de zoom"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Sempre que uma aplicação tiver sido concebida para ecrãs mais pequenos, aparecerá um controlo de zoom junto ao relógio."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index c7d1edf..447cce1 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Visualizar"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Usar por padrão para este dispositivo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Usar por padrão para este acessório USB"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zoom p/ preencher a tela"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Ampliar p/ preencher tela"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom em modo de compatibilidade"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Quando um aplicativo é desenvolvido para uma tela menor, um controle de zoom é exibido perto do relógio."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 30f317c..2f23275 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -87,12 +87,8 @@
     <skip />
     <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
     <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index c204b82..07394ab 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Afişaţi"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utilizaţi în mod prestabilit pt. acest dispoz. USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Utiliz. în mod prestabilit pt. acest accesoriu USB"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zoom pt. a umple ecranul"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Înt. pt. a umple ecranul"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom de compatibilitate"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Atunci când o aplicaţie a fost concepută pentru un ecran mai mic, o comandă pentru mărire/micşorare va apărea alături de ceas."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index b9ac0cb..e4f3e83 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Просмотр"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Использовать по умолчанию для этого USB-устройства"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Использовать по умолчанию для этого USB-аксессуара"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Подогнать по размерам экрана"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Растянуть на весь экран"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Масштаб и совместимость"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Если приложение рассчитано на экран меньших размеров, рядом с часами появятся средства масштабирования."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index fcb6d14..f720662 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Zobraziť"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Pre toto zariadenie USB použiť ako predvolené"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Pre toto periférne zar. USB použiť ako predvolené"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Priblížiť na celú obrazovku"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Na celú obrazovku"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilné priblíženie"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Ak je aplikácia navrhnutá pre menšiu obrazovku, zobrazí sa vedľa hodín ovládací prvok priblíženia."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index e5e365b..37ecf50 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Prikaži"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Privzeto uporabi za to napravo USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Privzeto uporabi za ta dodatek USB"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Povečava čez cel zaslon"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Raztegnitev čez zaslon"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Povečava združljivosti"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Če je program izdelan za manjše zaslone, se ob uri pokaže kontrolnik za povečavo."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index c6cc7db..7290f4c 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Прикажи"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Користи подразумевано за овај USB уређај"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Користи подразумевано за овај USB додатак"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Зумирај на целом екрану"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Развуци на цео екран"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Компатибилно зумирање"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Када је апликација намењена мањем екрану, контрола зумирања приказује се поред сата."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 558f5f8..19c9a09 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Visa"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Använd som standard för den här USB-enheten"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Använd som standard för det här USB-tillbehöret"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Zooma för att fylla skärm"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Dra för att fylla skärmen"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom i kompatibilitetsläge"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"När en app är anpassad för en mindre skärm visas ett zoomreglage vid klockan."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 12d86e3..17ec8a1 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -77,12 +77,8 @@
     <skip />
     <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
     <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 942ce5b..15f3007 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"ดู"</string>
     <string name="always_use_device" msgid="1450287437017315906">"ใช้ค่าเริ่มต้นสำหรับอุปกรณ์ USB นี้"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"ใช้ค่าเริ่มต้นสำหรับอุปกรณ์เสริม USB นี้"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"ขยายจนเต็มหน้าจอ"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"ยืดจนเต็มหน้าจอ"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"ความเข้ากันได้ของการย่อ/ขยาย"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"สำหรับแอปพลิเคชันที่ออกแบบมาสำหรับหน้าจอขนาดเล็ก ตัวควบคุมการย่อ/ขยายจะปรากฏขึ้นข้างนาฬิกา"</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 4178e2e..93fdb6a 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Tingnan"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Gamitin bilang default para sa USB device"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Gamitin bilang default sa USB accessory na ito"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"I-zoom upang punan screen"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"I-stretch upang mapuno screen"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom sa Pagiging Tugma"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Kapag nakadisenyo ang isang app para sa mas maliit na screen, isang kontrol ng zoom ang lalabas sa may orasan."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index beeb56f..5ec11b6 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Görüntüle"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Bu USB cihazı için varsayılan olarak kullan"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Bu USB aksesuar için varsayılan olarak kullan"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Yakınlaştır (ekranı kaplasın)"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Genişlet (ekran kapansın)"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Uyumluluk Zum\'u"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Uygulama küçük bir ekran için tasarlanmışsa saatin yanında bir yakınlaştırma denetimi görünür."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 22529e6..759acdc 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Переглянути"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Використовувати за умовчанням для пристрою USB"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Використовувати за умовчанням для аксесуара USB"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"Масштабув. на весь екран"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Розтягнути на весь екран"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Елемент керування масштабом для сумісності"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Якщо програму призначено для менших екранів, елемент керування масштабом буде відображатися біля годинника."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 41975b8..af44600 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"Xem"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Sử dụng theo mặc định cho thiết bị USB này"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"Sử dụng theo mặc định cho phụ kiện USB này"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"T.phóng để lấp đầy m.hình"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"Giãn ra để lấp đầy m.hình"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"Thu phóng tương thích"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"Khi ứng dụng được thiết kế cho một màn hình nhỏ hơn, điều khiển thu phóng sẽ xuất hiện bên cạnh đồng hồ."</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index d87268d..201ecfa 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"查看"</string>
     <string name="always_use_device" msgid="1450287437017315906">"默认情况下用于该 USB 设备"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"默认情况下用于该 USB 配件"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"缩放以填满屏幕"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"拉伸以填满屏幕"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"兼容性缩放"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"如果应用程序是针对较小屏幕设计的,则时钟旁会显示缩放控件。"</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index bb14bd6..a46a909 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -53,20 +53,12 @@
     <string name="label_view" msgid="6304565553218192990">"查看"</string>
     <string name="always_use_device" msgid="1450287437017315906">"預設用於這個 USB 裝置"</string>
     <string name="always_use_accessory" msgid="1210954576979621596">"預設用於這個 USB 配件"</string>
-    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <string name="compat_mode_on" msgid="6623839244840638213">"放大為全螢幕"</string>
+    <string name="compat_mode_off" msgid="4434467572461327898">"放大為全螢幕"</string>
+    <string name="compat_mode_help_header" msgid="7020175705401506719">"相容性縮放"</string>
+    <string name="compat_mode_help_body" msgid="4946726776359270040">"執行專為較小螢幕設計的應用程式時,系統會在時鐘旁顯示縮放控制項。"</string>
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for compat_mode_off (4434467572461327898) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
-    <skip />
-    <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
-    <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
-    <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 7597c3a..01db97f 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -77,12 +77,8 @@
     <skip />
     <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
     <skip />
-    <!-- no translation found for usb_preference_title (6551050377388882787) -->
+    <!-- no translation found for screenshot_saving_toast (8592630119048713208) -->
     <skip />
-    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
-    <skip />
-    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
-    <skip />
-    <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+    <!-- no translation found for screenshot_failed_toast (655180965533683356) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 9341693..fd5fe7a 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -21,4 +21,5 @@
     <drawable name="notification_item_background_color">#ff000000</drawable>
     <drawable name="ticker_background_color">#ff1d1d1d</drawable>
     <drawable name="status_bar_background">#000000</drawable>
+    <drawable name="status_bar_recents_background">#b3000000</drawable>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 7a4ac5d..5298f2e 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -36,10 +36,6 @@
     <!-- Whether or not we show the number in the bar. -->
     <bool name="config_statusBarShowNumber">true</bool>
 
-    <!-- Whether a software navigation bar should be shown. NOTE: in the future this may be
-         autodetected from the Configuration. -->
-    <bool name="config_showNavigationBar">false</bool>
-
     <!-- How many icons may be shown at once in the system bar. Includes any
          slots that may be reused for things like IME control. -->
     <integer name="config_maxNotificationIcons">5</integer>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index fc35a48..da28e1e 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -40,7 +40,11 @@
     <dimen name="peek_window_y_offset">-12dp</dimen>
 
     <!-- thickness (height) of the navigation bar on phones that require it -->
-    <dimen name="navigation_bar_size">42dp</dimen>
+    <dimen name="navigation_bar_size">48dp</dimen>
+
+    <!-- thickness (height) of the dead zone at the top of the navigation bar,
+         reducing false presses on navbar buttons; approx 2mm -->
+    <dimen name="navigation_bar_deadzone_size">12dp</dimen>
 
     <!-- thickness (height) of each notification row, including any separators or padding -->
     <dimen name="notification_height">65dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 86e0cd0..882455e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -157,12 +157,8 @@
     <!-- Compatibility mode help screen: body text. [CHAR LIMIT=150] -->
     <string name="compat_mode_help_body">When an app was designed for a smaller screen, a zoom control will appear by the clock.</string>
 
-    <!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] -->
-    <string name="usb_preference_title">USB file transfer options</string>
-    <!-- Label for the MTP USB function in UsbPreferenceActivity. [CHAR LIMIT=50] -->
-    <string name="use_mtp_button_title">Mount as a media player (MTP)</string>
-    <!-- Label for the PTP USB function in UsbPreferenceActivity. [CHAR LIMIT=50] -->
-    <string name="use_ptp_button_title">Mount as a camera (PTP)</string>
-    <!-- Label for the installer CD image option in UsbPreferenceActivity. [CHAR LIMIT=50] -->
-    <string name="installer_cd_button_title">Install Android File Transfer application for Mac</string>
+    <!-- toast message displayed when a screenshot is saved to the Gallery. -->
+    <string name="screenshot_saving_toast">Screenshot saved to Gallery</string>
+    <!-- toast message displayed when we fail to take a screenshot. -->
+    <string name="screenshot_failed_toast">Could not save screenshot</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
index 49a65d8..37a9913 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java
@@ -18,7 +18,9 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
+import android.animation.AnimatorSet.Builder;
 import android.animation.ObjectAnimator;
+import android.graphics.drawable.Drawable;
 import android.util.Log;
 import android.util.Slog;
 import android.view.View;
@@ -78,14 +80,14 @@
                 ? new android.view.animation.AccelerateInterpolator(1.0f)
                 : new android.view.animation.DecelerateInterpolator(1.0f));
 
-        Animator bgAnim = ObjectAnimator.ofInt(mScrimView.getBackground(),
-                "alpha", appearing ? 0 : 255, appearing ? 255 : 0);
-
         mContentAnim = new AnimatorSet();
-        mContentAnim
-                .play(bgAnim)
-                .with(glowAnim)
-                .with(posAnim);
+        final Builder builder = mContentAnim.play(glowAnim).with(posAnim);
+        Drawable background = mScrimView.getBackground();
+        if (background != null) {
+            Animator bgAnim = ObjectAnimator.ofInt(background,
+                "alpha", appearing ? 0 : 255, appearing ? 255 : 0);
+            builder.with(bgAnim);
+        }
         mContentAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
         mContentAnim.addListener(this);
         if (mListener != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Constants.java b/packages/SystemUI/src/com/android/systemui/recent/Constants.java
new file mode 100644
index 0000000..8252a9f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/Constants.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recent;
+
+public class Constants {
+    static final int MAX_ESCAPE_ANIMATION_DURATION = 500; // in ms
+    static final int SNAP_BACK_DURATION = 250; // in ms
+    static final int ESCAPE_VELOCITY = 100; // speed of item required to "curate" it in dp/s
+    public static float ALPHA_FADE_START = 0.8f; // fraction of thumbnail width where fade starts
+    static final float ALPHA_FADE_END = 0.5f; // fraction of thumbnail width beyond which alpha->0
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
index 3dbcc59..f984aac 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
@@ -25,6 +25,7 @@
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.database.DataSetObserver;
 import android.graphics.RectF;
 import android.util.AttributeSet;
@@ -33,6 +34,7 @@
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.LinearInterpolator;
 import android.widget.HorizontalScrollView;
@@ -42,12 +44,9 @@
 
 public class RecentsHorizontalScrollView extends HorizontalScrollView
         implements View.OnClickListener, View.OnTouchListener {
-    private static final float FADE_CONSTANT = 0.5f;
-    private static final int SNAP_BACK_DURATION = 250;
-    private static final int ESCAPE_VELOCITY = 100; // speed of item required to "curate" it
-    private static final String TAG = RecentsPanelView.TAG;
-    private static final float THRESHHOLD = 50;
     private static final boolean DEBUG_INVALIDATE = false;
+    private static final String TAG = RecentsPanelView.TAG;
+    private static final boolean DEBUG = RecentsPanelView.DEBUG;
     private LinearLayout mLinearLayout;
     private ActivityDescriptionAdapter mAdapter;
     private RecentsCallback mCallback;
@@ -56,6 +55,8 @@
     private float mLastY;
     private boolean mDragging;
     private VelocityTracker mVelocityTracker;
+    private float mDensityScale;
+    private float mPagingTouchSlop;
 
     public RecentsHorizontalScrollView(Context context) {
         this(context, null);
@@ -63,6 +64,8 @@
 
     public RecentsHorizontalScrollView(Context context, AttributeSet attrs) {
         super(context, attrs, 0);
+        mDensityScale = getResources().getDisplayMetrics().density;
+        mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
     }
 
     private int scrollPositionOfMostRecent() {
@@ -101,7 +104,8 @@
 
             case MotionEvent.ACTION_MOVE:
                 float delta = ev.getY() - mLastY;
-                if (Math.abs(delta) > THRESHHOLD) {
+                if (DEBUG) Log.v(TAG, "ACTION_MOVE : " + delta);
+                if (Math.abs(delta) > mPagingTouchSlop) {
                     mDragging = true;
                 }
                 break;
@@ -114,13 +118,14 @@
     }
 
     private float getAlphaForOffset(View view, float thumbHeight) {
-        final float fadeHeight = FADE_CONSTANT * thumbHeight;
+        final float fadeHeight = Constants.ALPHA_FADE_END * thumbHeight;
         float result = 1.0f;
-        if (view.getY() >= thumbHeight) {
-            result = 1.0f - (view.getY() - thumbHeight) / fadeHeight;
-        } else if (view.getY() < 0.0f) {
-            result = 1.0f + (thumbHeight + view.getY()) / fadeHeight;
+        if (view.getY() >= thumbHeight * Constants.ALPHA_FADE_START) {
+            result = 1.0f - (view.getY() - thumbHeight * Constants.ALPHA_FADE_START) / fadeHeight;
+        } else if (view.getY() < thumbHeight * (1.0f - Constants.ALPHA_FADE_START)) {
+            result = 1.0f + (thumbHeight * Constants.ALPHA_FADE_START + view.getY()) / fadeHeight;
         }
+        if (DEBUG) Log.v(TAG, "FADE AMOUNT: " + result);
         return result;
     }
 
@@ -155,12 +160,13 @@
                     final float velocityY = velocityTracker.getYVelocity();
                     final float curY = animView.getY();
                     final float newY = (velocityY >= 0.0f ? 1 : -1) * animView.getHeight();
-
+                    final float maxVelocity = Constants.ESCAPE_VELOCITY * mDensityScale;
                     if (Math.abs(velocityY) > Math.abs(velocityX)
-                            && Math.abs(velocityY) > ESCAPE_VELOCITY
+                            && Math.abs(velocityY) > maxVelocity
                             && (velocityY >= 0.0f) == (animView.getY() >= 0)) {
-                        final long duration =
+                        long duration =
                             (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY));
+                        duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION);
                         anim = ObjectAnimator.ofFloat(animView, "y", curY, newY);
                         anim.setInterpolator(new LinearInterpolator());
                         final int swipeDirection = animView.getY() >= 0.0f ?
@@ -181,9 +187,10 @@
                         });
                         anim.setDuration(duration);
                     } else { // Animate back to position
-                        final long duration = Math.abs(velocityY) > 0.0f ?
+                        long duration = Math.abs(velocityY) > 0.0f ?
                                 (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY))
-                                : SNAP_BACK_DURATION;
+                                : Constants.SNAP_BACK_DURATION;
+                        duration = Math.min(duration, Constants.SNAP_BACK_DURATION);
                         anim = ObjectAnimator.ofFloat(animView, "y", animView.getY(), 0.0f);
                         anim.setInterpolator(new DecelerateInterpolator(2.0f));
                         anim.setDuration(duration);
@@ -241,8 +248,15 @@
         setOverScrollEffectPadding(leftPadding, 0);
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        mDensityScale = getResources().getDisplayMetrics().density;
+        mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+    }
+
     private void setOverScrollEffectPadding(int leftPadding, int i) {
-        // TODO Add to RecentsHorizontalScrollView
+        // TODO Add to (Vertical)ScrollView
     }
 
     @Override
@@ -255,7 +269,7 @@
         // This has to happen post-layout, so run it "in the future"
         post(new Runnable() {
             public void run() {
-                scrollTo(0, mLastScrollPosition);
+                scrollTo(mLastScrollPosition, 0);
             }
         });
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index b8dc63d..a55fe9c 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -318,7 +318,11 @@
     }
 
     private Drawable getFullResIcon(Resources resources, int iconId) {
-        return resources.getDrawableForDensity(iconId, mIconDpi);
+        try {
+            return resources.getDrawableForDensity(iconId, mIconDpi);
+        } catch (Resources.NotFoundException e) {
+            return getFullResDefaultActivityIcon();
+        }
     }
 
     private Drawable getFullResIcon(ResolveInfo info, PackageManager packageManager) {
@@ -413,11 +417,11 @@
         mActivityDescriptions = getRecentTasks();
         mListAdapter.notifyDataSetInvalidated();
         if (mActivityDescriptions.size() > 0) {
-            Log.v(TAG, "Showing " + mActivityDescriptions.size() + " apps");
+            if (DEBUG) Log.v(TAG, "Showing " + mActivityDescriptions.size() + " apps");
             updateUiElements(getResources().getConfiguration());
         } else {
             // Immediately hide this panel
-            Log.v(TAG, "Nothing to show");
+            if (DEBUG) Log.v(TAG, "Nothing to show");
             hide(false);
         }
     }
@@ -432,7 +436,7 @@
             paint.setAlpha(255);
             final int srcWidth = thumbnail.getWidth();
             final int srcHeight = thumbnail.getHeight();
-            Log.v(TAG, "Source thumb: " + srcWidth + "x" + srcHeight);
+            if (DEBUG) Log.v(TAG, "Source thumb: " + srcWidth + "x" + srcHeight);
             canvas.drawBitmap(thumbnail,
                     new Rect(0, 0, srcWidth-1, srcHeight-1),
                     new RectF(mGlowBitmapPaddingLeftPx, mGlowBitmapPaddingTopPx,
@@ -482,7 +486,7 @@
 
     public void handleSwipe(View view, int direction) {
         ActivityDescription ad = ((ViewHolder) view.getTag()).activityDescription;
-        Log.v(TAG, "Jettison " + ad.label);
+        if (DEBUG) Log.v(TAG, "Jettison " + ad.label);
         mActivityDescriptions.remove(ad);
 
         // Handled by widget containers to enable LayoutTransitions properly
@@ -496,7 +500,7 @@
         // the task.
         final ActivityManager am = (ActivityManager)
                 mContext.getSystemService(Context.ACTIVITY_SERVICE);
-        am.removeTask(ad.taskId, 0);
+        am.removeTask(ad.taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
     }
 
     public void handleLongPress(View selectedView) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index 6a962cb..27bb0b5 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -25,6 +25,7 @@
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.database.DataSetObserver;
 import android.graphics.RectF;
 import android.util.AttributeSet;
@@ -33,6 +34,7 @@
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.LinearInterpolator;
 import android.widget.LinearLayout;
@@ -42,12 +44,9 @@
 
 public class RecentsVerticalScrollView extends ScrollView
         implements View.OnClickListener, View.OnTouchListener {
-    private static final float FADE_CONSTANT = 0.5f;
-    private static final int SNAP_BACK_DURATION = 250;
-    private static final int ESCAPE_VELOCITY = 100; // speed of item required to "curate" it
     private static final String TAG = RecentsPanelView.TAG;
-    private static final float THRESHHOLD = 50;
     private static final boolean DEBUG_INVALIDATE = false;
+    private static final boolean DEBUG = RecentsPanelView.DEBUG;
     private LinearLayout mLinearLayout;
     private ActivityDescriptionAdapter mAdapter;
     private RecentsCallback mCallback;
@@ -56,6 +55,8 @@
     private float mLastX;
     private boolean mDragging;
     private VelocityTracker mVelocityTracker;
+    private float mDensityScale;
+    private float mPagingTouchSlop;
 
     public RecentsVerticalScrollView(Context context) {
         this(context, null);
@@ -63,6 +64,8 @@
 
     public RecentsVerticalScrollView(Context context, AttributeSet attrs) {
         super(context, attrs, 0);
+        mDensityScale = getResources().getDisplayMetrics().density;
+        mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
     }
 
     private int scrollPositionOfMostRecent() {
@@ -101,8 +104,8 @@
 
             case MotionEvent.ACTION_MOVE:
                 float delta = ev.getX() - mLastX;
-                Log.v(TAG, "ACTION_MOVE : " + delta);
-                if (Math.abs(delta) > THRESHHOLD) {
+                if (DEBUG) Log.v(TAG, "ACTION_MOVE : " + delta);
+                if (Math.abs(delta) > mPagingTouchSlop) {
                     mDragging = true;
                 }
                 break;
@@ -115,14 +118,14 @@
     }
 
     private float getAlphaForOffset(View view, float thumbWidth) {
-        final float fadeWidth = FADE_CONSTANT * thumbWidth;
+        final float fadeWidth = Constants.ALPHA_FADE_END * thumbWidth;
         float result = 1.0f;
-        if (view.getX() >= thumbWidth) {
-            result = 1.0f - (view.getX() - thumbWidth) / fadeWidth;
-        } else if (view.getX() < 0.0f) {
-            result = 1.0f + (thumbWidth + view.getX()) / fadeWidth;
+        if (view.getX() >= thumbWidth*Constants.ALPHA_FADE_START) {
+            result = 1.0f - (view.getX() - thumbWidth*Constants.ALPHA_FADE_START) / fadeWidth;
+        } else if (view.getX() < thumbWidth* (1.0f - Constants.ALPHA_FADE_START)) {
+            result = 1.0f + (thumbWidth*Constants.ALPHA_FADE_START + view.getX()) / fadeWidth;
         }
-        Log.v(TAG, "FADE AMOUNT: " + result);
+        if (DEBUG) Log.v(TAG, "FADE AMOUNT: " + result);
         return result;
     }
 
@@ -157,12 +160,13 @@
                     final float velocityY = velocityTracker.getYVelocity();
                     final float curX = animView.getX();
                     final float newX = (velocityX >= 0.0f ? 1 : -1) * animView.getWidth();
-
+                    final float maxVelocity = Constants.ESCAPE_VELOCITY * mDensityScale;
                     if (Math.abs(velocityX) > Math.abs(velocityY)
-                            && Math.abs(velocityX) > ESCAPE_VELOCITY
+                            && Math.abs(velocityX) > maxVelocity
                             && (velocityX > 0.0f) == (animView.getX() >= 0)) {
-                        final long duration =
+                        long duration =
                             (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX));
+                        duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION);
                         anim = ObjectAnimator.ofFloat(animView, "x", curX, newX);
                         anim.setInterpolator(new LinearInterpolator());
                         final int swipeDirection = animView.getX() >= 0.0f ?
@@ -183,9 +187,10 @@
                         });
                         anim.setDuration(duration);
                     } else { // Animate back to position
-                        final long duration = Math.abs(velocityX) > 0.0f ?
+                        long duration = Math.abs(velocityX) > 0.0f ?
                                 (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX))
-                                : SNAP_BACK_DURATION;
+                                : Constants.SNAP_BACK_DURATION;
+                        duration = Math.min(duration, Constants.SNAP_BACK_DURATION);
                         anim = ObjectAnimator.ofFloat(animView, "x", animView.getX(), 0.0f);
                         anim.setInterpolator(new DecelerateInterpolator(4.0f));
                         anim.setDuration(duration);
@@ -243,6 +248,13 @@
         setOverScrollEffectPadding(leftPadding, 0);
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        mDensityScale = getResources().getDisplayMetrics().density;
+        mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+    }
+
     private void setOverScrollEffectPadding(int leftPadding, int i) {
         // TODO Add to (Vertical)ScrollView
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
new file mode 100644
index 0000000..83a5578
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.app.Activity;
+import android.content.ContentValues;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.PixelFormat;
+import android.media.MediaScannerConnection;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Binder;
+import android.os.Environment;
+import android.os.ServiceManager;
+import android.provider.MediaStore;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Display;
+import android.view.IWindowManager;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.systemui.R;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.Thread;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * POD used in the AsyncTask which saves an image in the background.
+ */
+class SaveImageInBackgroundData {
+    Context context;
+    Bitmap image;
+    int result;
+}
+
+/**
+ * An AsyncTask that saves an image to the media store in the background.
+ */
+class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Void,
+        SaveImageInBackgroundData> {
+    private static final String TAG = "SaveImageInBackgroundTask";
+    private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
+    private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/Screenshot_%s-%d.png";
+
+    @Override
+    protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) {
+        if (params.length != 1) return null;
+
+        Context context = params[0].context;
+        Bitmap image = params[0].image;
+
+        try{
+            long currentTime = System.currentTimeMillis();
+            String date = new SimpleDateFormat("MM-dd-yy-kk-mm-ss").format(new Date(currentTime));
+            String imageDir = Environment.getExternalStoragePublicDirectory(
+                    Environment.DIRECTORY_PICTURES).getAbsolutePath();
+            String imageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE,
+                    imageDir, SCREENSHOTS_DIR_NAME,
+                    date, currentTime % 1000);
+
+            // Save the screenshot to the MediaStore
+            ContentValues values = new ContentValues();
+            values.put(MediaStore.Images.ImageColumns.DATA, imageFilePath);
+            values.put(MediaStore.Images.ImageColumns.TITLE, "Screenshot");
+            values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, "Screenshot");
+            values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, currentTime);
+            values.put(MediaStore.Images.ImageColumns.DATE_ADDED, currentTime);
+            values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, currentTime);
+            values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png");
+            Uri uri = context.getContentResolver().insert(
+                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
+
+            OutputStream out = context.getContentResolver().openOutputStream(uri);
+            image.compress(Bitmap.CompressFormat.PNG, 100, out);
+            out.flush();
+            out.close();
+
+            params[0].result = 0;
+        }catch(IOException e){
+            params[0].result = 1;
+        }
+
+        return params[0];
+    };
+
+    @Override
+    protected void onPostExecute(SaveImageInBackgroundData params) {
+        if (params.result > 0) {
+            // Show a message that we've failed to save the image to disk
+            Toast.makeText(params.context, R.string.screenshot_failed_toast,
+                    Toast.LENGTH_SHORT).show();
+        } else {
+            // Show a message that we've saved the screenshot to disk
+            Toast.makeText(params.context, R.string.screenshot_saving_toast,
+                    Toast.LENGTH_SHORT).show();
+        }
+    };
+}
+
+/**
+ * TODO:
+ *   - Performance when over gl surfaces? Ie. Gallery
+ *   - what do we say in the Toast? Which icon do we get if the user uses another
+ *     type of gallery?
+ */
+class GlobalScreenshot {
+    private static final String TAG = "GlobalScreenshot";
+    private static final int SCREENSHOT_FADE_IN_DURATION = 900;
+    private static final int SCREENSHOT_FADE_OUT_DELAY = 1000;
+    private static final int SCREENSHOT_FADE_OUT_DURATION = 450;
+    private static final int TOAST_FADE_IN_DURATION = 500;
+    private static final int TOAST_FADE_OUT_DELAY = 1000;
+    private static final int TOAST_FADE_OUT_DURATION = 500;
+    private static final float BACKGROUND_ALPHA = 0.65f;
+    private static final float SCREENSHOT_SCALE = 0.85f;
+    private static final float SCREENSHOT_MIN_SCALE = 0.7f;
+    private static final float SCREENSHOT_ROTATION = -6.75f; // -12.5f;
+
+    private Context mContext;
+    private LayoutInflater mLayoutInflater;
+    private IWindowManager mIWindowManager;
+    private WindowManager mWindowManager;
+    private WindowManager.LayoutParams mWindowLayoutParams;
+    private Display mDisplay;
+    private DisplayMetrics mDisplayMetrics;
+    private Matrix mDisplayMatrix;
+
+    private Bitmap mScreenBitmap;
+    private View mScreenshotLayout;
+    private ImageView mBackgroundView;
+    private FrameLayout mScreenshotContainerView;
+    private ImageView mScreenshotView;
+
+    private AnimatorSet mScreenshotAnimation;
+
+    // General use cubic interpolator
+    final TimeInterpolator mCubicInterpolator = new TimeInterpolator() {
+        public float getInterpolation(float t) {
+            return t*t*t;
+        }
+    };
+    // The interpolator used to control the background alpha at the start of the animation
+    final TimeInterpolator mBackgroundViewAlphaInterpolator = new TimeInterpolator() {
+        public float getInterpolation(float t) {
+            float tStep = 0.35f;
+            if (t < tStep) {
+                return t * (1f / tStep);
+            } else {
+                return 1f;
+            }
+        }
+    };
+
+    /**
+     * @param context everything needs a context :(
+     */
+    public GlobalScreenshot(Context context) {
+        mContext = context;
+        mLayoutInflater = (LayoutInflater)
+                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+        // Inflate the screenshot layout
+        mDisplayMetrics = new DisplayMetrics();
+        mDisplayMatrix = new Matrix();
+        mScreenshotLayout = mLayoutInflater.inflate(R.layout.global_screenshot, null);
+        mBackgroundView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_background);
+        mScreenshotContainerView = (FrameLayout) mScreenshotLayout.findViewById(R.id.global_screenshot_container);
+        mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot);
+        mScreenshotLayout.setFocusable(true);
+        mScreenshotLayout.setOnTouchListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                // Intercept and ignore all touch events
+                return true;
+            }
+        });
+
+        // Setup the window that we are going to use
+        mIWindowManager = IWindowManager.Stub.asInterface(
+                ServiceManager.getService(Context.WINDOW_SERVICE));
+        mWindowLayoutParams = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
+                WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
+                WindowManager.LayoutParams.FLAG_FULLSCREEN
+                    | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
+                    | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED_SYSTEM
+                    | WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING
+                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                    | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
+                PixelFormat.TRANSLUCENT);
+        mWindowLayoutParams.token = new Binder();
+        mWindowLayoutParams.setTitle("ScreenshotAnimation");
+        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        mDisplay = mWindowManager.getDefaultDisplay();
+    }
+
+    /**
+     * Creates a new worker thread and saves the screenshot to the media store.
+     */
+    private void saveScreenshotInWorkerThread() {
+        SaveImageInBackgroundData data = new SaveImageInBackgroundData();
+        data.context = mContext;
+        data.image = mScreenBitmap;
+        new SaveImageInBackgroundTask().execute(data);
+    }
+
+    /**
+     * @return the current display rotation in degrees
+     */
+    private float getDegreesForRotation(int value) {
+        switch (value) {
+        case Surface.ROTATION_90:
+            return 90f;
+        case Surface.ROTATION_180:
+            return 180f;
+        case Surface.ROTATION_270:
+            return 270f;
+        }
+        return 0f;
+    }
+
+    /**
+     * Takes a screenshot of the current display and shows an animation.
+     */
+    void takeScreenshot() {
+        // We need to orient the screenshot correctly (and the Surface api seems to take screenshots
+        // only in the natural orientation of the device :!)
+        mDisplay.getRealMetrics(mDisplayMetrics);
+        float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels};
+        float degrees = getDegreesForRotation(mDisplay.getRotation());
+        boolean requiresRotation = (degrees > 0);
+        if (requiresRotation) {
+            // Get the dimensions of the device in its native orientation
+            mDisplayMatrix.reset();
+            mDisplayMatrix.preRotate(-degrees);
+            mDisplayMatrix.mapPoints(dims);
+            dims[0] = Math.abs(dims[0]);
+            dims[1] = Math.abs(dims[1]);
+        }
+        mScreenBitmap = Surface.screenshot((int) dims[0], (int) dims[1]);
+        if (requiresRotation) {
+            // Rotate the screenshot to the current orientation
+            Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels,
+                    mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888);
+            Canvas c = new Canvas(ss);
+            c.translate(ss.getWidth() / 2, ss.getHeight() / 2);
+            c.rotate(360f - degrees);
+            c.translate(-dims[0] / 2, -dims[1] / 2);
+            c.drawBitmap(mScreenBitmap, 0, 0, null);
+            mScreenBitmap = ss;
+        }
+
+        // If we couldn't take the screenshot, notify the user
+        if (mScreenBitmap == null) {
+            Toast.makeText(mContext, R.string.screenshot_failed_toast,
+                    Toast.LENGTH_SHORT).show();
+            return;
+        }
+
+        // Start the post-screenshot animation
+        startAnimation();
+    }
+
+
+    /**
+     * Starts the animation after taking the screenshot
+     */
+    private void startAnimation() {
+        // Add the view for the animation
+        mScreenshotView.setImageBitmap(mScreenBitmap);
+        mScreenshotLayout.requestFocus();
+
+        // Setup the animation with the screenshot just taken
+        if (mScreenshotAnimation != null) {
+            mScreenshotAnimation.end();
+        }
+
+        mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
+        ValueAnimator screenshotFadeInAnim = createScreenshotFadeInAnimation();
+        ValueAnimator screenshotFadeOutAnim = createScreenshotFadeOutAnimation();
+        mScreenshotAnimation = new AnimatorSet();
+        mScreenshotAnimation.play(screenshotFadeInAnim).before(screenshotFadeOutAnim);
+        mScreenshotAnimation.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                // Save the screenshot once we have a bit of time now
+                saveScreenshotInWorkerThread();
+
+                mWindowManager.removeView(mScreenshotLayout);
+            }
+        });
+        mScreenshotAnimation.start();
+    }
+    private ValueAnimator createScreenshotFadeInAnimation() {
+        ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
+        anim.setInterpolator(mCubicInterpolator);
+        anim.setDuration(SCREENSHOT_FADE_IN_DURATION);
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mBackgroundView.setVisibility(View.VISIBLE);
+                mScreenshotContainerView.setVisibility(View.VISIBLE);
+            }
+        });
+        anim.addUpdateListener(new AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float t = ((Float) animation.getAnimatedValue()).floatValue();
+                mBackgroundView.setAlpha(mBackgroundViewAlphaInterpolator.getInterpolation(t) *
+                        BACKGROUND_ALPHA);
+                float scaleT = SCREENSHOT_SCALE + (1f - t) * SCREENSHOT_SCALE;
+                mScreenshotContainerView.setAlpha(t*t*t*t);
+                mScreenshotContainerView.setScaleX(scaleT);
+                mScreenshotContainerView.setScaleY(scaleT);
+                mScreenshotContainerView.setRotation(t * SCREENSHOT_ROTATION);
+            }
+        });
+        return anim;
+    }
+    private ValueAnimator createScreenshotFadeOutAnimation() {
+        ValueAnimator anim = ValueAnimator.ofFloat(1f, 0f);
+        anim.setInterpolator(mCubicInterpolator);
+        anim.setStartDelay(SCREENSHOT_FADE_OUT_DELAY);
+        anim.setDuration(SCREENSHOT_FADE_OUT_DURATION);
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mBackgroundView.setVisibility(View.GONE);
+                mScreenshotContainerView.setVisibility(View.GONE);
+            }
+        });
+        anim.addUpdateListener(new AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float t = ((Float) animation.getAnimatedValue()).floatValue();
+                float scaleT = SCREENSHOT_MIN_SCALE +
+                        t*(SCREENSHOT_SCALE - SCREENSHOT_MIN_SCALE);
+                mScreenshotContainerView.setAlpha(t);
+                mScreenshotContainerView.setScaleX(scaleT);
+                mScreenshotContainerView.setScaleY(scaleT);
+                mBackgroundView.setAlpha(t * t * BACKGROUND_ALPHA);
+            }
+        });
+        return anim;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
new file mode 100644
index 0000000..35eaedf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot;
+
+import android.app.Service;
+import android.app.AlertDialog;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+
+import com.android.internal.app.AlertActivity;
+import com.android.internal.app.AlertController;
+
+import com.android.systemui.R;
+
+public class TakeScreenshotService extends Service {
+    private static final String TAG = "TakeScreenshotService";
+
+    private static GlobalScreenshot mScreenshot;
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (mScreenshot == null) {
+            mScreenshot = new GlobalScreenshot(this);
+        }
+        mScreenshot.takeScreenshot();
+        return null;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 7dafb89..550fc57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -36,14 +36,24 @@
 import com.android.systemui.R;
 
 public class NavigationBarView extends LinearLayout {
+    final static boolean DEBUG_DEADZONE = false;
+
     final static boolean NAVBAR_ALWAYS_AT_RIGHT = true;
 
     protected IStatusBarService mBarService;
     final Display mDisplay;
+    View mCurrentView = null;
     View[] mRotatedViews = new View[4];
-    View mBackground;
     Animator mLastAnimator = null;
 
+    public View getRecentsButton() {
+        return mCurrentView.findViewById(R.id.recent_apps);
+    }
+
+    public View getMenuButton() {
+        return mCurrentView.findViewById(R.id.menu);
+    }
+
     public NavigationBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mDisplay = ((WindowManager)context.getSystemService(
@@ -65,13 +75,13 @@
     }
 
     private void setLights(final boolean on) {
-        float oldAlpha = mBackground.getAlpha();
+        float oldAlpha = mCurrentView.getAlpha();
         android.util.Log.d("NavigationBarView", "animating alpha: " + oldAlpha + " -> "
             + (on ? 1f : 0f));
 
         if (mLastAnimator != null && mLastAnimator.isRunning()) mLastAnimator.cancel();
 
-        mLastAnimator = ObjectAnimator.ofFloat(mBackground, "alpha", oldAlpha, on ? 1f : 0f)
+        mLastAnimator = ObjectAnimator.ofFloat(mCurrentView, "alpha", oldAlpha, on ? 1f : 0f)
             .setDuration(on ? 250 : 1500);
         mLastAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
@@ -83,8 +93,6 @@
     }
 
     public void onFinishInflate() {
-        mBackground = findViewById(R.id.background);
-
         mRotatedViews[Surface.ROTATION_0] = 
         mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
 
@@ -93,6 +101,8 @@
         mRotatedViews[Surface.ROTATION_270] = NAVBAR_ALWAYS_AT_RIGHT
                                                 ? findViewById(R.id.rot90)
                                                 : findViewById(R.id.rot270);
+
+        mCurrentView = mRotatedViews[Surface.ROTATION_0];
     }
 
     @Override
@@ -107,7 +117,12 @@
         for (int i=0; i<4; i++) {
             mRotatedViews[i].setVisibility(View.GONE);
         }
-        mRotatedViews[rot].setVisibility(View.VISIBLE);
+        mCurrentView = mRotatedViews[rot];
+        mCurrentView.setVisibility(View.VISIBLE);
+
+        if (DEBUG_DEADZONE) {
+            mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF);
+        }
 
         android.util.Log.d("NavigationBarView", "reorient(): rot=" + mDisplay.getRotation());
     }
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 f3c2623..b50fd81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -53,6 +53,7 @@
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
@@ -246,7 +247,7 @@
         mIntruderAlertView.setClickable(true);
 
         try {
-            boolean showNav = res.getBoolean(R.bool.config_showNavigationBar);
+            boolean showNav = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
             if (showNav) {
                 mNavigationBarView = 
                     (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);
@@ -306,7 +307,7 @@
         mDateView.setVisibility(View.INVISIBLE);
 
         // Recents Panel
-        initializeRecentsPanel();
+        updateRecentsPanel();
 
         // receive broadcasts
         IntentFilter filter = new IntentFilter();
@@ -318,11 +319,11 @@
         return sb;
     }
 
-    protected WindowManager.LayoutParams getRecentsLayoutParams() {
+    protected WindowManager.LayoutParams getRecentsLayoutParams(LayoutParams layoutParams) {
         boolean translucent = false;
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                ViewGroup.LayoutParams.WRAP_CONTENT,
-                ViewGroup.LayoutParams.WRAP_CONTENT,
+                layoutParams.width,
+                layoutParams.height,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
@@ -337,20 +338,23 @@
         return lp;
     }
 
-    protected void initializeRecentsPanel() {
+    protected void updateRecentsPanel() {
         // Recents Panel
         boolean visible = false;
         if (mRecentsPanel != null) {
             visible = mRecentsPanel.getVisibility() == View.VISIBLE;
             WindowManagerImpl.getDefault().removeView(mRecentsPanel);
         }
-        mRecentsPanel = (RecentsPanelView) View.inflate(mContext,
-                R.layout.status_bar_recent_panel, null);
+
+        // Provide RecentsPanelView with a temporary parent to allow layout params to work.
+        LinearLayout tmpRoot = new LinearLayout(mContext);
+        mRecentsPanel = (RecentsPanelView) LayoutInflater.from(mContext).inflate(
+                R.layout.status_bar_recent_panel, tmpRoot, false);
 
         mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL,
                 mRecentsPanel));
         mRecentsPanel.setVisibility(View.GONE);
-        WindowManager.LayoutParams lp = getRecentsLayoutParams();
+        WindowManager.LayoutParams lp = getRecentsLayoutParams(mRecentsPanel.getLayoutParams());
 
         WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
         mRecentsPanel.setBar(this);
@@ -372,19 +376,31 @@
         return res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
     }
 
+    private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
+        public void onClick(View v) {
+            toggleRecentApps();
+        }
+    };
+
     // For small-screen devices (read: phones) that lack hardware navigation buttons
     private void addNavigationBar() {
         if (mNavigationBarView == null) return;
-        
+
         mNavigationBarView.reorient();
+
+        mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
+
         WindowManagerImpl.getDefault().addView(
                 mNavigationBarView, getNavigationBarLayoutParams());
     }
 
     private void repositionNavigationBar() {
         if (mNavigationBarView == null) return;
-        
+
         mNavigationBarView.reorient();
+
+        mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
+
         WindowManagerImpl.getDefault().updateViewLayout(
                 mNavigationBarView, getNavigationBarLayoutParams());
     }
@@ -640,7 +656,7 @@
 
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
-        initializeRecentsPanel();
+        updateRecentsPanel();
     }
 
 
@@ -1230,8 +1246,20 @@
         }
     }
 
+    public void topAppWindowChanged(boolean showMenu) {
+        if (DEBUG) {
+            Slog.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
+        }
+        if (mNavigationBarView != null) {
+            mNavigationBarView.getMenuButton().setVisibility(showMenu
+                ? View.VISIBLE : View.INVISIBLE);
+        }
+
+        // See above re: lights-out policy for legacy apps.
+        if (showMenu) setLightsOn(true);
+    }
+
     // Not supported
-    public void topAppWindowChanged(boolean visible) { }
     public void setImeWindowStatus(IBinder token, int vis, int backDisposition) { }
     @Override
     public void setHardKeyboardStatus(boolean available, boolean enabled) { }
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 fe279c8..df09f84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -1001,14 +1001,14 @@
         mHandler.sendEmptyMessage(on ? MSG_SHOW_CHROME : MSG_HIDE_CHROME);
     }
 
-    public void topAppWindowChanged(boolean windowVisible) {
+    public void topAppWindowChanged(boolean showMenu) {
         if (DEBUG) {
-            Slog.d(TAG, (windowVisible?"showing":"hiding") + " the MENU button");
+            Slog.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
         }
-        mMenuButton.setVisibility(windowVisible ? View.VISIBLE : View.GONE);
+        mMenuButton.setVisibility(showMenu ? View.VISIBLE : View.GONE);
 
         // See above re: lights-out policy for legacy apps.
-        if (windowVisible) setLightsOn(true);
+        if (showMenu) setLightsOn(true);
 
         mCompatModeButton.refresh();
         if (mCompatModeButton.getVisibility() == View.VISIBLE) {
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java
deleted file mode 100644
index 60906a1..0000000
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java
+++ /dev/null
@@ -1,96 +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 com.android.systemui.usb;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.hardware.usb.UsbManager;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.util.Log;
-import android.widget.Button;
-
-import java.io.File;
-
-import com.android.systemui.R;
-
-public class UsbPreferenceActivity extends Activity implements View.OnClickListener  {
-
-    private static final String TAG = "UsbPreferenceActivity";
-
-    private UsbManager mUsbManager;
-    private String mCurrentFunction;
-    private String[] mFunctions;
-    private String mInstallerImagePath;
-    private AlertDialog mDialog;
-    private Button mMtpPtpButton;
-    private Button mInstallerCdButton;
-    private boolean mPtpActive;
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
-
-        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
-        dialogBuilder.setTitle(getString(R.string.usb_preference_title));
-
-        LayoutInflater inflater = (LayoutInflater)getSystemService(
-                Context.LAYOUT_INFLATER_SERVICE);
-        View buttonView = inflater.inflate(R.layout.usb_preference_buttons, null);
-        dialogBuilder.setView(buttonView);
-        mMtpPtpButton = (Button)buttonView.findViewById(R.id.mtp_ptp_button);
-        mInstallerCdButton = (Button)buttonView.findViewById(R.id.installer_cd_button);
-        mMtpPtpButton.setOnClickListener(this);
-        mInstallerCdButton.setOnClickListener(this);
-
-        mPtpActive = mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_PTP);
-        if (mPtpActive) {
-            mMtpPtpButton.setText(R.string.use_mtp_button_title);
-        }
-
-        mInstallerImagePath = getString(com.android.internal.R.string.config_isoImagePath);
-        if (!(new File(mInstallerImagePath)).exists()) {
-            mInstallerCdButton.setVisibility(View.GONE);
-        }
-
-        mDialog = dialogBuilder.show();
-    }
-
-    public void onClick(View v) {
-        if (v.equals(mMtpPtpButton)) {
-            if (mPtpActive) {
-                mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP, true);
-            } else {
-                mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_PTP, true);
-            }
-        } else if (v.equals(mInstallerCdButton)) {
-            // installer CD is never default
-            mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MASS_STORAGE, false);
-            mUsbManager.setMassStorageBackingFile(mInstallerImagePath);
-        }
-
-        if (mDialog != null) {
-            mDialog.dismiss();
-        }
-        finish();

-    }
-}
diff --git a/packages/VpnDialogs/Android.mk b/packages/VpnDialogs/Android.mk
index 89f010a..ac84125 100644
--- a/packages/VpnDialogs/Android.mk
+++ b/packages/VpnDialogs/Android.mk
@@ -20,6 +20,8 @@
 
 LOCAL_MODULE_TAGS := optional
 
+LOCAL_CERTIFICATE := platform
+
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := VpnDialogs
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index 4e6784c..c0b0a08 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -1,5 +1,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.vpndialogs">
+        package="com.android.vpndialogs"
+        android:sharedUserId="android.uid.system">
 
     <application android:label="VpnDialogs">
         <activity android:name=".ConfirmDialog"
diff --git a/packages/VpnDialogs/res/layout/confirm.xml b/packages/VpnDialogs/res/layout/confirm.xml
index 249b6e6..5ab6ee2 100644
--- a/packages/VpnDialogs/res/layout/confirm.xml
+++ b/packages/VpnDialogs/res/layout/confirm.xml
@@ -17,7 +17,8 @@
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content">
+        android:layout_height="wrap_content"
+        android:padding="5mm">
 
     <ImageView android:id="@+id/icon"
             android:layout_width="@android:dimen/app_icon_size"
@@ -32,7 +33,7 @@
             android:layout_alignParentLeft="true"
             android:layout_alignParentRight="true"
             android:layout_below="@id/icon"
-            android:padding="2mm"
+            android:padding="3mm"
             android:text="@string/warning"
             android:textSize="18sp"/>
 
@@ -53,9 +54,7 @@
             android:layout_alignParentRight="true"
             android:layout_below="@id/warning"
             android:text="@string/accept"
-
-
-            android:textSize="18sp"
+            android:textSize="20sp"
             android:checked="false"/>
 
 </RelativeLayout>
diff --git a/packages/VpnDialogs/res/values/strings.xml b/packages/VpnDialogs/res/values/strings.xml
index 8186e26..df6d36b 100644
--- a/packages/VpnDialogs/res/values/strings.xml
+++ b/packages/VpnDialogs/res/values/strings.xml
@@ -29,6 +29,7 @@
 
     <string name="accept">I trust this application.</string>
 
+    <string name="legacy_title">VPN is connected</string>
     <string name="configure">Configure</string>
     <string name="disconnect">Disconnect</string>
 
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
index c54e719..c7b4a5f 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
@@ -36,7 +36,7 @@
         DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
     private static final String TAG = "VpnConfirm";
 
-    private String mPackageName;
+    private String mPackage;
 
     private IConnectivityManager mService;
 
@@ -47,19 +47,19 @@
     protected void onResume() {
         super.onResume();
         try {
-            mPackageName = getCallingPackage();
+            mPackage = getCallingPackage();
 
             mService = IConnectivityManager.Stub.asInterface(
                     ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
 
-            if (mPackageName.equals(mService.prepareVpn(null))) {
+            if (mService.prepareVpn(mPackage, null)) {
                 setResult(RESULT_OK);
                 finish();
                 return;
             }
 
             PackageManager pm = getPackageManager();
-            ApplicationInfo app = pm.getApplicationInfo(mPackageName, 0);
+            ApplicationInfo app = pm.getApplicationInfo(mPackage, 0);
 
             View view = View.inflate(this, R.layout.confirm, null);
             ((ImageView) view.findViewById(R.id.icon)).setImageDrawable(app.loadIcon(pm));
@@ -103,8 +103,7 @@
     @Override
     public void onClick(DialogInterface dialog, int which) {
         try {
-            if (which == AlertDialog.BUTTON_POSITIVE &&
-                    mPackageName.equals(mService.prepareVpn(mPackageName))) {
+            if (which == AlertDialog.BUTTON_POSITIVE && mService.prepareVpn(null, mPackage)) {
                 setResult(RESULT_OK);
             }
         } catch (Exception e) {
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
index ba3f344..21e916b 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
@@ -64,26 +64,36 @@
             mService = IConnectivityManager.Stub.asInterface(
                     ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
 
-            PackageManager pm = getPackageManager();
-            ApplicationInfo app = pm.getApplicationInfo(mConfig.packageName, 0);
-
             View view = View.inflate(this, R.layout.manage, null);
-            if (mConfig.sessionName != null) {
-                ((TextView) view.findViewById(R.id.session)).setText(mConfig.sessionName);
+            if (mConfig.session != null) {
+                ((TextView) view.findViewById(R.id.session)).setText(mConfig.session);
             }
             mDuration = (TextView) view.findViewById(R.id.duration);
             mDataTransmitted = (TextView) view.findViewById(R.id.data_transmitted);
             mDataReceived = (TextView) view.findViewById(R.id.data_received);
 
-            mDialog = new AlertDialog.Builder(this)
-                    .setIcon(app.loadIcon(pm))
-                    .setTitle(app.loadLabel(pm))
-                    .setView(view)
-                    .setNeutralButton(R.string.disconnect, this)
-                    .setNegativeButton(android.R.string.cancel, this)
-                    .create();
+            if (mConfig.packagz.equals(VpnConfig.LEGACY_VPN)) {
+                mDialog = new AlertDialog.Builder(this)
+                        .setIcon(android.R.drawable.ic_dialog_info)
+                        .setTitle(R.string.legacy_title)
+                        .setView(view)
+                        .setNeutralButton(R.string.disconnect, this)
+                        .setNegativeButton(android.R.string.cancel, this)
+                        .create();
+            } else {
+                PackageManager pm = getPackageManager();
+                ApplicationInfo app = pm.getApplicationInfo(mConfig.packagz, 0);
 
-            if (mConfig.configureActivity != null) {
+                mDialog = new AlertDialog.Builder(this)
+                        .setIcon(app.loadIcon(pm))
+                        .setTitle(app.loadLabel(pm))
+                        .setView(view)
+                        .setNeutralButton(R.string.disconnect, this)
+                        .setNegativeButton(android.R.string.cancel, this)
+                        .create();
+            }
+
+            if (mConfig.configureIntent != null) {
                 mDialog.setButton(DialogInterface.BUTTON_POSITIVE,
                         getText(R.string.configure), this);
             }
@@ -113,11 +123,9 @@
     public void onClick(DialogInterface dialog, int which) {
         try {
             if (which == AlertDialog.BUTTON_POSITIVE) {
-                Intent intent = new Intent();
-                intent.setClassName(mConfig.packageName, mConfig.configureActivity);
-                startActivity(intent);
+                mConfig.configureIntent.send();
             } else if (which == AlertDialog.BUTTON_NEUTRAL) {
-                mService.prepareVpn("");
+                mService.prepareVpn(mConfig.packagz, VpnConfig.LEGACY_VPN);
             }
         } catch (Exception e) {
             Log.e(TAG, "onClick", e);
@@ -161,7 +169,7 @@
         try {
             // See dev_seq_printf_stats() in net/core/dev.c.
             in = new DataInputStream(new FileInputStream("/proc/net/dev"));
-            String prefix = mConfig.interfaceName + ':';
+            String prefix = mConfig.interfaze + ':';
 
             while (true) {
                 String line = in.readLine().trim();
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index eea3040..b60bae7 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -682,8 +682,9 @@
             final boolean usingLockPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality()
                     == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
 
-            boolean showSlidingTab = getResources().getBoolean(R.bool.config_enableSlidingTabFirst);
-            if (isSecure() && (usingLockPattern || !showSlidingTab)) {
+            boolean showLockBeforeUnlock = getResources()
+                    .getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
+            if (isSecure() && (usingLockPattern || !showLockBeforeUnlock)) {
                 return Mode.UnlockScreen;
             } else {
                 return Mode.LockScreen;
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 8b7a61e..1c4084c 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -64,7 +64,6 @@
     private KeyguardUpdateMonitor mUpdateMonitor;
     private KeyguardScreenCallback mCallback;
 
-    private SlidingTab mSlidingTab;
     private TextView mScreenLocked;
     private TextView mEmergencyCallText;
     private Button mEmergencyCallButton;
@@ -89,11 +88,9 @@
     private boolean mEnableMenuKeyInLockScreen;
 
     private StatusView mStatusView;
-    private WaveView mEnergyWave;
-    private SlidingTabMethods mSlidingTabMethods;
-    private WaveViewMethods mWaveViewMethods;
-    private MultiWaveView mMultiWaveView;
-    private MultiWaveViewMethods mMultiWaveViewMethods;
+    private UnlockWidgetCommonMethods mUnlockWidgetMethods;
+    private View mUnlockWidget;
+
 
     /**
      * The status of this lock screen.
@@ -151,9 +148,28 @@
         }
     }
 
-    class SlidingTabMethods implements SlidingTab.OnTriggerListener {
+    private interface UnlockWidgetCommonMethods {
+        // Update resources based on phone state
+        public void updateResources();
 
-        private void updateRightTabResources() {
+        // Get the view associated with this widget
+        public View getView();
+
+        // Reset the view
+        public void reset(boolean animate);
+
+        // Animate the widget if it supports ping()
+        public void ping();
+    }
+
+    class SlidingTabMethods implements SlidingTab.OnTriggerListener, UnlockWidgetCommonMethods {
+        private final SlidingTab mSlidingTab;
+
+        SlidingTabMethods(SlidingTab slidingTab) {
+            mSlidingTab = slidingTab;
+        }
+
+        public void updateResources() {
             boolean vibe = mSilentMode
                 && (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
 
@@ -175,7 +191,6 @@
                 mCallback.goToUnlockScreen();
             } else if (whichHandle == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
                 toggleRingMode();
-                updateRightTabResources();
                 doSilenceRingToast();
                 mCallback.pokeWakelock();
             }
@@ -195,12 +210,29 @@
                 mCallback.pokeWakelock();
             }
         }
+
+        public View getView() {
+            return mSlidingTab;
+        }
+
+        public void reset(boolean animate) {
+            mSlidingTab.reset(animate);
+        }
+
+        public void ping() {
+        }
     }
 
     private static final int WAIT_FOR_ANIMATION_TIMEOUT = 0;
     private static final int STAY_ON_WHILE_GRABBED_TIMEOUT = 30000;
 
-    class WaveViewMethods implements WaveView.OnTriggerListener {
+    class WaveViewMethods implements WaveView.OnTriggerListener, UnlockWidgetCommonMethods {
+
+        private final WaveView mWaveView;
+
+        WaveViewMethods(WaveView waveView) {
+            mWaveView = waveView;
+        }
         /** {@inheritDoc} */
         public void onTrigger(View v, int whichHandle) {
             if (whichHandle == WaveView.OnTriggerListener.CENTER_HANDLE) {
@@ -210,8 +242,6 @@
 
         /** {@inheritDoc} */
         public void onGrabbedStateChange(View v, int grabbedState) {
-            if (DBG) Log.v(TAG, "*** LockScreen accel is "
-                    + (mEnergyWave.isHardwareAccelerated() ? "on":"off"));
             // Don't poke the wake lock when returning to a state where the handle is
             // not grabbed since that can happen when the system (instead of the user)
             // cancels the grab.
@@ -219,30 +249,51 @@
                 mCallback.pokeWakelock(STAY_ON_WHILE_GRABBED_TIMEOUT);
             }
         }
+
+        public void updateResources() {
+        }
+
+        public View getView() {
+            return mWaveView;
+        }
+        public void reset(boolean animate) {
+            mWaveView.reset();
+        }
+        public void ping() {
+        }
     }
 
-    class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener {
+    class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener,
+            UnlockWidgetCommonMethods {
+
+        private final MultiWaveView mMultiWaveView;
+
+        MultiWaveViewMethods(MultiWaveView multiWaveView) {
+            mMultiWaveView = multiWaveView;
+        }
+
+        public void updateResources() {
+            mMultiWaveView.setTargetResources(mSilentMode ? R.array.lockscreen_targets_when_silent
+                    : R.array.lockscreen_targets_when_soundon);
+        }
+
         public void onGrabbed(View v, int handle) {
 
         }
+
         public void onReleased(View v, int handle) {
 
         }
+
         public void onTrigger(View v, int target) {
             if (target == 0) { // TODO: Use resources to determine which handle was used
                 mCallback.goToUnlockScreen();
             } else if (target == 2) {
                 toggleRingMode();
-                updateResources();
                 doSilenceRingToast();
+                mUnlockWidgetMethods.updateResources();
                 mCallback.pokeWakelock();
             }
-
-        }
-
-        private void updateResources() {
-            mMultiWaveView.setTargetResources(mSilentMode ? R.array.lockscreen_targets_when_silent
-                    : R.array.lockscreen_targets_when_soundon);
         }
 
         public void onGrabbedStateChange(View v, int handle) {
@@ -253,6 +304,18 @@
                 mCallback.pokeWakelock();
             }
         }
+
+        public View getView() {
+            return mMultiWaveView;
+        }
+
+        public void reset(boolean animate) {
+            mMultiWaveView.reset(animate);
+        }
+
+        public void ping() {
+            mMultiWaveView.ping();
+        }
     }
 
     private void requestUnlockScreen() {
@@ -371,32 +434,39 @@
         mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
         mSilentMode = isSilentMode();
 
-        View unlockWidget = findViewById(R.id.unlock_widget);
-        if (unlockWidget instanceof SlidingTab) {
-            mSlidingTab = (SlidingTab) unlockWidget;
-            mSlidingTab.setHoldAfterTrigger(true, false);
-            mSlidingTab.setLeftHintText(R.string.lockscreen_unlock_label);
-            mSlidingTab.setLeftTabResources(
+        mUnlockWidget = findViewById(R.id.unlock_widget);
+        if (mUnlockWidget instanceof SlidingTab) {
+            SlidingTab slidingTabView = (SlidingTab) mUnlockWidget;
+            slidingTabView.setHoldAfterTrigger(true, false);
+            slidingTabView.setLeftHintText(R.string.lockscreen_unlock_label);
+            slidingTabView.setLeftTabResources(
                     R.drawable.ic_jog_dial_unlock,
                     R.drawable.jog_tab_target_green,
                     R.drawable.jog_tab_bar_left_unlock,
                     R.drawable.jog_tab_left_unlock);
-            mSlidingTabMethods = new SlidingTabMethods();
-            mSlidingTab.setOnTriggerListener(mSlidingTabMethods);
-            mSlidingTabMethods.updateRightTabResources();
-        } else if (unlockWidget instanceof WaveView) {
-            mEnergyWave = (WaveView) unlockWidget;
-            mWaveViewMethods = new WaveViewMethods();
-            mEnergyWave.setOnTriggerListener(mWaveViewMethods);
-        } else if (unlockWidget instanceof MultiWaveView) {
-            mMultiWaveView = (MultiWaveView) unlockWidget;
-            mMultiWaveViewMethods = new MultiWaveViewMethods();
-            mMultiWaveViewMethods.updateResources(); // update silence/ring resources
-            mMultiWaveView.setOnTriggerListener(mMultiWaveViewMethods);
+            SlidingTabMethods slidingTabMethods = new SlidingTabMethods(slidingTabView);
+            slidingTabView.setOnTriggerListener(slidingTabMethods);
+            mUnlockWidgetMethods = slidingTabMethods;
+        } else if (mUnlockWidget instanceof WaveView) {
+            WaveView waveView = (WaveView) mUnlockWidget;
+            WaveViewMethods waveViewMethods = new WaveViewMethods(waveView);
+            waveView.setOnTriggerListener(waveViewMethods);
+            mUnlockWidgetMethods = waveViewMethods;
+        } else if (mUnlockWidget instanceof MultiWaveView) {
+            MultiWaveView multiWaveView = (MultiWaveView) mUnlockWidget;
+            MultiWaveViewMethods multiWaveViewMethods = new MultiWaveViewMethods(multiWaveView);
+            multiWaveView.setOnTriggerListener(multiWaveViewMethods);
+            mUnlockWidgetMethods = multiWaveViewMethods;
         } else {
-            throw new IllegalStateException("Unrecognized unlock widget: " + unlockWidget);
+            throw new IllegalStateException("Unrecognized unlock widget: " + mUnlockWidget);
         }
 
+        // Update widget with initial ring state
+        mUnlockWidgetMethods.updateResources();
+
+        if (DBG) Log.v(TAG, "*** LockScreen accel is "
+                + (mUnlockWidget.isHardwareAccelerated() ? "on":"off"));
+
         resetStatusInfo(updateMonitor);
     }
 
@@ -540,16 +610,14 @@
      * Enables unlocking of this screen. Typically just shows the unlock widget.
      */
     private void enableUnlock() {
-        if (mEnergyWave != null) mEnergyWave.setVisibility(View.VISIBLE);
-        if (mSlidingTab != null) mSlidingTab.setVisibility(View.VISIBLE);
+        mUnlockWidgetMethods.getView().setVisibility(View.VISIBLE);
     }
 
     /**
      * Disable unlocking of this screen. Typically just hides the unlock widget.
      */
     private void disableUnlock() {
-        if (mEnergyWave != null) mEnergyWave.setVisibility(View.GONE);
-        if (mSlidingTab != null) mSlidingTab.setVisibility(View.GONE);
+        mUnlockWidgetMethods.getView().setVisibility(View.GONE);
     }
 
     /**
@@ -728,20 +796,13 @@
 
     /** {@inheritDoc} */
     public void onPause() {
-        if (mEnergyWave != null) {
-            mEnergyWave.reset();
-        }
-        if (mMultiWaveView != null) {
-            mMultiWaveView.reset(false);
-        }
+        mUnlockWidgetMethods.reset(false);
     }
 
     /** {@inheritDoc} */
     public void onResume() {
         resetStatusInfo(mUpdateMonitor);
-        if (mMultiWaveView != null) {
-            mMultiWaveView.ping();
-        }
+        mUnlockWidgetMethods.ping();
     }
 
     /** {@inheritDoc} */
@@ -757,7 +818,7 @@
         boolean silent = AudioManager.RINGER_MODE_NORMAL != state;
         if (silent != mSilentMode) {
             mSilentMode = silent;
-            if (mSlidingTabMethods != null) mSlidingTabMethods.updateRightTabResources();
+            mUnlockWidgetMethods.updateResources();
         }
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index f862d01..75e799c 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -29,7 +29,9 @@
 import android.os.SystemClock;
 import android.security.KeyStore;
 import android.telephony.TelephonyManager;
+import android.text.Editable;
 import android.text.InputType;
+import android.text.TextWatcher;
 import android.text.method.DigitsKeyListener;
 import android.text.method.TextKeyListener;
 import android.util.Log;
@@ -120,15 +122,6 @@
             }
         });
 
-        // We don't currently use the IME for PIN mode, but this will make it work if we ever do...
-        if (!mIsAlpha) {
-            mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
-                    | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
-        } else {
-            mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
-                    | InputType.TYPE_TEXT_VARIATION_PASSWORD);
-        }
-
         mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
         mEmergencyCallButton.setOnClickListener(this);
         mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
@@ -151,14 +144,17 @@
 
         mPasswordEntry.requestFocus();
 
-        // This allows keyboards with overlapping qwerty/numeric keys to choose just the
-        // numeric keys.
+        // This allows keyboards with overlapping qwerty/numeric keys to choose just numeric keys.
         if (mIsAlpha) {
             mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
+            mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
+                    | InputType.TYPE_TEXT_VARIATION_PASSWORD);
             // mStatusView.setHelpMessage(R.string.keyguard_password_enter_password_code,
             //      StatusView.LOCK_ICON);
         } else {
             mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
+            mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
+                    | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
             //mStatusView.setHelpMessage(R.string.keyguard_password_enter_pin_code,
             //      StatusView.LOCK_ICON);
         }
@@ -179,6 +175,19 @@
         //mUpdateMonitor.registerSimStateCallback(this);
 
         resetStatusInfo();
+
+        // Poke the wakelock any time the text is modified
+        mPasswordEntry.addTextChangedListener(new TextWatcher() {
+            public void onTextChanged(CharSequence s, int start, int before, int count) {
+            }
+
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+            }
+
+            public void afterTextChanged(Editable s) {
+                mCallback.pokeWakelock();
+            }
+        });
     }
 
     @Override
diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
index cd79b60..6573286 100644
--- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
@@ -183,8 +183,7 @@
 
         mStatusView = new StatusView(this, mUpdateMonitor, mLockPatternUtils);
         // This shows up when no other information is required on status1
-        mStatusView.setHelpMessage(R.string.lockscreen_pattern_instructions,
-                StatusView.LOCK_ICON);
+        //mStatusView.setHelpMessage(R.string.lockscreen_pattern_instructions,StatusView.LOCK_ICON);
 
         mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index b52e7e1..ad6cebb 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -28,6 +28,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.ServiceConnection;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.res.CompatibilityInfo;
@@ -372,6 +373,10 @@
     // What we do when the user long presses on home
     private int mLongPressOnHomeBehavior = -1;
 
+    // Screenshot trigger states
+    private boolean mVolumeDownTriggered;
+    private boolean mPowerDownTriggered;
+
     ShortcutManager mShortcutManager;
     PowerManager.WakeLock mBroadcastWakeLock;
 
@@ -2339,6 +2344,26 @@
         }
     }
 
+    private void takeScreenshot() {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                ComponentName cn = new ComponentName("com.android.systemui",
+                        "com.android.systemui.screenshot.TakeScreenshotService");
+                Intent intent = new Intent();
+                intent.setComponent(cn);
+                ServiceConnection conn = new ServiceConnection() {
+                    @Override
+                    public void onServiceConnected(ComponentName name, IBinder service) {}
+                    @Override
+                    public void onServiceDisconnected(ComponentName name) {}
+                };
+                mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE);
+                mContext.unbindService(conn);
+            }
+        });
+    }
+
     /** {@inheritDoc} */
     @Override
     public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
@@ -2398,6 +2423,24 @@
         // Handle special keys.
         switch (keyCode) {
             case KeyEvent.KEYCODE_VOLUME_DOWN:
+                if (down) {
+                    // If the power key down was already triggered, take the screenshot
+                    if (mPowerDownTriggered) {
+                        // Dismiss the power-key longpress
+                        mHandler.removeCallbacks(mPowerLongPress);
+                        mPowerKeyHandled = true;
+
+                        // Take the screenshot
+                        takeScreenshot();
+
+                        // Prevent the event from being passed through to the current activity
+                        result &= ~ACTION_PASS_TO_USER;
+                        break;
+                    }
+                    mVolumeDownTriggered = true;
+                } else {
+                    mVolumeDownTriggered = false;
+                }
             case KeyEvent.KEYCODE_VOLUME_UP:
             case KeyEvent.KEYCODE_VOLUME_MUTE: {
                 if (down) {
@@ -2478,6 +2521,18 @@
             case KeyEvent.KEYCODE_POWER: {
                 result &= ~ACTION_PASS_TO_USER;
                 if (down) {
+                    // If the volume down key has been triggered, then just take the screenshot
+                    if (mVolumeDownTriggered) {
+                        // Take the screenshot
+                        takeScreenshot();
+                        mPowerKeyHandled = true;
+
+                        // Prevent the event from being passed through to the current activity
+                        break;
+                    }
+                    mPowerDownTriggered = true;
+
+
                     ITelephony telephonyService = getTelephonyService();
                     boolean hungUp = false;
                     if (telephonyService != null) {
@@ -2499,6 +2554,7 @@
                     }
                     interceptPowerKeyDown(!isScreenOn || hungUp);
                 } else {
+                    mPowerDownTriggered = false;
                     if (interceptPowerKeyUp(canceled)) {
                         result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
                     }
diff --git a/policy/src/com/android/internal/policy/impl/StatusView.java b/policy/src/com/android/internal/policy/impl/StatusView.java
index 46ce5a3..79f81ff 100644
--- a/policy/src/com/android/internal/policy/impl/StatusView.java
+++ b/policy/src/com/android/internal/policy/impl/StatusView.java
@@ -40,7 +40,7 @@
 
     private String mInstructions = null;
     private TextView mStatus1;
-    private TextView mPropertyOf;
+    private TextView mOwnerInfo;
 
     private boolean mHasCarrier;
     private boolean mHasDate;
@@ -105,7 +105,7 @@
         mStatus1 = (TextView) findViewById(R.id.status1);
         mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
         mAlarmStatus.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0);
-        mPropertyOf = (TextView) findViewById(R.id.propertyOf);
+        mOwnerInfo = (TextView) findViewById(R.id.propertyOf);
 
         resetStatusInfo(updateMonitor, lockPatternUtils);
 
@@ -153,20 +153,22 @@
     void updateStatusLines(boolean showStatusLines) {
         if (!showStatusLines) {
             mStatus1.setVisibility(showStatusLines ? View.VISIBLE : View.INVISIBLE);
-            mAlarmStatus.setVisibility(showStatusLines ? View.VISIBLE : View.INVISIBLE);
+            mAlarmStatus.setVisibility(showStatusLines ? View.VISIBLE : View.GONE);
             return;
         }
 
         // Update owner info
-        if (mPropertyOf != null) {
-            ContentResolver res = getContext().getContentResolver();
-            String info = Settings.Secure.getString(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO);
-            boolean enabled = Settings.Secure.getInt(res,
-                    Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1) != 0;
-
-            mPropertyOf.setText(info);
-            mPropertyOf.setVisibility(enabled && !TextUtils.isEmpty(info) ?
-                    View.VISIBLE : View.INVISIBLE);
+        final ContentResolver res = getContext().getContentResolver();
+        final boolean ownerInfoEnabled = Settings.Secure.getInt(res,
+                Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1) != 0;
+        String ownerInfo = null;
+        if (ownerInfoEnabled) {
+            ownerInfo = Settings.Secure.getString(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO);
+            if (mOwnerInfo != null) {
+                mOwnerInfo.setText(ownerInfo);
+                mOwnerInfo.setVisibility(ownerInfoEnabled && !TextUtils.isEmpty(ownerInfo) ?
+                        View.VISIBLE : View.INVISIBLE);
+            }
         }
 
         // Update Alarm status
@@ -175,7 +177,7 @@
             mAlarmStatus.setText(nextAlarm);
             mAlarmStatus.setVisibility(View.VISIBLE);
         } else {
-            mAlarmStatus.setVisibility(View.INVISIBLE);
+            mAlarmStatus.setVisibility(View.GONE);
         }
 
         // Update Status1
@@ -204,15 +206,16 @@
             } else {
                 mStatus1.setVisibility(View.INVISIBLE);
             }
+        } else if (mHelpMessageId != 0) {
+            mStatus1.setText(mHelpMessageId);
+            mStatus1.setCompoundDrawablesWithIntrinsicBounds(mHelpIconId, 0,0, 0);
+            mStatus1.setVisibility(View.VISIBLE);
+        } else if (ownerInfoEnabled && mOwnerInfo == null && ownerInfo != null) {
+            mStatus1.setText(ownerInfo);
+            mStatus1.setCompoundDrawablesWithIntrinsicBounds(0, 0,0, 0);
+            mStatus1.setVisibility(View.VISIBLE);
         } else {
-            // nothing specific to show; show help message and icon, if provided
-            if (mHelpMessageId != 0) {
-                mStatus1.setText(mHelpMessageId);
-                mStatus1.setCompoundDrawablesWithIntrinsicBounds(mHelpIconId, 0,0, 0);
-                mStatus1.setVisibility(View.VISIBLE);
-            } else {
-                mStatus1.setVisibility(View.INVISIBLE);
-            }
+            mStatus1.setVisibility(View.INVISIBLE);
         }
     }
 
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 2222e8b..75d24a1 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -10,6 +10,9 @@
     AudioResamplerCubic.cpp.arm \
     AudioPolicyService.cpp
 
+LOCAL_C_INCLUDES := \
+    system/media/audio_effects/include
+
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libutils \
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index f716e63..daf94f2 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -50,7 +50,7 @@
 #include "AudioFlinger.h"
 
 #include <media/EffectsFactoryApi.h>
-#include <media/EffectVisualizerApi.h>
+#include <audio_effects/effect_visualizer.h>
 
 // ----------------------------------------------------------------------------
 
diff --git a/services/audioflinger/AudioResamplerCubic.cpp b/services/audioflinger/AudioResamplerCubic.cpp
index 1d247bd..4d721f6 100644
--- a/services/audioflinger/AudioResamplerCubic.cpp
+++ b/services/audioflinger/AudioResamplerCubic.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "AudioSRC"
+
 #include <stdint.h>
 #include <string.h>
 #include <sys/types.h>
@@ -22,8 +24,6 @@
 #include "AudioResampler.h"
 #include "AudioResamplerCubic.h"
 
-#define LOG_TAG "AudioSRC"
-
 namespace android {
 // ----------------------------------------------------------------------------
 
diff --git a/services/camera/libcameraservice/CameraHardwareInterface.h b/services/camera/libcameraservice/CameraHardwareInterface.h
index a3749cf..a583aad 100644
--- a/services/camera/libcameraservice/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/CameraHardwareInterface.h
@@ -559,13 +559,8 @@
         ANativeWindowBuffer* anb;
         rc = a->dequeueBuffer(a, &anb);
         if (!rc) {
-            rc = a->lockBuffer(a, anb);
-            if (!rc) {
-                *buffer = &anb->handle;
-                *stride = anb->stride;
-            }
-            else
-                a->cancelBuffer(a, anb);
+            *buffer = &anb->handle;
+            *stride = anb->stride;
         }
         return rc;
     }
@@ -576,6 +571,14 @@
         (type *) ((char *) __mptr - (char *)(&((type *)0)->member)); })
 #endif
 
+    static int __lock_buffer(struct preview_stream_ops* w,
+                      buffer_handle_t* buffer)
+    {
+        ANativeWindow *a = anw(w);
+        return a->lockBuffer(a,
+                  container_of(buffer, ANativeWindowBuffer, handle));
+    }
+
     static int __enqueue_buffer(struct preview_stream_ops* w,
                       buffer_handle_t* buffer)
     {
@@ -641,6 +644,7 @@
     void initHalPreviewWindow()
     {
         mHalPreviewWindow.nw.cancel_buffer = __cancel_buffer;
+        mHalPreviewWindow.nw.lock_buffer = __lock_buffer;
         mHalPreviewWindow.nw.dequeue_buffer = __dequeue_buffer;
         mHalPreviewWindow.nw.enqueue_buffer = __enqueue_buffer;
         mHalPreviewWindow.nw.set_buffer_count = __set_buffer_count;
diff --git a/services/camera/libcameraservice/CameraHardwareStub.h b/services/camera/libcameraservice/CameraHardwareStub.h
index 9b66a76..c6d8756 100644
--- a/services/camera/libcameraservice/CameraHardwareStub.h
+++ b/services/camera/libcameraservice/CameraHardwareStub.h
@@ -73,14 +73,7 @@
         CameraHardwareStub* mHardware;
     public:
         PreviewThread(CameraHardwareStub* hw) :
-#ifdef SINGLE_PROCESS
-            // In single process mode this thread needs to be a java thread,
-            // since we won't be calling through the binder.
-            Thread(true),
-#else
-            Thread(false),
-#endif
-              mHardware(hw) { }
+                Thread(false), mHardware(hw) { }
         virtual void onFirstRef() {
             run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
         }
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a011ae2..9b09983 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -420,6 +420,10 @@
     // allow anyone to use camera (after they lock the camera)
     status_t result = checkPid();
     if (result == NO_ERROR) {
+        if (mHardware->recordingEnabled()) {
+            LOGE("Not allowed to unlock camera during recording.");
+            return INVALID_OPERATION;
+        }
         mClientPid = 0;
         LOG1("clear mCameraClient (pid %d)", callingPid);
         // we need to remove the reference to ICameraClient so that when the app
@@ -756,6 +760,11 @@
     status_t result = checkPidAndHardware();
     if (result != NO_ERROR) return result;
 
+    if (mHardware->recordingEnabled()) {
+        LOGE("Cannot take picture during recording.");
+        return INVALID_OPERATION;
+    }
+
     if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
         (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
         LOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 95b8a57..ca2540b 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -212,8 +212,8 @@
     struct input_absinfo info;
 
     if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
-        LOGW("Error reading absolute controller %d for device %s fd %d\n",
-             axis, device->identifier.name.string(), device->fd);
+        LOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
+             axis, device->identifier.name.string(), device->fd, errno);
         return -errno;
     }
 
@@ -335,6 +335,33 @@
     return AKEY_STATE_UNKNOWN;
 }
 
+status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const {
+    if (axis >= 0 && axis <= ABS_MAX) {
+        AutoMutex _l(mLock);
+
+        Device* device = getDeviceLocked(deviceId);
+        if (device != NULL) {
+            return getAbsoluteAxisValueLocked(device, axis, outValue);
+        }
+    }
+    *outValue = 0;
+    return -1;
+}
+
+status_t EventHub::getAbsoluteAxisValueLocked(Device* device, int32_t axis,
+        int32_t* outValue) const {
+    struct input_absinfo info;
+
+     if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
+         LOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
+              axis, device->identifier.name.string(), device->fd, errno);
+         return -errno;
+     }
+
+     *outValue = info.value;
+     return OK;
+}
+
 bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
         const int32_t* keyCodes, uint8_t* outFlags) const {
     AutoMutex _l(mLock);
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index 0a34e45..695dfdf 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -186,6 +186,8 @@
     virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0;
     virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0;
     virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0;
+    virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
+            int32_t* outValue) const = 0;
 
     /*
      * Examine key input devices for specific framework keycode support
@@ -237,6 +239,7 @@
     virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const;
     virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const;
     virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const;
+    virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const;
 
     virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
             const int32_t* keyCodes, uint8_t* outFlags) const;
@@ -305,6 +308,7 @@
     int32_t getScanCodeStateLocked(Device* device, int32_t scanCode) const;
     int32_t getKeyCodeStateLocked(Device* device, int32_t keyCode) const;
     int32_t getSwitchStateLocked(Device* device, int32_t sw) const;
+    int32_t getAbsoluteAxisValueLocked(Device* device, int32_t axis, int32_t* outValue) const;
     bool markSupportedKeyCodesLocked(Device* device, size_t numCodes,
             const int32_t* keyCodes, uint8_t* outFlags) const;
 
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 4a50d8a..10b9083 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -569,9 +569,9 @@
         break;
     case DROP_REASON_BLOCKED:
         LOGI("Dropped event because the current application is not responding and the user "
-                "has started interating with a different application.");
+                "has started interacting with a different application.");
         reason = "inbound event was dropped because the current application is not responding "
-                "and the user has started interating with a different application";
+                "and the user has started interacting with a different application";
         break;
     case DROP_REASON_STALE:
         LOGI("Dropped event because it is stale.");
@@ -1239,7 +1239,7 @@
     const InputWindow* newHoverWindow = NULL;
 
     bool isSplit = mTouchState.split;
-    bool wrongDevice = mTouchState.down
+    bool switchedDevice = mTouchState.deviceId >= 0
             && (mTouchState.deviceId != entry->deviceId
                     || mTouchState.source != entry->source);
     bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
@@ -1248,28 +1248,27 @@
     bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN
             || maskedAction == AMOTION_EVENT_ACTION_SCROLL
             || isHoverAction);
+    bool wrongDevice = false;
     if (newGesture) {
         bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
-        if (wrongDevice && !down) {
+        if (switchedDevice && mTouchState.down && !down) {
+#if DEBUG_FOCUS
+            LOGD("Dropping event because a pointer for a different device is already down.");
+#endif
             mTempTouchState.copyFrom(mTouchState);
-        } else {
-            mTempTouchState.reset();
-            mTempTouchState.down = down;
-            mTempTouchState.deviceId = entry->deviceId;
-            mTempTouchState.source = entry->source;
-            isSplit = false;
-            wrongDevice = false;
+            injectionResult = INPUT_EVENT_INJECTION_FAILED;
+            switchedDevice = false;
+            wrongDevice = true;
+            goto Failed;
         }
+        mTempTouchState.reset();
+        mTempTouchState.down = down;
+        mTempTouchState.deviceId = entry->deviceId;
+        mTempTouchState.source = entry->source;
+        isSplit = false;
     } else {
         mTempTouchState.copyFrom(mTouchState);
     }
-    if (wrongDevice) {
-#if DEBUG_FOCUS
-        LOGD("Dropping event because a pointer for a different device is already down.");
-#endif
-        injectionResult = INPUT_EVENT_INJECTION_FAILED;
-        goto Failed;
-    }
 
     if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
         /* Case 1: New splittable pointer going down, or need target for hover or scroll. */
@@ -1598,18 +1597,38 @@
     // Update final pieces of touch state if the injector had permission.
     if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
         if (!wrongDevice) {
-            if (maskedAction == AMOTION_EVENT_ACTION_UP
-                    || maskedAction == AMOTION_EVENT_ACTION_CANCEL
-                    || isHoverAction) {
+            if (switchedDevice) {
+#if DEBUG_FOCUS
+                LOGD("Conflicting pointer actions: Switched to a different device.");
+#endif
+                *outConflictingPointerActions = true;
+            }
+
+            if (isHoverAction) {
+                // Started hovering, therefore no longer down.
+                if (mTouchState.down) {
+#if DEBUG_FOCUS
+                    LOGD("Conflicting pointer actions: Hover received while pointer was down.");
+#endif
+                    *outConflictingPointerActions = true;
+                }
+                mTouchState.reset();
+                if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
+                        || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
+                    mTouchState.deviceId = entry->deviceId;
+                    mTouchState.source = entry->source;
+                }
+            } else if (maskedAction == AMOTION_EVENT_ACTION_UP
+                    || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
                 // All pointers up or canceled.
                 mTouchState.reset();
             } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
                 // First pointer went down.
                 if (mTouchState.down) {
-                    *outConflictingPointerActions = true;
 #if DEBUG_FOCUS
-                    LOGD("Pointer down received while already down.");
+                    LOGD("Conflicting pointer actions: Down received while already down.");
 #endif
+                    *outConflictingPointerActions = true;
                 }
                 mTouchState.copyFrom(mTempTouchState);
             } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
@@ -1868,6 +1887,18 @@
                 return;
             }
 
+            // If the motion event was modified in flight, then we cannot stream the sample.
+            if ((motionEventDispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_MASK)
+                    != InputTarget::FLAG_DISPATCH_AS_IS) {
+#if DEBUG_BATCHING
+                LOGD("channel '%s' ~ Not streaming because the motion event was not "
+                        "being dispatched as-is.  "
+                        "(Waiting for next dispatch cycle to start.)",
+                        connection->getInputChannelName());
+#endif
+                return;
+            }
+
             // The dispatch entry is in progress and is still potentially open for streaming.
             // Try to stream the new motion sample.  This might fail if the consumer has already
             // consumed the motion event (or if the channel is broken).
@@ -1972,6 +2003,66 @@
         dispatchEntry->headMotionSample = appendedMotionSample;
     }
 
+    // Apply target flags and update the connection's input state.
+    switch (eventEntry->type) {
+    case EventEntry::TYPE_KEY: {
+        KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
+        dispatchEntry->resolvedAction = keyEntry->action;
+        dispatchEntry->resolvedFlags = keyEntry->flags;
+
+        if (!connection->inputState.trackKey(keyEntry,
+                dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
+#if DEBUG_DISPATCH_CYCLE
+            LOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
+                    connection->getInputChannelName());
+#endif
+            return; // skip the inconsistent event
+        }
+        break;
+    }
+
+    case EventEntry::TYPE_MOTION: {
+        MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
+        if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
+        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
+        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
+        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
+        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
+        } else {
+            dispatchEntry->resolvedAction = motionEntry->action;
+        }
+        if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
+                && !connection->inputState.isHovering(
+                        motionEntry->deviceId, motionEntry->source)) {
+#if DEBUG_DISPATCH_CYCLE
+        LOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event",
+                connection->getInputChannelName());
+#endif
+            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
+        }
+
+        dispatchEntry->resolvedFlags = motionEntry->flags;
+        if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
+            dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
+        }
+
+        if (!connection->inputState.trackMotion(motionEntry,
+                dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
+#if DEBUG_DISPATCH_CYCLE
+            LOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent motion event",
+                    connection->getInputChannelName());
+#endif
+            return; // skip the inconsistent event
+        }
+        break;
+    }
+    }
+
     // Enqueue the dispatch entry.
     connection->outboundQueue.enqueueAtTail(dispatchEntry);
 }
@@ -1999,16 +2090,11 @@
     case EventEntry::TYPE_KEY: {
         KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
 
-        // Apply target flags.
-        int32_t action = keyEntry->action;
-        int32_t flags = keyEntry->flags;
-
-        // Update the connection's input state.
-        connection->inputState.trackKey(keyEntry, action);
-
         // Publish the key event.
-        status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
-                action, flags, keyEntry->keyCode, keyEntry->scanCode,
+        status = connection->inputPublisher.publishKeyEvent(
+                keyEntry->deviceId, keyEntry->source,
+                dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
+                keyEntry->keyCode, keyEntry->scanCode,
                 keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
                 keyEntry->eventTime);
 
@@ -2024,24 +2110,6 @@
     case EventEntry::TYPE_MOTION: {
         MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
 
-        // Apply target flags.
-        int32_t action = motionEntry->action;
-        int32_t flags = motionEntry->flags;
-        if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
-            action = AMOTION_EVENT_ACTION_OUTSIDE;
-        } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
-            action = AMOTION_EVENT_ACTION_HOVER_EXIT;
-        } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
-            action = AMOTION_EVENT_ACTION_HOVER_ENTER;
-        } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
-            action = AMOTION_EVENT_ACTION_CANCEL;
-        } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
-            action = AMOTION_EVENT_ACTION_DOWN;
-        }
-        if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
-            flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
-        }
-
         // If headMotionSample is non-NULL, then it points to the first new sample that we
         // were unable to dispatch during the previous cycle so we resume dispatching from
         // that point in the list of motion samples.
@@ -2082,13 +2150,11 @@
             }
         }
 
-        // Update the connection's input state.
-        connection->inputState.trackMotion(motionEntry, action);
-
         // Publish the motion event and the first motion sample.
-        status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
-                motionEntry->source, action, flags, motionEntry->edgeFlags,
-                motionEntry->metaState, motionEntry->buttonState,
+        status = connection->inputPublisher.publishMotionEvent(
+                motionEntry->deviceId, motionEntry->source,
+                dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
+                motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState,
                 xOffset, yOffset,
                 motionEntry->xPrecision, motionEntry->yPrecision,
                 motionEntry->downTime, firstMotionSample->eventTime,
@@ -2102,8 +2168,8 @@
             return;
         }
 
-        if (action == AMOTION_EVENT_ACTION_MOVE
-                || action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
+        if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_MOVE
+                || dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
             // Append additional motion samples.
             MotionSample* nextMotionSample = firstMotionSample->next;
             for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
@@ -2355,23 +2421,22 @@
                 break;
             }
 
-            int32_t xOffset, yOffset;
-            float scaleFactor;
+            InputTarget target;
             const InputWindow* window = getWindowLocked(connection->inputChannel);
             if (window) {
-                xOffset = -window->frameLeft;
-                yOffset = -window->frameTop;
-                scaleFactor = window->scaleFactor;
+                target.xOffset = -window->frameLeft;
+                target.yOffset = -window->frameTop;
+                target.scaleFactor = window->scaleFactor;
             } else {
-                xOffset = 0;
-                yOffset = 0;
-                scaleFactor = 1.0f;
+                target.xOffset = 0;
+                target.yOffset = 0;
+                target.scaleFactor = 1.0f;
             }
+            target.inputChannel = connection->inputChannel;
+            target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
 
-            DispatchEntry* cancelationDispatchEntry =
-                    mAllocator.obtainDispatchEntry(cancelationEventEntry, // increments ref
-                    0, xOffset, yOffset, scaleFactor);
-            connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
+            enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref
+                    &target, false, InputTarget::FLAG_DISPATCH_AS_IS);
 
             mAllocator.releaseEventEntry(cancelationEventEntry);
         }
@@ -3327,6 +3392,7 @@
     resetTargetsLocked();
 
     mTouchState.reset();
+    mLastHoverWindow = NULL;
 }
 
 void InputDispatcher::logDispatchStateLocked() {
@@ -4125,111 +4191,186 @@
     return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
 }
 
-void InputDispatcher::InputState::trackEvent(const EventEntry* entry, int32_t action) {
-    switch (entry->type) {
-    case EventEntry::TYPE_KEY:
-        trackKey(static_cast<const KeyEntry*>(entry), action);
-        break;
+bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source) const {
+    for (size_t i = 0; i < mMotionMementos.size(); i++) {
+        const MotionMemento& memento = mMotionMementos.itemAt(i);
+        if (memento.deviceId == deviceId
+                && memento.source == source
+                && memento.hovering) {
+            return true;
+        }
+    }
+    return false;
+}
 
-    case EventEntry::TYPE_MOTION:
-        trackMotion(static_cast<const MotionEntry*>(entry), action);
-        break;
+bool InputDispatcher::InputState::trackKey(const KeyEntry* entry,
+        int32_t action, int32_t flags) {
+    switch (action) {
+    case AKEY_EVENT_ACTION_UP: {
+        if (entry->flags & AKEY_EVENT_FLAG_FALLBACK) {
+            for (size_t i = 0; i < mFallbackKeys.size(); ) {
+                if (mFallbackKeys.valueAt(i) == entry->keyCode) {
+                    mFallbackKeys.removeItemsAt(i);
+                } else {
+                    i += 1;
+                }
+            }
+        }
+        ssize_t index = findKeyMemento(entry);
+        if (index >= 0) {
+            mKeyMementos.removeAt(index);
+            return true;
+        }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        LOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
+                "keyCode=%d, scanCode=%d",
+                entry->deviceId, entry->source, entry->keyCode, entry->scanCode);
+#endif
+        return false;
+    }
+
+    case AKEY_EVENT_ACTION_DOWN: {
+        ssize_t index = findKeyMemento(entry);
+        if (index >= 0) {
+            mKeyMementos.removeAt(index);
+        }
+        addKeyMemento(entry, flags);
+        return true;
+    }
+
+    default:
+        return true;
     }
 }
 
-void InputDispatcher::InputState::trackKey(const KeyEntry* entry, int32_t action) {
-    if (action == AKEY_EVENT_ACTION_UP
-            && (entry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
-        for (size_t i = 0; i < mFallbackKeys.size(); ) {
-            if (mFallbackKeys.valueAt(i) == entry->keyCode) {
-                mFallbackKeys.removeItemsAt(i);
-            } else {
-                i += 1;
-            }
+bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry,
+        int32_t action, int32_t flags) {
+    int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
+    switch (actionMasked) {
+    case AMOTION_EVENT_ACTION_UP:
+    case AMOTION_EVENT_ACTION_CANCEL: {
+        ssize_t index = findMotionMemento(entry, false /*hovering*/);
+        if (index >= 0) {
+            mMotionMementos.removeAt(index);
+            return true;
         }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        LOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
+                "actionMasked=%d",
+                entry->deviceId, entry->source, actionMasked);
+#endif
+        return false;
     }
 
+    case AMOTION_EVENT_ACTION_DOWN: {
+        ssize_t index = findMotionMemento(entry, false /*hovering*/);
+        if (index >= 0) {
+            mMotionMementos.removeAt(index);
+        }
+        addMotionMemento(entry, flags, false /*hovering*/);
+        return true;
+    }
+
+    case AMOTION_EVENT_ACTION_POINTER_UP:
+    case AMOTION_EVENT_ACTION_POINTER_DOWN:
+    case AMOTION_EVENT_ACTION_MOVE: {
+        ssize_t index = findMotionMemento(entry, false /*hovering*/);
+        if (index >= 0) {
+            MotionMemento& memento = mMotionMementos.editItemAt(index);
+            memento.setPointers(entry);
+            return true;
+        }
+        if (actionMasked == AMOTION_EVENT_ACTION_MOVE
+                && (entry->source & (AINPUT_SOURCE_CLASS_JOYSTICK
+                        | AINPUT_SOURCE_CLASS_NAVIGATION))) {
+            // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
+            return true;
+        }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        LOGD("Dropping inconsistent motion pointer up/down or move event: "
+                "deviceId=%d, source=%08x, actionMasked=%d",
+                entry->deviceId, entry->source, actionMasked);
+#endif
+        return false;
+    }
+
+    case AMOTION_EVENT_ACTION_HOVER_EXIT: {
+        ssize_t index = findMotionMemento(entry, true /*hovering*/);
+        if (index >= 0) {
+            mMotionMementos.removeAt(index);
+            return true;
+        }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        LOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x",
+                entry->deviceId, entry->source);
+#endif
+        return false;
+    }
+
+    case AMOTION_EVENT_ACTION_HOVER_ENTER:
+    case AMOTION_EVENT_ACTION_HOVER_MOVE: {
+        ssize_t index = findMotionMemento(entry, true /*hovering*/);
+        if (index >= 0) {
+            mMotionMementos.removeAt(index);
+        }
+        addMotionMemento(entry, flags, true /*hovering*/);
+        return true;
+    }
+
+    default:
+        return true;
+    }
+}
+
+ssize_t InputDispatcher::InputState::findKeyMemento(const KeyEntry* entry) const {
     for (size_t i = 0; i < mKeyMementos.size(); i++) {
-        KeyMemento& memento = mKeyMementos.editItemAt(i);
+        const KeyMemento& memento = mKeyMementos.itemAt(i);
         if (memento.deviceId == entry->deviceId
                 && memento.source == entry->source
                 && memento.keyCode == entry->keyCode
                 && memento.scanCode == entry->scanCode) {
-            switch (action) {
-            case AKEY_EVENT_ACTION_UP:
-                mKeyMementos.removeAt(i);
-                return;
-
-            case AKEY_EVENT_ACTION_DOWN:
-                mKeyMementos.removeAt(i);
-                goto Found;
-
-            default:
-                return;
-            }
+            return i;
         }
     }
-
-Found:
-    if (action == AKEY_EVENT_ACTION_DOWN) {
-        mKeyMementos.push();
-        KeyMemento& memento = mKeyMementos.editTop();
-        memento.deviceId = entry->deviceId;
-        memento.source = entry->source;
-        memento.keyCode = entry->keyCode;
-        memento.scanCode = entry->scanCode;
-        memento.flags = entry->flags;
-        memento.downTime = entry->downTime;
-    }
+    return -1;
 }
 
-void InputDispatcher::InputState::trackMotion(const MotionEntry* entry, int32_t action) {
-    int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
+ssize_t InputDispatcher::InputState::findMotionMemento(const MotionEntry* entry,
+        bool hovering) const {
     for (size_t i = 0; i < mMotionMementos.size(); i++) {
-        MotionMemento& memento = mMotionMementos.editItemAt(i);
+        const MotionMemento& memento = mMotionMementos.itemAt(i);
         if (memento.deviceId == entry->deviceId
-                && memento.source == entry->source) {
-            switch (actionMasked) {
-            case AMOTION_EVENT_ACTION_UP:
-            case AMOTION_EVENT_ACTION_CANCEL:
-            case AMOTION_EVENT_ACTION_HOVER_ENTER:
-            case AMOTION_EVENT_ACTION_HOVER_MOVE:
-            case AMOTION_EVENT_ACTION_HOVER_EXIT:
-                mMotionMementos.removeAt(i);
-                return;
-
-            case AMOTION_EVENT_ACTION_DOWN:
-                mMotionMementos.removeAt(i);
-                goto Found;
-
-            case AMOTION_EVENT_ACTION_POINTER_UP:
-            case AMOTION_EVENT_ACTION_POINTER_DOWN:
-            case AMOTION_EVENT_ACTION_MOVE:
-                memento.setPointers(entry);
-                return;
-
-            default:
-                return;
-            }
+                && memento.source == entry->source
+                && memento.hovering == hovering) {
+            return i;
         }
     }
+    return -1;
+}
 
-Found:
-    switch (actionMasked) {
-    case AMOTION_EVENT_ACTION_DOWN:
-    case AMOTION_EVENT_ACTION_HOVER_ENTER:
-    case AMOTION_EVENT_ACTION_HOVER_MOVE:
-    case AMOTION_EVENT_ACTION_HOVER_EXIT:
-        mMotionMementos.push();
-        MotionMemento& memento = mMotionMementos.editTop();
-        memento.deviceId = entry->deviceId;
-        memento.source = entry->source;
-        memento.xPrecision = entry->xPrecision;
-        memento.yPrecision = entry->yPrecision;
-        memento.downTime = entry->downTime;
-        memento.setPointers(entry);
-        memento.hovering = actionMasked != AMOTION_EVENT_ACTION_DOWN;
-    }
+void InputDispatcher::InputState::addKeyMemento(const KeyEntry* entry, int32_t flags) {
+    mKeyMementos.push();
+    KeyMemento& memento = mKeyMementos.editTop();
+    memento.deviceId = entry->deviceId;
+    memento.source = entry->source;
+    memento.keyCode = entry->keyCode;
+    memento.scanCode = entry->scanCode;
+    memento.flags = flags;
+    memento.downTime = entry->downTime;
+}
+
+void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry,
+        int32_t flags, bool hovering) {
+    mMotionMementos.push();
+    MotionMemento& memento = mMotionMementos.editTop();
+    memento.deviceId = entry->deviceId;
+    memento.source = entry->source;
+    memento.flags = flags;
+    memento.xPrecision = entry->xPrecision;
+    memento.yPrecision = entry->yPrecision;
+    memento.downTime = entry->downTime;
+    memento.setPointers(entry);
+    memento.hovering = hovering;
 }
 
 void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
@@ -4243,20 +4384,17 @@
 void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
         Allocator* allocator, Vector<EventEntry*>& outEvents,
         const CancelationOptions& options) {
-    for (size_t i = 0; i < mKeyMementos.size(); ) {
+    for (size_t i = 0; i < mKeyMementos.size(); i++) {
         const KeyMemento& memento = mKeyMementos.itemAt(i);
         if (shouldCancelKey(memento, options)) {
             outEvents.push(allocator->obtainKeyEntry(currentTime,
                     memento.deviceId, memento.source, 0,
                     AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
                     memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
-            mKeyMementos.removeAt(i);
-        } else {
-            i += 1;
         }
     }
 
-    for (size_t i = 0; i < mMotionMementos.size(); ) {
+    for (size_t i = 0; i < mMotionMementos.size(); i++) {
         const MotionMemento& memento = mMotionMementos.itemAt(i);
         if (shouldCancelMotion(memento, options)) {
             outEvents.push(allocator->obtainMotionEntry(currentTime,
@@ -4264,12 +4402,9 @@
                     memento.hovering
                             ? AMOTION_EVENT_ACTION_HOVER_EXIT
                             : AMOTION_EVENT_ACTION_CANCEL,
-                    0, 0, 0, 0,
+                    memento.flags, 0, 0, 0,
                     memento.xPrecision, memento.yPrecision, memento.downTime,
                     memento.pointerCount, memento.pointerProperties, memento.pointerCoords));
-            mMotionMementos.removeAt(i);
-        } else {
-            i += 1;
         }
     }
 }
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 676d162..bdd1922 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -522,6 +522,10 @@
         // True if dispatch has started.
         bool inProgress;
 
+        // Set to the resolved action and flags when the event is enqueued.
+        int32_t resolvedAction;
+        int32_t resolvedFlags;
+
         // For motion events:
         //   Pointer to the first motion sample to dispatch in this cycle.
         //   Usually NULL to indicate that the list of motion samples begins at
@@ -709,14 +713,19 @@
         // Returns true if there is no state to be canceled.
         bool isNeutral() const;
 
-        // Records tracking information for an event that has just been published.
-        void trackEvent(const EventEntry* entry, int32_t action);
+        // Returns true if the specified source is known to have received a hover enter
+        // motion event.
+        bool isHovering(int32_t deviceId, uint32_t source) const;
 
         // Records tracking information for a key event that has just been published.
-        void trackKey(const KeyEntry* entry, int32_t action);
+        // Returns true if the event should be delivered, false if it is inconsistent
+        // and should be skipped.
+        bool trackKey(const KeyEntry* entry, int32_t action, int32_t flags);
 
         // Records tracking information for a motion event that has just been published.
-        void trackMotion(const MotionEntry* entry, int32_t action);
+        // Returns true if the event should be delivered, false if it is inconsistent
+        // and should be skipped.
+        bool trackMotion(const MotionEntry* entry, int32_t action, int32_t flags);
 
         // Synthesizes cancelation events for the current state and resets the tracked state.
         void synthesizeCancelationEvents(nsecs_t currentTime, Allocator* allocator,
@@ -756,6 +765,7 @@
         struct MotionMemento {
             int32_t deviceId;
             uint32_t source;
+            int32_t flags;
             float xPrecision;
             float yPrecision;
             nsecs_t downTime;
@@ -771,6 +781,12 @@
         Vector<MotionMemento> mMotionMementos;
         KeyedVector<int32_t, int32_t> mFallbackKeys;
 
+        ssize_t findKeyMemento(const KeyEntry* entry) const;
+        ssize_t findMotionMemento(const MotionEntry* entry, bool hovering) const;
+
+        void addKeyMemento(const KeyEntry* entry, int32_t flags);
+        void addMotionMemento(const MotionEntry* entry, int32_t flags, bool hovering);
+
         static bool shouldCancelKey(const KeyMemento& memento,
                 const CancelationOptions& options);
         static bool shouldCancelMotion(const MotionMemento& memento,
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 3e4c666..49cb864 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -53,6 +53,7 @@
 #define INDENT2 "    "
 #define INDENT3 "      "
 #define INDENT4 "        "
+#define INDENT5 "          "
 
 namespace android {
 
@@ -154,14 +155,15 @@
     case BTN_LEFT:
         return AMOTION_EVENT_BUTTON_PRIMARY;
     case BTN_RIGHT:
+    case BTN_STYLUS:
         return AMOTION_EVENT_BUTTON_SECONDARY;
     case BTN_MIDDLE:
+    case BTN_STYLUS2:
         return AMOTION_EVENT_BUTTON_TERTIARY;
     case BTN_SIDE:
         return AMOTION_EVENT_BUTTON_BACK;
-    case BTN_EXTRA:
-        return AMOTION_EVENT_BUTTON_FORWARD;
     case BTN_FORWARD:
+    case BTN_EXTRA:
         return AMOTION_EVENT_BUTTON_FORWARD;
     case BTN_BACK:
         return AMOTION_EVENT_BUTTON_BACK;
@@ -176,8 +178,7 @@
 static bool isPointerDown(int32_t buttonState) {
     return buttonState &
             (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
-                    | AMOTION_EVENT_BUTTON_TERTIARY
-                    | AMOTION_EVENT_BUTTON_ERASER);
+                    | AMOTION_EVENT_BUTTON_TERTIARY);
 }
 
 static int32_t calculateEdgeFlagsUsingPointerBounds(
@@ -767,10 +768,6 @@
         dump.append(mConfig.excludedDeviceNames.itemAt(i).string());
     }
     dump.append("]\n");
-    dump.appendFormat(INDENT2 "FilterTouchEvents: %s\n",
-            toString(mConfig.filterTouchEvents));
-    dump.appendFormat(INDENT2 "FilterJumpyTouchEvents: %s\n",
-            toString(mConfig.filterJumpyTouchEvents));
     dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
             mConfig.virtualKeyQuietTime * 0.000001f);
 
@@ -921,7 +918,7 @@
     for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
 #if DEBUG_RAW_EVENTS
         LOGD("Input event: device=%d type=0x%04x scancode=0x%04x "
-                "keycode=0x%04x value=0x%04x flags=0x%08x",
+                "keycode=0x%04x value=0x%08x flags=0x%08x",
                 rawEvent->deviceId, rawEvent->type, rawEvent->scanCode, rawEvent->keyCode,
                 rawEvent->value, rawEvent->flags);
 #endif
@@ -1921,8 +1918,17 @@
         dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mLocked.distanceScale);
 
         dump.appendFormat(INDENT3 "Last Touch:\n");
-        dump.appendFormat(INDENT4 "Pointer Count: %d\n", mLastTouch.pointerCount);
         dump.appendFormat(INDENT4 "Button State: 0x%08x\n", mLastTouch.buttonState);
+        dump.appendFormat(INDENT4 "Pointer Count: %d\n", mLastTouch.pointerCount);
+        for (uint32_t i = 0; i < mLastTouch.pointerCount; i++) {
+            const PointerData& pointer = mLastTouch.pointers[i];
+            dump.appendFormat(INDENT5 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
+                    "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
+                    "orientation=%d, distance=%d, isStylus=%s\n", i,
+                    pointer.id, pointer.x, pointer.y, pointer.pressure,
+                    pointer.touchMajor, pointer.touchMinor, pointer.toolMajor, pointer.toolMinor,
+                    pointer.orientation, pointer.distance, toString(pointer.isStylus));
+        }
 
         if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
             dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
@@ -1945,13 +1951,6 @@
     mLastTouch.clear();
     mDownTime = 0;
 
-    for (uint32_t i = 0; i < MAX_POINTERS; i++) {
-        mAveragingTouchFilter.historyStart[i] = 0;
-        mAveragingTouchFilter.historyEnd[i] = 0;
-    }
-
-    mJumpyTouchFilter.jumpyPointsDropped = 0;
-
     mLocked.currentVirtualKey.down = false;
 
     mLocked.orientedRanges.havePressure = false;
@@ -2018,10 +2017,6 @@
 }
 
 void TouchInputMapper::configureParameters() {
-    mParameters.useBadTouchFilter = mConfig.filterTouchEvents;
-    mParameters.useAveragingTouchFilter = mConfig.filterTouchEvents;
-    mParameters.useJumpyTouchFilter = mConfig.filterJumpyTouchEvents;
-
     // Use the pointer presentation mode for devices that do not support distinct
     // multitouch.  The spot-based presentation relies on being able to accurately
     // locate two or more fingers on the touch pad.
@@ -2112,13 +2107,6 @@
             mParameters.associatedDisplayId);
     dump.appendFormat(INDENT4 "OrientationAware: %s\n",
             toString(mParameters.orientationAware));
-
-    dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
-            toString(mParameters.useBadTouchFilter));
-    dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
-            toString(mParameters.useAveragingTouchFilter));
-    dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
-            toString(mParameters.useJumpyTouchFilter));
 }
 
 void TouchInputMapper::configureRawAxes() {
@@ -2975,33 +2963,10 @@
 #endif
 
     // Preprocess pointer data.
-    if (mParameters.useBadTouchFilter) {
-        if (applyBadTouchFilter()) {
-            havePointerIds = false;
-        }
-    }
-
-    if (mParameters.useJumpyTouchFilter) {
-        if (applyJumpyTouchFilter()) {
-            havePointerIds = false;
-        }
-    }
-
     if (!havePointerIds) {
         calculatePointerIds();
     }
 
-    TouchData temp;
-    TouchData* savedTouch;
-    if (mParameters.useAveragingTouchFilter) {
-        temp.copyFrom(mCurrentTouch);
-        savedTouch = & temp;
-
-        applyAveragingTouchFilter();
-    } else {
-        savedTouch = & mCurrentTouch;
-    }
-
     uint32_t policyFlags = 0;
     if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
         if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
@@ -3048,9 +3013,9 @@
     // Keep the button state so we can track edge-triggered button state changes.
     if (touchResult == DROP_STROKE) {
         mLastTouch.clear();
-        mLastTouch.buttonState = savedTouch->buttonState;
+        mLastTouch.buttonState = mCurrentTouch.buttonState;
     } else {
-        mLastTouch.copyFrom(*savedTouch);
+        mLastTouch.copyFrom(mCurrentTouch);
     }
 }
 
@@ -3704,6 +3669,29 @@
                 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
                 mPointerGesture.currentGestureIdBits, -1,
                 0, 0, mPointerGesture.downTime);
+    } else if (dispatchedGestureIdBits.isEmpty()
+            && !mPointerGesture.lastGestureIdBits.isEmpty()) {
+        // Synthesize a hover move event after all pointers go up to indicate that
+        // the pointer is hovering again even if the user is not currently touching
+        // the touch pad.  This ensures that a view will receive a fresh hover enter
+        // event after a tap.
+        float x, y;
+        mPointerController->getPosition(&x, &y);
+
+        PointerProperties pointerProperties;
+        pointerProperties.clear();
+        pointerProperties.id = 0;
+        pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+
+        PointerCoords pointerCoords;
+        pointerCoords.clear();
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+
+        getDispatcher()->notifyMotion(when, getDeviceId(), mPointerSource, policyFlags,
+                AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
+                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                1, &pointerProperties, &pointerCoords, 0, 0, mPointerGesture.downTime);
     }
 
     // Update state.
@@ -4793,359 +4781,6 @@
     }
 }
 
-/* Special hack for devices that have bad screen data: if one of the
- * points has moved more than a screen height from the last position,
- * then drop it. */
-bool TouchInputMapper::applyBadTouchFilter() {
-    uint32_t pointerCount = mCurrentTouch.pointerCount;
-
-    // Nothing to do if there are no points.
-    if (pointerCount == 0) {
-        return false;
-    }
-
-    // Don't do anything if a finger is going down or up.  We run
-    // here before assigning pointer IDs, so there isn't a good
-    // way to do per-finger matching.
-    if (pointerCount != mLastTouch.pointerCount) {
-        return false;
-    }
-
-    // We consider a single movement across more than a 7/16 of
-    // the long size of the screen to be bad.  This was a magic value
-    // determined by looking at the maximum distance it is feasible
-    // to actually move in one sample.
-    int32_t maxDeltaY = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) * 7 / 16;
-
-    // XXX The original code in InputDevice.java included commented out
-    //     code for testing the X axis.  Note that when we drop a point
-    //     we don't actually restore the old X either.  Strange.
-    //     The old code also tries to track when bad points were previously
-    //     detected but it turns out that due to the placement of a "break"
-    //     at the end of the loop, we never set mDroppedBadPoint to true
-    //     so it is effectively dead code.
-    // Need to figure out if the old code is busted or just overcomplicated
-    // but working as intended.
-
-    // Look through all new points and see if any are farther than
-    // acceptable from all previous points.
-    for (uint32_t i = pointerCount; i-- > 0; ) {
-        int32_t y = mCurrentTouch.pointers[i].y;
-        int32_t closestY = INT_MAX;
-        int32_t closestDeltaY = 0;
-
-#if DEBUG_HACKS
-        LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
-#endif
-
-        for (uint32_t j = pointerCount; j-- > 0; ) {
-            int32_t lastY = mLastTouch.pointers[j].y;
-            int32_t deltaY = abs(y - lastY);
-
-#if DEBUG_HACKS
-            LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
-                    j, lastY, deltaY);
-#endif
-
-            if (deltaY < maxDeltaY) {
-                goto SkipSufficientlyClosePoint;
-            }
-            if (deltaY < closestDeltaY) {
-                closestDeltaY = deltaY;
-                closestY = lastY;
-            }
-        }
-
-        // Must not have found a close enough match.
-#if DEBUG_HACKS
-        LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
-                i, y, closestY, closestDeltaY, maxDeltaY);
-#endif
-
-        mCurrentTouch.pointers[i].y = closestY;
-        return true; // XXX original code only corrects one point
-
-    SkipSufficientlyClosePoint: ;
-    }
-
-    // No change.
-    return false;
-}
-
-/* Special hack for devices that have bad screen data: drop points where
- * the coordinate value for one axis has jumped to the other pointer's location.
- */
-bool TouchInputMapper::applyJumpyTouchFilter() {
-    uint32_t pointerCount = mCurrentTouch.pointerCount;
-    if (mLastTouch.pointerCount != pointerCount) {
-#if DEBUG_HACKS
-        LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
-                mLastTouch.pointerCount, pointerCount);
-        for (uint32_t i = 0; i < pointerCount; i++) {
-            LOGD("  Pointer %d (%d, %d)", i,
-                    mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
-        }
-#endif
-
-        if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
-            if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
-                // Just drop the first few events going from 1 to 2 pointers.
-                // They're bad often enough that they're not worth considering.
-                mCurrentTouch.pointerCount = 1;
-                mJumpyTouchFilter.jumpyPointsDropped += 1;
-
-#if DEBUG_HACKS
-                LOGD("JumpyTouchFilter: Pointer 2 dropped");
-#endif
-                return true;
-            } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
-                // The event when we go from 2 -> 1 tends to be messed up too
-                mCurrentTouch.pointerCount = 2;
-                mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
-                mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
-                mJumpyTouchFilter.jumpyPointsDropped += 1;
-
-#if DEBUG_HACKS
-                for (int32_t i = 0; i < 2; i++) {
-                    LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
-                            mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
-                }
-#endif
-                return true;
-            }
-        }
-        // Reset jumpy points dropped on other transitions or if limit exceeded.
-        mJumpyTouchFilter.jumpyPointsDropped = 0;
-
-#if DEBUG_HACKS
-        LOGD("JumpyTouchFilter: Transition - drop limit reset");
-#endif
-        return false;
-    }
-
-    // We have the same number of pointers as last time.
-    // A 'jumpy' point is one where the coordinate value for one axis
-    // has jumped to the other pointer's location. No need to do anything
-    // else if we only have one pointer.
-    if (pointerCount < 2) {
-        return false;
-    }
-
-    if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
-        int jumpyEpsilon = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) / JUMPY_EPSILON_DIVISOR;
-
-        // We only replace the single worst jumpy point as characterized by pointer distance
-        // in a single axis.
-        int32_t badPointerIndex = -1;
-        int32_t badPointerReplacementIndex = -1;
-        int32_t badPointerDistance = INT_MIN; // distance to be corrected
-
-        for (uint32_t i = pointerCount; i-- > 0; ) {
-            int32_t x = mCurrentTouch.pointers[i].x;
-            int32_t y = mCurrentTouch.pointers[i].y;
-
-#if DEBUG_HACKS
-            LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
-#endif
-
-            // Check if a touch point is too close to another's coordinates
-            bool dropX = false, dropY = false;
-            for (uint32_t j = 0; j < pointerCount; j++) {
-                if (i == j) {
-                    continue;
-                }
-
-                if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
-                    dropX = true;
-                    break;
-                }
-
-                if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
-                    dropY = true;
-                    break;
-                }
-            }
-            if (! dropX && ! dropY) {
-                continue; // not jumpy
-            }
-
-            // Find a replacement candidate by comparing with older points on the
-            // complementary (non-jumpy) axis.
-            int32_t distance = INT_MIN; // distance to be corrected
-            int32_t replacementIndex = -1;
-
-            if (dropX) {
-                // X looks too close.  Find an older replacement point with a close Y.
-                int32_t smallestDeltaY = INT_MAX;
-                for (uint32_t j = 0; j < pointerCount; j++) {
-                    int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
-                    if (deltaY < smallestDeltaY) {
-                        smallestDeltaY = deltaY;
-                        replacementIndex = j;
-                    }
-                }
-                distance = abs(x - mLastTouch.pointers[replacementIndex].x);
-            } else {
-                // Y looks too close.  Find an older replacement point with a close X.
-                int32_t smallestDeltaX = INT_MAX;
-                for (uint32_t j = 0; j < pointerCount; j++) {
-                    int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
-                    if (deltaX < smallestDeltaX) {
-                        smallestDeltaX = deltaX;
-                        replacementIndex = j;
-                    }
-                }
-                distance = abs(y - mLastTouch.pointers[replacementIndex].y);
-            }
-
-            // If replacing this pointer would correct a worse error than the previous ones
-            // considered, then use this replacement instead.
-            if (distance > badPointerDistance) {
-                badPointerIndex = i;
-                badPointerReplacementIndex = replacementIndex;
-                badPointerDistance = distance;
-            }
-        }
-
-        // Correct the jumpy pointer if one was found.
-        if (badPointerIndex >= 0) {
-#if DEBUG_HACKS
-            LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
-                    badPointerIndex,
-                    mLastTouch.pointers[badPointerReplacementIndex].x,
-                    mLastTouch.pointers[badPointerReplacementIndex].y);
-#endif
-
-            mCurrentTouch.pointers[badPointerIndex].x =
-                    mLastTouch.pointers[badPointerReplacementIndex].x;
-            mCurrentTouch.pointers[badPointerIndex].y =
-                    mLastTouch.pointers[badPointerReplacementIndex].y;
-            mJumpyTouchFilter.jumpyPointsDropped += 1;
-            return true;
-        }
-    }
-
-    mJumpyTouchFilter.jumpyPointsDropped = 0;
-    return false;
-}
-
-/* Special hack for devices that have bad screen data: aggregate and
- * compute averages of the coordinate data, to reduce the amount of
- * jitter seen by applications. */
-void TouchInputMapper::applyAveragingTouchFilter() {
-    for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
-        uint32_t id = mCurrentTouch.pointers[currentIndex].id;
-        int32_t x = mCurrentTouch.pointers[currentIndex].x;
-        int32_t y = mCurrentTouch.pointers[currentIndex].y;
-        int32_t pressure;
-        switch (mCalibration.pressureSource) {
-        case Calibration::PRESSURE_SOURCE_PRESSURE:
-            pressure = mCurrentTouch.pointers[currentIndex].pressure;
-            break;
-        case Calibration::PRESSURE_SOURCE_TOUCH:
-            pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
-            break;
-        default:
-            pressure = 1;
-            break;
-        }
-
-        if (mLastTouch.idBits.hasBit(id)) {
-            // Pointer was down before and is still down now.
-            // Compute average over history trace.
-            uint32_t start = mAveragingTouchFilter.historyStart[id];
-            uint32_t end = mAveragingTouchFilter.historyEnd[id];
-
-            int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
-            int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
-            uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
-
-#if DEBUG_HACKS
-            LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
-                    id, distance);
-#endif
-
-            if (distance < AVERAGING_DISTANCE_LIMIT) {
-                // Increment end index in preparation for recording new historical data.
-                end += 1;
-                if (end > AVERAGING_HISTORY_SIZE) {
-                    end = 0;
-                }
-
-                // If the end index has looped back to the start index then we have filled
-                // the historical trace up to the desired size so we drop the historical
-                // data at the start of the trace.
-                if (end == start) {
-                    start += 1;
-                    if (start > AVERAGING_HISTORY_SIZE) {
-                        start = 0;
-                    }
-                }
-
-                // Add the raw data to the historical trace.
-                mAveragingTouchFilter.historyStart[id] = start;
-                mAveragingTouchFilter.historyEnd[id] = end;
-                mAveragingTouchFilter.historyData[end].pointers[id].x = x;
-                mAveragingTouchFilter.historyData[end].pointers[id].y = y;
-                mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
-
-                // Average over all historical positions in the trace by total pressure.
-                int32_t averagedX = 0;
-                int32_t averagedY = 0;
-                int32_t totalPressure = 0;
-                for (;;) {
-                    int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
-                    int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
-                    int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
-                            .pointers[id].pressure;
-
-                    averagedX += historicalX * historicalPressure;
-                    averagedY += historicalY * historicalPressure;
-                    totalPressure += historicalPressure;
-
-                    if (start == end) {
-                        break;
-                    }
-
-                    start += 1;
-                    if (start > AVERAGING_HISTORY_SIZE) {
-                        start = 0;
-                    }
-                }
-
-                if (totalPressure != 0) {
-                    averagedX /= totalPressure;
-                    averagedY /= totalPressure;
-
-#if DEBUG_HACKS
-                    LOGD("AveragingTouchFilter: Pointer id %d - "
-                            "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
-                            averagedX, averagedY);
-#endif
-
-                    mCurrentTouch.pointers[currentIndex].x = averagedX;
-                    mCurrentTouch.pointers[currentIndex].y = averagedY;
-                }
-            } else {
-#if DEBUG_HACKS
-                LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
-#endif
-            }
-        } else {
-#if DEBUG_HACKS
-            LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
-#endif
-        }
-
-        // Reset pointer history.
-        mAveragingTouchFilter.historyStart[id] = 0;
-        mAveragingTouchFilter.historyEnd[id] = 0;
-        mAveragingTouchFilter.historyData[0].pointers[id].x = x;
-        mAveragingTouchFilter.historyData[0].pointers[id].y = y;
-        mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
-    }
-}
-
 int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
     { // acquire lock
         AutoMutex _l(mLock);
@@ -5361,7 +4996,6 @@
 
 MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
         TouchInputMapper(device), mSlotCount(0), mUsingSlotsProtocol(false) {
-    clearState();
 }
 
 MultiTouchInputMapper::~MultiTouchInputMapper() {
@@ -5371,6 +5005,25 @@
     mAccumulator.clearSlots(mSlotCount);
     mAccumulator.clearButtons();
     mButtonState = 0;
+    mPointerIdBits.clear();
+
+    if (mUsingSlotsProtocol) {
+        // Query the driver for the current slot index and use it as the initial slot
+        // before we start reading events from the device.  It is possible that the
+        // current slot index will not be the same as it was when the first event was
+        // written into the evdev buffer, which means the input mapper could start
+        // out of sync with the initial state of the events in the evdev buffer.
+        // In the extremely unlikely case that this happens, the data from
+        // two slots will be confused until the next ABS_MT_SLOT event is received.
+        // This can cause the touch point to "jump", but at least there will be
+        // no stuck touches.
+        status_t status = getEventHub()->getAbsoluteAxisValue(getDeviceId(), ABS_MT_SLOT,
+                &mAccumulator.currentSlot);
+        if (status) {
+            LOGW("Could not retrieve current multitouch slot index.  status=%d", status);
+            mAccumulator.currentSlot = -1;
+        }
+    }
 }
 
 void MultiTouchInputMapper::reset() {
@@ -5577,28 +5230,32 @@
 
         // Assign pointer id using tracking id if available.
         if (havePointerIds) {
-            int32_t id;
-            if (mUsingSlotsProtocol) {
-                id = inIndex;
-            } else if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
-                id = inSlot.absMTTrackingId;
-            } else {
-                id = -1;
-            }
+            int32_t id = -1;
+            if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
+                int32_t trackingId = inSlot.absMTTrackingId;
 
-            if (id >= 0 && id <= MAX_POINTER_ID) {
+                for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
+                    uint32_t n = idBits.firstMarkedBit();
+                    idBits.clearBit(n);
+
+                    if (mPointerTrackingIdMap[n] == trackingId) {
+                        id = n;
+                    }
+                }
+
+                if (id < 0 && !mPointerIdBits.isFull()) {
+                    id = mPointerIdBits.firstUnmarkedBit();
+                    mPointerIdBits.markBit(id);
+                    mPointerTrackingIdMap[id] = trackingId;
+                }
+            }
+            if (id < 0) {
+                havePointerIds = false;
+                mCurrentTouch.idBits.clear();
+            } else {
                 outPointer.id = id;
                 mCurrentTouch.idToIndex[id] = outCount;
                 mCurrentTouch.idBits.markBit(id);
-            } else {
-                if (id >= 0) {
-#if DEBUG_POINTERS
-                    LOGD("Pointers: Ignoring driver provided slot index or tracking id %d because "
-                            "it is larger than the maximum supported pointer id %d",
-                            id, MAX_POINTER_ID);
-#endif
-                }
-                havePointerIds = false;
             }
         }
 
@@ -5610,6 +5267,8 @@
     mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
     mCurrentTouch.buttonState = mButtonState;
 
+    mPointerIdBits = mCurrentTouch.idBits;
+
     syncTouch(when, havePointerIds);
 
     if (!mUsingSlotsProtocol) {
@@ -5649,6 +5308,8 @@
     }
 
     mAccumulator.allocateSlots(mSlotCount);
+
+    clearState();
 }
 
 
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 288ff4e..69fa6b4 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -57,14 +57,6 @@
         CHANGE_MUST_REOPEN = 1 << 31,
     };
 
-    // Determines whether to turn on some hacks we have to improve the touch interaction with a
-    // certain device whose screen currently is not all that good.
-    bool filterTouchEvents;
-
-    // Determines whether to turn on some hacks to improve touch interaction with another device
-    // where touch coordinate data can get corrupted.
-    bool filterJumpyTouchEvents;
-
     // Gets the amount of time to disable virtual keys after the screen is touched
     // in order to filter out accidental virtual key presses due to swiping gestures
     // or taps near the edge of the display.  May be 0 to disable the feature.
@@ -146,8 +138,6 @@
     float pointerGestureZoomSpeedRatio;
 
     InputReaderConfiguration() :
-            filterTouchEvents(false),
-            filterJumpyTouchEvents(false),
             virtualKeyQuietTime(0),
             pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f),
             wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f),
@@ -812,10 +802,6 @@
         int32_t associatedDisplayId;
         bool orientationAware;
 
-        bool useBadTouchFilter;
-        bool useJumpyTouchFilter;
-        bool useAveragingTouchFilter;
-
         enum GestureMode {
             GESTURE_MODE_POINTER,
             GESTURE_MODE_SPOTS,
@@ -1042,38 +1028,6 @@
     void syncTouch(nsecs_t when, bool havePointerIds);
 
 private:
-    /* Maximum number of historical samples to average. */
-    static const uint32_t AVERAGING_HISTORY_SIZE = 5;
-
-    /* Slop distance for jumpy pointer detection.
-     * The vertical range of the screen divided by this is our epsilon value. */
-    static const uint32_t JUMPY_EPSILON_DIVISOR = 212;
-
-    /* Number of jumpy points to drop for touchscreens that need it. */
-    static const uint32_t JUMPY_TRANSITION_DROPS = 3;
-    static const uint32_t JUMPY_DROP_LIMIT = 3;
-
-    /* Maximum squared distance for averaging.
-     * If moving farther than this, turn of averaging to avoid lag in response. */
-    static const uint64_t AVERAGING_DISTANCE_LIMIT = 75 * 75;
-
-    struct AveragingTouchFilterState {
-        // Individual history tracks are stored by pointer id
-        uint32_t historyStart[MAX_POINTERS];
-        uint32_t historyEnd[MAX_POINTERS];
-        struct {
-            struct {
-                int32_t x;
-                int32_t y;
-                int32_t pressure;
-            } pointers[MAX_POINTERS];
-        } historyData[AVERAGING_HISTORY_SIZE];
-    } mAveragingTouchFilter;
-
-    struct JumpyTouchFilterState {
-        uint32_t jumpyPointsDropped;
-    } mJumpyTouchFilter;
-
     struct PointerDistanceHeapElement {
         uint32_t currentPointerIndex : 8;
         uint32_t lastPointerIndex : 8;
@@ -1251,9 +1205,6 @@
     bool isPointInsideSurfaceLocked(int32_t x, int32_t y);
     const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y);
 
-    bool applyBadTouchFilter();
-    bool applyJumpyTouchFilter();
-    void applyAveragingTouchFilter();
     void calculatePointerIds();
 };
 
@@ -1401,6 +1352,10 @@
 
     int32_t mButtonState;
 
+    // Specifies the pointer id bits that are in use, and their associated tracking id.
+    BitSet32 mPointerIdBits;
+    int32_t mPointerTrackingIdMap[MAX_POINTER_ID + 1];
+
     void clearState();
 
     void sync(nsecs_t when);
diff --git a/services/input/SpriteController.cpp b/services/input/SpriteController.cpp
index 08cc75e..0ae2ab8 100644
--- a/services/input/SpriteController.cpp
+++ b/services/input/SpriteController.cpp
@@ -252,11 +252,7 @@
                         | DIRTY_VISIBILITY | DIRTY_HOTSPOT))))) {
             status_t status;
             if (!haveTransaction) {
-                status = mSurfaceComposerClient->openTransaction();
-                if (status) {
-                    LOGE("Error %d opening transation to update sprite surface.", status);
-                    break;
-                }
+                SurfaceComposerClient::openGlobalTransaction();
                 haveTransaction = true;
             }
 
@@ -322,10 +318,7 @@
     }
 
     if (haveTransaction) {
-        status_t status = mSurfaceComposerClient->closeTransaction();
-        if (status) {
-            LOGE("Error %d closing transaction to update sprite surface.", status);
-        }
+        SurfaceComposerClient::closeGlobalTransaction();
     }
 
     // If any surfaces were changed, write back the new surface properties to the sprites.
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index e349248..67067de 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -144,14 +144,6 @@
         mDisplayInfos.add(displayId, info);
     }
 
-    void setFilterTouchEvents(bool enabled) {
-        mConfig.filterTouchEvents = enabled;
-    }
-
-    void setFilterJumpyTouchEvents(bool enabled) {
-        mConfig.filterJumpyTouchEvents = enabled;
-    }
-
     virtual nsecs_t getVirtualKeyQuietTime() {
         return 0;
     }
@@ -429,6 +421,7 @@
         KeyedVector<int32_t, int32_t> keyCodeStates;
         KeyedVector<int32_t, int32_t> scanCodeStates;
         KeyedVector<int32_t, int32_t> switchStates;
+        KeyedVector<int32_t, int32_t> absoluteAxisValue;
         KeyedVector<int32_t, KeyInfo> keys;
         KeyedVector<int32_t, bool> leds;
         Vector<VirtualKeyDefinition> virtualKeys;
@@ -514,6 +507,11 @@
         device->switchStates.replaceValueFor(switchCode, state);
     }
 
+    void setAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t value) {
+        Device* device = getDevice(deviceId);
+        device->absoluteAxisValue.replaceValueFor(axis, value);
+    }
+
     void addKey(int32_t deviceId, int32_t scanCode, int32_t keyCode, uint32_t flags) {
         Device* device = getDevice(deviceId);
         KeyInfo info;
@@ -677,6 +675,20 @@
         return AKEY_STATE_UNKNOWN;
     }
 
+    virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
+            int32_t* outValue) const {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->absoluteAxisValue.indexOfKey(axis);
+            if (index >= 0) {
+                *outValue = device->absoluteAxisValue.valueAt(index);
+                return OK;
+            }
+        }
+        *outValue = 0;
+        return -1;
+    }
+
     virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
             uint8_t* outFlags) const {
         bool result = false;
@@ -3516,7 +3528,7 @@
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
     ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
+    ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
@@ -3525,9 +3537,9 @@
     ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
             motionArgs.action);
     ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
+    ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-    ASSERT_EQ(2, motionArgs.pointerProperties[1].id);
+    ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
@@ -3547,9 +3559,9 @@
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
     ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
+    ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-    ASSERT_EQ(2, motionArgs.pointerProperties[1].id);
+    ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
@@ -3567,9 +3579,9 @@
     ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
             motionArgs.action);
     ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
+    ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-    ASSERT_EQ(2, motionArgs.pointerProperties[1].id);
+    ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
@@ -3579,7 +3591,7 @@
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
     ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(2, motionArgs.pointerProperties[0].id);
+    ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
@@ -3594,7 +3606,7 @@
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
     ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(2, motionArgs.pointerProperties[0].id);
+    ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
@@ -3610,17 +3622,17 @@
     processSync(mapper);
 
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
             motionArgs.action);
     ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(2, motionArgs.pointerProperties[0].id);
+    ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-    ASSERT_EQ(3, motionArgs.pointerProperties[1].id);
+    ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
             toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
 
     // Second finger up.
     x3 += 30; y3 -= 20;
@@ -3630,22 +3642,22 @@
     processSync(mapper);
 
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
             motionArgs.action);
     ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(2, motionArgs.pointerProperties[0].id);
+    ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-    ASSERT_EQ(3, motionArgs.pointerProperties[1].id);
+    ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
             toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
 
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
     ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(3, motionArgs.pointerProperties[0].id);
+    ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
@@ -3657,7 +3669,7 @@
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
     ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
     ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(3, motionArgs.pointerProperties[0].id);
+    ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
     ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
             toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
@@ -3708,7 +3720,7 @@
 
     FakeInputDispatcher::NotifyMotionArgs args;
     ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(id, args.pointerProperties[0].id);
+    ASSERT_EQ(0, args.pointerProperties[0].id);
     ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
             x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, orientation));
 }
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 158c778..0b15221 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -1072,7 +1072,7 @@
             throw new IllegalArgumentException("packageName and uid don't match packageName="
                     + packageName);
         }
-        if (callingUid != packageUid && Process.supportsProcesses()) {
+        if (callingUid != packageUid) {
             throw new IllegalArgumentException("packageName and uid don't match packageName="
                     + packageName);
         }
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 3aa1239..786f2fa 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -23,6 +23,7 @@
 import android.app.IApplicationThread;
 import android.app.IBackupAgent;
 import android.app.PendingIntent;
+import android.app.backup.BackupAgent;
 import android.app.backup.BackupDataOutput;
 import android.app.backup.FullBackup;
 import android.app.backup.RestoreSet;
@@ -64,6 +65,7 @@
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.util.EventLog;
+import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
@@ -222,6 +224,7 @@
         public PackageInfo pkgInfo;
         public int pmToken; // in post-install restore, the PM's token for this transaction
         public boolean needFullBackup;
+        public String[] filterSet;
 
         RestoreParams(IBackupTransport _transport, IRestoreObserver _obs,
                 long _token, PackageInfo _pkg, int _pmToken, boolean _needFullBackup) {
@@ -231,6 +234,7 @@
             pkgInfo = _pkg;
             pmToken = _pmToken;
             needFullBackup = _needFullBackup;
+            filterSet = null;
         }
 
         RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token,
@@ -241,6 +245,18 @@
             pkgInfo = null;
             pmToken = 0;
             needFullBackup = _needFullBackup;
+            filterSet = null;
+        }
+
+        RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token,
+                String[] _filterSet, boolean _needFullBackup) {
+            transport = _transport;
+            observer = _obs;
+            token = _token;
+            pkgInfo = null;
+            pmToken = 0;
+            needFullBackup = _needFullBackup;
+            filterSet = _filterSet;
         }
     }
 
@@ -402,7 +418,7 @@
                 Slog.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer);
                 (new PerformRestoreTask(params.transport, params.observer,
                         params.token, params.pkgInfo, params.pmToken,
-                        params.needFullBackup)).run();
+                        params.needFullBackup, params.filterSet)).run();
                 break;
             }
 
@@ -1587,8 +1603,7 @@
 
                 // Initiate the target's backup pass
                 prepareOperationTimeout(token, TIMEOUT_BACKUP_INTERVAL);
-                agent.doBackup(savedState, backupData, newState, false,
-                        token, mBackupManagerBinder);
+                agent.doBackup(savedState, backupData, newState, token, mBackupManagerBinder);
                 boolean success = waitUntilOperationComplete(token);
 
                 if (!success) {
@@ -1764,30 +1779,31 @@
             if (agent != null) {
                 try {
                     ApplicationInfo app = pkg.applicationInfo;
-                    boolean sendApk = mIncludeApks
+                    final boolean sendApk = mIncludeApks
                             && ((app.flags & ApplicationInfo.FLAG_FORWARD_LOCK) == 0)
                             && ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 ||
                                 (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
 
                     sendOnBackupPackage(pkg.packageName);
 
-                    {
-                        BackupDataOutput output = new BackupDataOutput(
-                                mOutputFile.getFileDescriptor());
+                    BackupDataOutput output = new BackupDataOutput(
+                            mOutputFile.getFileDescriptor());
 
-                        if (DEBUG) Slog.d(TAG, "Writing manifest for " + pkg.packageName);
-                        writeAppManifest(pkg, mManifestFile, sendApk);
-                        FullBackup.backupToTar(pkg.packageName, null, null,
-                                mFilesDir.getAbsolutePath(),
-                                mManifestFile.getAbsolutePath(),
-                                output);
+                    if (DEBUG) Slog.d(TAG, "Writing manifest for " + pkg.packageName);
+                    writeAppManifest(pkg, mManifestFile, sendApk);
+                    FullBackup.backupToTar(pkg.packageName, null, null,
+                            mFilesDir.getAbsolutePath(),
+                            mManifestFile.getAbsolutePath(),
+                            output);
+
+                    if (sendApk) {
+                        writeApkToBackup(pkg, output);
                     }
 
-                    if (DEBUG) Slog.d(TAG, "Calling doBackup()");
+                    if (DEBUG) Slog.d(TAG, "Calling doFullBackup()");
                     final int token = generateToken();
                     prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL);
-                    agent.doBackup(null, mOutputFile, null, sendApk,
-                            token, mBackupManagerBinder);
+                    agent.doFullBackup(mOutputFile, token, mBackupManagerBinder);
                     if (!waitUntilOperationComplete(token)) {
                         Slog.e(TAG, "Full backup failed on package " + pkg.packageName);
                     } else {
@@ -1802,6 +1818,29 @@
             tearDown(pkg);
         }
 
+        private void writeApkToBackup(PackageInfo pkg, BackupDataOutput output) {
+            // Forward-locked apps, system-bundled .apks, etc are filtered out before we get here
+            final String appSourceDir = pkg.applicationInfo.sourceDir;
+            final String apkDir = new File(appSourceDir).getParent();
+            FullBackup.backupToTar(pkg.packageName, FullBackup.APK_TREE_TOKEN, null,
+                    apkDir, appSourceDir, output);
+
+            // Save associated .obb content if it exists and we did save the apk
+            // check for .obb and save those too
+            final File obbDir = Environment.getExternalStorageAppObbDirectory(pkg.packageName);
+            if (obbDir != null) {
+                if (DEBUG) Log.i(TAG, "obb dir: " + obbDir.getAbsolutePath());
+                File[] obbFiles = obbDir.listFiles();
+                if (obbFiles != null) {
+                    final String obbDirName = obbDir.getAbsolutePath();
+                    for (File obb : obbFiles) {
+                        FullBackup.backupToTar(pkg.packageName, FullBackup.OBB_TREE_TOKEN, null,
+                                obbDirName, obb.getAbsolutePath(), output);
+                    }
+                }
+            }
+        }
+
         private void backupSharedStorage() throws RemoteException {
             PackageInfo pkg = null;
             try {
@@ -1813,7 +1852,7 @@
 
                     final int token = generateToken();
                     prepareOperationTimeout(token, TIMEOUT_SHARED_BACKUP_INTERVAL);
-                    agent.doBackup(null, mOutputFile, null, false, token, mBackupManagerBinder);
+                    agent.doFullBackup(mOutputFile, token, mBackupManagerBinder);
                     if (!waitUntilOperationComplete(token)) {
                         Slog.e(TAG, "Full backup failed on shared storage");
                     } else {
@@ -1933,7 +1972,7 @@
     static class FileMetadata {
         String packageName;             // name of the owning app
         String installerPackageName;    // name of the market-type app that installed the owner
-        int type;                       // e.g. FullBackup.TYPE_DIRECTORY
+        int type;                       // e.g. BackupAgent.TYPE_DIRECTORY
         String domain;                  // e.g. FullBackup.DATABASE_TREE_TOKEN
         String path;                    // subpath within the semantic domain
         long mode;                      // e.g. 0666 (actually int)
@@ -2182,15 +2221,15 @@
                                 // If we haven't sent any data to this app yet, we probably
                                 // need to clear it first.  Check that.
                                 if (!mClearedPackages.contains(pkg)) {
-                                    // apps with their own full backup agents are
+                                    // apps with their own backup agents are
                                     // responsible for coherently managing a full
                                     // restore.
-                                    if (mTargetApp.fullBackupAgentName == null) {
+                                    if (mTargetApp.backupAgentName == null) {
                                         if (DEBUG) Slog.d(TAG, "Clearing app data preparatory to full restore");
                                         clearApplicationDataSynchronous(pkg);
                                     } else {
-                                        if (DEBUG) Slog.d(TAG, "full backup agent ("
-                                                + mTargetApp.fullBackupAgentName + ") => no clear");
+                                        if (DEBUG) Slog.d(TAG, "backup agent ("
+                                                + mTargetApp.backupAgentName + ") => no clear");
                                     }
                                     mClearedPackages.add(pkg);
                                 } else {
@@ -2686,7 +2725,7 @@
                 StringBuilder b = new StringBuilder(128);
 
                 // mode string
-                b.append((info.type == FullBackup.TYPE_DIRECTORY) ? 'd' : '-');
+                b.append((info.type == BackupAgent.TYPE_DIRECTORY) ? 'd' : '-');
                 b.append(((info.mode & 0400) != 0) ? 'r' : '-');
                 b.append(((info.mode & 0200) != 0) ? 'w' : '-');
                 b.append(((info.mode & 0100) != 0) ? 'x' : '-');
@@ -2746,9 +2785,9 @@
                 }
 
                 switch (typeChar) {
-                    case '0': info.type = FullBackup.TYPE_FILE; break;
+                    case '0': info.type = BackupAgent.TYPE_FILE; break;
                     case '5': {
-                        info.type = FullBackup.TYPE_DIRECTORY;
+                        info.type = BackupAgent.TYPE_DIRECTORY;
                         if (info.size != 0) {
                             Slog.w(TAG, "Directory entry with nonzero size in header");
                             info.size = 0;
@@ -2995,6 +3034,7 @@
         private File mStateDir;
         private int mPmToken;
         private boolean mNeedFullBackup;
+        private HashSet<String> mFilterSet;
 
         class RestoreRequest {
             public PackageInfo app;
@@ -3008,7 +3048,7 @@
 
         PerformRestoreTask(IBackupTransport transport, IRestoreObserver observer,
                 long restoreSetToken, PackageInfo targetPackage, int pmToken,
-                boolean needFullBackup) {
+                boolean needFullBackup, String[] filterSet) {
             mTransport = transport;
             mObserver = observer;
             mToken = restoreSetToken;
@@ -3016,6 +3056,15 @@
             mPmToken = pmToken;
             mNeedFullBackup = needFullBackup;
 
+            if (filterSet != null) {
+                mFilterSet = new HashSet<String>();
+                for (String pkg : filterSet) {
+                    mFilterSet.add(pkg);
+                }
+            } else {
+                mFilterSet = null;
+            }
+
             try {
                 mStateDir = new File(mBaseStateDir, transport.transportDirName());
             } catch (RemoteException e) {
@@ -3027,7 +3076,8 @@
             long startRealtime = SystemClock.elapsedRealtime();
             if (DEBUG) Slog.v(TAG, "Beginning restore process mTransport=" + mTransport
                     + " mObserver=" + mObserver + " mToken=" + Long.toHexString(mToken)
-                    + " mTargetPackage=" + mTargetPackage + " mPmToken=" + mPmToken);
+                    + " mTargetPackage=" + mTargetPackage + " mFilterSet=" + mFilterSet
+                    + " mPmToken=" + mPmToken);
 
             PackageManagerBackupAgent pmAgent = null;
             int error = -1; // assume error
@@ -3046,6 +3096,22 @@
 
                 List<PackageInfo> agentPackages = allAgentPackages();
                 if (mTargetPackage == null) {
+                    // if there's a filter set, strip out anything that isn't
+                    // present before proceeding
+                    if (mFilterSet != null) {
+                        for (int i = agentPackages.size() - 1; i >= 0; i--) {
+                            final PackageInfo pkg = agentPackages.get(i);
+                            if (! mFilterSet.contains(pkg.packageName)) {
+                                agentPackages.remove(i);
+                            }
+                        }
+                        if (DEBUG) {
+                            Slog.i(TAG, "Post-filter package set for restore:");
+                            for (PackageInfo p : agentPackages) {
+                                Slog.i(TAG, "    " + p);
+                            }
+                        }
+                    }
                     restorePackages.addAll(agentPackages);
                 } else {
                     // Just one package to attempt restore of
@@ -4241,6 +4307,67 @@
             return -1;
         }
 
+        public synchronized int restoreSome(long token, IRestoreObserver observer,
+                String[] packages) {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
+                    "performRestore");
+
+            if (DEBUG) {
+                StringBuilder b = new StringBuilder(128);
+                b.append("restoreSome token=");
+                b.append(Long.toHexString(token));
+                b.append(" observer=");
+                b.append(observer.toString());
+                b.append(" packages=");
+                if (packages == null) {
+                    b.append("null");
+                } else {
+                    b.append('{');
+                    boolean first = true;
+                    for (String s : packages) {
+                        if (!first) {
+                            b.append(", ");
+                        } else first = false;
+                        b.append(s);
+                    }
+                    b.append('}');
+                }
+                Slog.d(TAG, b.toString());
+            }
+
+            if (mEnded) {
+                throw new IllegalStateException("Restore session already ended");
+            }
+
+            if (mRestoreTransport == null || mRestoreSets == null) {
+                Slog.e(TAG, "Ignoring restoreAll() with no restore set");
+                return -1;
+            }
+
+            if (mPackageName != null) {
+                Slog.e(TAG, "Ignoring restoreAll() on single-package session");
+                return -1;
+            }
+
+            synchronized (mQueueLock) {
+                for (int i = 0; i < mRestoreSets.length; i++) {
+                    if (token == mRestoreSets[i].token) {
+                        long oldId = Binder.clearCallingIdentity();
+                        mWakelock.acquire();
+                        Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
+                        msg.obj = new RestoreParams(mRestoreTransport, observer, token,
+                                packages, true);
+                        mBackupHandler.sendMessage(msg);
+                        Binder.restoreCallingIdentity(oldId);
+                        return 0;
+                    }
+                }
+            }
+
+            Slog.w(TAG, "Restore token " + Long.toHexString(token) + " not found");
+            return -1;
+        }
+
         public synchronized int restorePackage(String packageName, IRestoreObserver observer) {
             if (DEBUG) Slog.v(TAG, "restorePackage pkg=" + packageName + " obs=" + observer);
 
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index e6f443a..41450d2 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -44,7 +44,6 @@
 import android.net.Proxy;
 import android.net.ProxyProperties;
 import android.net.RouteInfo;
-import android.net.vpn.VpnManager;
 import android.net.wifi.WifiStateTracker;
 import android.os.Binder;
 import android.os.FileUtils;
@@ -65,6 +64,7 @@
 import android.util.Slog;
 import android.util.SparseIntArray;
 
+import com.android.internal.net.LegacyVpnInfo;
 import com.android.internal.net.VpnConfig;
 import com.android.internal.telephony.Phone;
 import com.android.server.connectivity.Tethering;
@@ -131,8 +131,6 @@
      */
     private List mNetRequestersPids[];
 
-    private WifiWatchdogService mWifiWatchdogService;
-
     // priority order of the nettrackers
     // (excluding dynamically set mNetworkPreference)
     // TODO - move mNetworkTypePreference into this
@@ -278,6 +276,9 @@
     }
     RadioAttributes[] mRadioAttributes;
 
+    // the set of network types that can only be enabled by system/sig apps
+    List mProtectedNetworks;
+
     public ConnectivityService(
             Context context, INetworkManagementService netd, INetworkPolicyManager policyManager) {
         if (DBG) log("ConnectivityService starting up");
@@ -381,6 +382,17 @@
             }
         }
 
+        mProtectedNetworks = new ArrayList<Integer>();
+        int[] protectedNetworks = context.getResources().getIntArray(
+                com.android.internal.R.array.config_protectedNetworks);
+        for (int p : protectedNetworks) {
+            if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
+                mProtectedNetworks.add(p);
+            } else {
+                if (DBG) loge("Ignoring protectedNetwork " + p);
+            }
+        }
+
         // high priority first
         mPriorityList = new int[mNetworksDefined];
         {
@@ -432,10 +444,6 @@
                 wifiService.checkAndStartWifi();
                 mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
                 wst.startMonitoring(context, mHandler);
-
-                //TODO: as part of WWS refactor, create only when needed
-                mWifiWatchdogService = new WifiWatchdogService(context);
-
                 break;
             case ConnectivityManager.TYPE_MOBILE:
                 mNetTrackers[netType] = new MobileDataStateTracker(netType,
@@ -488,11 +496,8 @@
         mSettingsObserver.observe(mContext);
 
         loadGlobalProxy();
-
-        VpnManager.startVpnService(context);
     }
 
-
     /**
      * Sets the preferred network.
      * @param preference the new preference
@@ -802,6 +807,11 @@
                 usedNetworkType = networkType;
             }
         }
+
+        if (mProtectedNetworks.contains(usedNetworkType)) {
+            enforceConnectivityInternalPermission();
+        }
+
         NetworkStateTracker network = mNetTrackers[usedNetworkType];
         if (network != null) {
             Integer currentPid = new Integer(getCallingPid());
@@ -1012,6 +1022,10 @@
      */
     public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
         enforceChangePermission();
+        if (mProtectedNetworks.contains(networkType)) {
+            enforceConnectivityInternalPermission();
+        }
+
         if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
             return false;
         }
@@ -1129,7 +1143,8 @@
     }
 
     public void setDataDependency(int networkType, boolean met) {
-        enforceChangePermission();
+        enforceConnectivityInternalPermission();
+
         if (DBG) {
             log("setDataDependency(" + networkType + ", " + met + ")");
         }
@@ -1587,11 +1602,23 @@
             if (linkProperties != null) {
                 String iface = linkProperties.getInterfaceName();
                 if (TextUtils.isEmpty(iface) == false) {
-                    if (DBG) log("resetConnections(" + iface + ")");
-                    NetworkUtils.resetConnections(iface);
+                    if (DBG) {
+                        log("resetConnections(" + iface + ", NetworkUtils.RESET_ALL_ADDRESSES)");
+                    }
+                    NetworkUtils.resetConnections(iface, NetworkUtils.RESET_ALL_ADDRESSES);
                 }
             }
         }
+
+        // TODO: Temporary notifying upstread change to Tethering.
+        //       @see bug/4455071
+        /** Notify TetheringService if interface name has been changed. */
+        if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
+                             Phone.REASON_LINK_PROPERTIES_CHANGED)) {
+            if (isTetheringSupported()) {
+                mTethering.handleTetherIfaceChange();
+            }
+        }
     }
 
     private void addPrivateDnsRoutes(NetworkStateTracker nt) {
@@ -2017,7 +2044,10 @@
                     break;
                 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
                     info = (NetworkInfo) msg.obj;
-                    handleConnectivityChange(info.getType(), true);
+                    // TODO: Temporary allowing network configuration
+                    //       change not resetting sockets.
+                    //       @see bug/4455071
+                    handleConnectivityChange(info.getType(), false);
                     break;
                 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
                     String causedBy = null;
@@ -2442,8 +2472,8 @@
 
     /**
      * Protect a socket from VPN routing rules. This method is used by
-     * VpnBuilder and not available in ConnectivityManager. Permission
-     * checks are done in Vpn class.
+     * VpnBuilder and not available in ConnectivityManager. Permissions
+     * are checked in Vpn class.
      * @hide
      */
     @Override
@@ -2453,20 +2483,20 @@
 
     /**
      * Prepare for a VPN application. This method is used by VpnDialogs
-     * and not available in ConnectivityManager. Permission checks are
-     * done in Vpn class.
+     * and not available in ConnectivityManager. Permissions are checked
+     * in Vpn class.
      * @hide
      */
     @Override
-    public String prepareVpn(String packageName) {
-        return mVpn.prepare(packageName);
+    public boolean prepareVpn(String oldPackage, String newPackage) {
+        return mVpn.prepare(oldPackage, newPackage);
     }
 
     /**
      * Configure a TUN interface and return its file descriptor. Parameters
      * are encoded and opaque to this class. This method is used by VpnBuilder
-     * and not available in ConnectivityManager. Permission checks are done
-     * in Vpn class.
+     * and not available in ConnectivityManager. Permissions are checked in
+     * Vpn class.
      * @hide
      */
     @Override
@@ -2474,6 +2504,28 @@
         return mVpn.establish(config);
     }
 
+    /**
+     * Start legacy VPN and return an intent to VpnDialogs. This method is
+     * used by VpnSettings and not available in ConnectivityManager.
+     * Permissions are checked in Vpn class.
+     * @hide
+     */
+    @Override
+    public void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) {
+        mVpn.startLegacyVpn(config, racoon, mtpd);
+    }
+
+    /**
+     * Return the information of the ongoing legacy VPN. This method is used
+     * by VpnSettings and not available in ConnectivityManager. Permissions
+     * are checked in Vpn class.
+     * @hide
+     */
+    @Override
+    public LegacyVpnInfo getLegacyVpnInfo() {
+        return mVpn.getLegacyVpnInfo();
+    }
+
     private String getDefaultInterface() {
         if (ConnectivityManager.isNetworkTypeValid(mActiveDefaultNetwork)) {
             NetworkStateTracker tracker = mNetTrackers[mActiveDefaultNetwork];
@@ -2502,7 +2554,7 @@
         private VpnCallback() {
         }
 
-        public synchronized void override(String[] dnsServers) {
+        public synchronized void override(List<String> dnsServers, List<String> searchDomains) {
             // TODO: override DNS servers and http proxy.
         }
 
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 8037d7a..2d55433 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -137,6 +137,7 @@
     private static final String NOT_A_SUBTYPE_ID_STR = String.valueOf(NOT_A_SUBTYPE_ID);
     private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
     private static final String SUBTYPE_MODE_VOICE = "voice";
+    private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
 
     final Context mContext;
     final Resources mRes;
@@ -1057,25 +1058,44 @@
         synchronized (mMethodMap) {
             List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
             final int N = imis.size();
-            int count = 0;
+            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 = getEnabledInputMethodSubtypeListLocked(
                         imi, true);
                 final int subtypeCount = subtypes.size();
                 if (subtypeCount == 0) {
-                    ++count;
+                    ++nonAuxCount;
                 } else {
                     for (int j = 0; j < subtypeCount; ++j) {
-                        if (!subtypes.get(j).isAuxiliary()) {
-                            ++count;
+                        final InputMethodSubtype subtype = subtypes.get(j);
+                        if (!subtype.isAuxiliary()) {
+                            ++nonAuxCount;
+                            nonAuxSubtype = subtype;
+                        } else {
+                            ++auxCount;
+                            auxSubtype = subtype;
                         }
                     }
                 }
-                if (count > 1) return true;
             }
+            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;
         }
-        return false;
     }
 
     @Override
@@ -1603,8 +1623,11 @@
             if (lastImi == null) return null;
             try {
                 final int lastSubtypeHash = Integer.valueOf(lastIme.second);
-                return lastImi.getSubtypeAt(getSubtypeIdFromHashCode(
-                        lastImi, lastSubtypeHash));
+                final int lastSubtypeId = getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
+                if (lastSubtypeId < 0 || lastSubtypeId >= lastImi.getSubtypeCount()) {
+                    return null;
+                }
+                return lastImi.getSubtypeAt(lastSubtypeId);
             } catch (NumberFormatException e) {
                 return null;
             }
@@ -1621,7 +1644,7 @@
             final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
             if (imi == null) return false;
             final int N = subtypes.length;
-            mFileManager.addInputMethodSubtypes(mCurMethodId, subtypes);
+            mFileManager.addInputMethodSubtypes(imi, subtypes);
             buildInputMethodListLocked(mMethodList, mMethodMap);
             return true;
         }
@@ -2003,25 +2026,26 @@
                 final CharSequence label = imi.loadLabel(pm);
                 if (showSubtypes && enabledSubtypeSet.size() > 0) {
                     final int subtypeCount = imi.getSubtypeCount();
+                    if (DEBUG) {
+                        Slog.v(TAG, "Add subtypes: " + subtypeCount + ", " + imi.getId());
+                    }
                     for (int j = 0; j < subtypeCount; ++j) {
-                        InputMethodSubtype subtype = imi.getSubtypeAt(j);
-                        if (enabledSubtypeSet.contains(String.valueOf(subtype.hashCode()))
-                                && !subtype.isAuxiliary()) {
+                        final InputMethodSubtype subtype = imi.getSubtypeAt(j);
+                        final String subtypeHashCode = String.valueOf(subtype.hashCode());
+                        // We show all enabled IMEs and subtypes when an IME is shown.
+                        if (enabledSubtypeSet.contains(subtypeHashCode)
+                                && (mInputShown || !subtype.isAuxiliary())) {
                             final CharSequence title;
-                            int nameResId = subtype.getNameResId();
-                            String mode = subtype.getMode();
-                            if (nameResId != 0) {
-                                title = TextUtils.concat(subtype.getDisplayName(context,
-                                        imi.getPackageName(), imi.getServiceInfo().applicationInfo),
-                                        (TextUtils.isEmpty(label) ? "" : " (" + label + ")"));
-                            } else {
-                                CharSequence language = subtype.getLocale();
-                                // TODO: Use more friendly Title and UI
-                                title = label + "," + (mode == null ? "" : mode) + ","
-                                        + (language == null ? "" : language);
-                            }
+                            final String mode = subtype.getMode();
+                            title = TextUtils.concat(subtype.getDisplayName(context,
+                                    imi.getPackageName(), imi.getServiceInfo().applicationInfo),
+                                    (TextUtils.isEmpty(label) ? "" : " (" + label + ")"));
                             imList.add(new Pair<CharSequence, Pair<InputMethodInfo, Integer>>(
                                     title, new Pair<InputMethodInfo, Integer>(imi, j)));
+                            // Removing this subtype from enabledSubtypeSet because we no longer
+                            // need to add an entry of this subtype to imList to avoid duplicated
+                            // entries.
+                            enabledSubtypeSet.remove(subtypeHashCode);
                         }
                     }
                 } else {
@@ -2318,7 +2342,7 @@
                 }
             }
         }
-        ArrayList<InputMethodSubtype> applicableSubtypes = new ArrayList<InputMethodSubtype>(
+        final ArrayList<InputMethodSubtype> applicableSubtypes = new ArrayList<InputMethodSubtype>(
                 applicableModeAndSubtypesMap.values());
         if (!containsKeyboardSubtype) {
             InputMethodSubtype lastResortKeyboardSubtype = findLastResortApplicableSubtypeLocked(
@@ -2996,17 +3020,23 @@
         }
 
         public void addInputMethodSubtypes(
-                String imiId, InputMethodSubtype[] additionalSubtypes) {
+                InputMethodInfo imi, InputMethodSubtype[] additionalSubtypes) {
             synchronized (mMethodMap) {
+                final HashSet<InputMethodSubtype> existingSubtypes =
+                        new HashSet<InputMethodSubtype>();
+                for (int i = 0; i < imi.getSubtypeCount(); ++i) {
+                    existingSubtypes.add(imi.getSubtypeAt(i));
+                }
+
                 final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
                 final int N = additionalSubtypes.length;
                 for (int i = 0; i < N; ++i) {
                     final InputMethodSubtype subtype = additionalSubtypes[i];
-                    if (!subtypes.contains(subtype)) {
+                    if (!subtypes.contains(subtype) && !existingSubtypes.contains(subtype)) {
                         subtypes.add(subtype);
                     }
                 }
-                mSubtypesMap.put(imiId, subtypes);
+                mSubtypesMap.put(imi.getId(), subtypes);
                 writeAdditionalInputMethodSubtypes(mSubtypesMap, mAdditionalInputMethodSubtypeFile,
                         mMethodMap);
             }
@@ -3113,8 +3143,8 @@
                                 parser.getAttributeValue(null, ATTR_IME_SUBTYPE_MODE);
                         final String imeSubtypeExtraValue =
                                 parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
-                        final boolean isAuxiliary =
-                                Boolean.valueOf(parser.getAttributeValue(null, ATTR_IS_AUXILIARY));
+                        final boolean isAuxiliary = "1".equals(String.valueOf(
+                                parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
                         final InputMethodSubtype subtype =
                                 new InputMethodSubtype(label, icon, imeSubtypeLocale,
                                         imeSubtypeMode, imeSubtypeExtraValue, isAuxiliary);
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index 1d3e3ac..b3d7220 100644
--- a/services/java/com/android/server/IntentResolver.java
+++ b/services/java/com/android/server/IntentResolver.java
@@ -41,7 +41,7 @@
 /**
  * {@hide}
  */
-public class IntentResolver<F extends IntentFilter, R extends Object> {
+public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
     final private static String TAG = "IntentResolver";
     final private static boolean DEBUG = false;
     final private static boolean localLOGV = DEBUG || false;
@@ -333,14 +333,19 @@
         return false;
     }
 
-    protected String packageForFilter(F filter) {
-        return null;
-    }
+    /**
+     * Return the package that owns this filter.  This must be implemented to
+     * provide correct filtering of Intents that have specified a package name
+     * they are to be delivered to.
+     */
+    protected abstract String packageForFilter(F filter);
     
+    @SuppressWarnings("unchecked")
     protected R newResult(F filter, int match) {
         return (R)filter;
     }
 
+    @SuppressWarnings("unchecked")
     protected void sortResults(List<R> results) {
         Collections.sort(results, mResolvePrioritySorter);
     }
@@ -502,6 +507,7 @@
             String resolvedType, String scheme, List<F> src, List<R> dest) {
         final String action = intent.getAction();
         final Uri data = intent.getData();
+        final String packageName = intent.getPackage();
 
         final boolean excludingStopped = intent.isExcludingStopped();
 
@@ -520,6 +526,14 @@
                 continue;
             }
 
+            // Is delivery being limited to filters owned by a particular package?
+            if (packageName != null && !packageName.equals(packageForFilter(filter))) {
+                if (debug) {
+                    Slog.v(TAG, "  Filter is not from package " + packageName + "; skipping");
+                }
+                continue;
+            }
+
             // Do we already have this one?
             if (!allowFilterResult(filter, dest)) {
                 if (debug) {
@@ -561,6 +575,7 @@
     }
 
     // Sorts a List of IntentFilter objects into descending priority order.
+    @SuppressWarnings("rawtypes")
     private static final Comparator mResolvePrioritySorter = new Comparator() {
         public int compare(Object o1, Object o2) {
             final int q1 = ((IntentFilter) o1).getPriority();
diff --git a/services/java/com/android/server/LoadAverageService.java b/services/java/com/android/server/LoadAverageService.java
index b6baadb..da9fc99 100644
--- a/services/java/com/android/server/LoadAverageService.java
+++ b/services/java/com/android/server/LoadAverageService.java
@@ -278,14 +278,14 @@
             PixelFormat.TRANSLUCENT);
         params.gravity = Gravity.RIGHT | Gravity.TOP;
         params.setTitle("Load Average");
-        WindowManagerImpl wm = (WindowManagerImpl)getSystemService(WINDOW_SERVICE);
+        WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE);
         wm.addView(mView, params);
     }
 
     @Override
     public void onDestroy() {
         super.onDestroy();
-        ((WindowManagerImpl)getSystemService(WINDOW_SERVICE)).removeView(mView);
+        ((WindowManager)getSystemService(WINDOW_SERVICE)).removeView(mView);
         mView = null;
     }
 
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 656ec4d..56afe7f 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -195,6 +195,7 @@
         final Object mKey;
         final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
         int mPendingBroadcasts;
+        String requiredPermissions;
 
         Receiver(ILocationListener listener) {
             mListener = listener;
@@ -284,7 +285,8 @@
                     synchronized (this) {
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
-                        mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler);
+                        mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
+                                requiredPermissions);
                         // call this after broadcasting so we do not increment
                         // if we throw an exeption.
                         incrementPendingBroadcastsLocked();
@@ -319,7 +321,8 @@
                     synchronized (this) {
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
-                        mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler);
+                        mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
+                                requiredPermissions);
                         // call this after broadcasting so we do not increment
                         // if we throw an exeption.
                         incrementPendingBroadcastsLocked();
@@ -358,7 +361,8 @@
                     synchronized (this) {
                         // synchronize to ensure incrementPendingBroadcastsLocked()
                         // is called before decrementPendingBroadcasts()
-                        mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler);
+                        mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
+                                requiredPermissions);
                         // call this after broadcasting so we do not increment
                         // if we throw an exeption.
                         incrementPendingBroadcastsLocked();
@@ -572,22 +576,30 @@
         return Settings.Secure.isLocationProviderEnabled(resolver, provider);
     }
 
-    private void checkPermissionsSafe(String provider) {
-        if ((LocationManager.GPS_PROVIDER.equals(provider)
-                 || LocationManager.PASSIVE_PROVIDER.equals(provider))
-            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
-                != PackageManager.PERMISSION_GRANTED)) {
-            throw new SecurityException("Provider " + provider
-                    + " requires ACCESS_FINE_LOCATION permission");
+    private String checkPermissionsSafe(String provider, String lastPermission) {
+        if (LocationManager.GPS_PROVIDER.equals(provider)
+                 || LocationManager.PASSIVE_PROVIDER.equals(provider)) {
+            if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
+                    != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("Provider " + provider
+                        + " requires ACCESS_FINE_LOCATION permission");
+            }
+            return ACCESS_FINE_LOCATION;
         }
-        if (LocationManager.NETWORK_PROVIDER.equals(provider)
-            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
-                != PackageManager.PERMISSION_GRANTED)
-            && (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
-                != PackageManager.PERMISSION_GRANTED)) {
-            throw new SecurityException("Provider " + provider
-                    + " requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission");
+
+        // Assume any other provider requires the coarse or fine permission.
+        if (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
+                == PackageManager.PERMISSION_GRANTED) {
+            return ACCESS_FINE_LOCATION.equals(lastPermission)
+                    ? lastPermission : ACCESS_COARSE_LOCATION;
         }
+        if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
+                == PackageManager.PERMISSION_GRANTED) {
+            return ACCESS_FINE_LOCATION;
+        }
+
+        throw new SecurityException("Provider " + provider
+                + " requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission");
     }
 
     private boolean isAllowedProviderSafe(String provider) {
@@ -1099,8 +1111,21 @@
         }
     }
 
+    void validatePendingIntent(PendingIntent intent) {
+        if (intent.isTargetedToPackage()) {
+            return;
+        }
+        Slog.i(TAG, "Given Intent does not require a specific package: "
+                + intent);
+        // XXX we should really throw a security exception, if the caller's
+        // targetSdkVersion is high enough.
+        //throw new SecurityException("Given Intent does not require a specific package: "
+        //        + intent);
+    }
+
     public void requestLocationUpdatesPI(String provider, Criteria criteria,
             long minTime, float minDistance, boolean singleShot, PendingIntent intent) {
+        validatePendingIntent(intent);
         if (criteria != null) {
             // FIXME - should we consider using multiple providers simultaneously
             // rather than only the best one?
@@ -1132,7 +1157,8 @@
             throw new IllegalArgumentException("provider=" + provider);
         }
 
-        checkPermissionsSafe(provider);
+        receiver.requiredPermissions = checkPermissionsSafe(provider,
+                receiver.requiredPermissions);
 
         // so wakelock calls will succeed
         final int callingUid = Binder.getCallingUid();
@@ -1300,7 +1326,7 @@
         }
 
         // first check for permission to the provider
-        checkPermissionsSafe(provider);
+        checkPermissionsSafe(provider, null);
         // and check for ACCESS_LOCATION_EXTRA_COMMANDS
         if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
                 != PackageManager.PERMISSION_GRANTED)) {
@@ -1432,7 +1458,8 @@
                             synchronized (this) {
                                 // synchronize to ensure incrementPendingBroadcasts()
                                 // is called before decrementPendingBroadcasts()
-                                intent.send(mContext, 0, enteredIntent, this, mLocationHandler);
+                                intent.send(mContext, 0, enteredIntent, this, mLocationHandler,
+                                        ACCESS_FINE_LOCATION);
                                 // call this after broadcasting so we do not increment
                                 // if we throw an exeption.
                                 incrementPendingBroadcasts();
@@ -1457,7 +1484,8 @@
                             synchronized (this) {
                                 // synchronize to ensure incrementPendingBroadcasts()
                                 // is called before decrementPendingBroadcasts()
-                                intent.send(mContext, 0, exitedIntent, this, mLocationHandler);
+                                intent.send(mContext, 0, exitedIntent, this, mLocationHandler,
+                                        ACCESS_FINE_LOCATION);
                                 // call this after broadcasting so we do not increment
                                 // if we throw an exeption.
                                 incrementPendingBroadcasts();
@@ -1526,6 +1554,7 @@
 
     public void addProximityAlert(double latitude, double longitude,
         float radius, long expiration, PendingIntent intent) {
+        validatePendingIntent(intent);
         try {
             synchronized (mLock) {
                 addProximityAlertLocked(latitude, longitude, radius, expiration, intent);
@@ -1626,7 +1655,7 @@
             return null;
         }
 
-        checkPermissionsSafe(provider);
+        checkPermissionsSafe(provider, null);
 
         Bundle b = new Bundle();
         b.putBoolean("network", p.requiresNetwork());
@@ -1668,7 +1697,7 @@
     }
 
     private boolean _isProviderEnabledLocked(String provider) {
-        checkPermissionsSafe(provider);
+        checkPermissionsSafe(provider, null);
 
         LocationProviderInterface p = mProvidersByName.get(provider);
         if (p == null) {
@@ -1694,7 +1723,7 @@
     }
 
     private Location _getLastKnownLocationLocked(String provider) {
-        checkPermissionsSafe(provider);
+        checkPermissionsSafe(provider, null);
 
         LocationProviderInterface p = mProvidersByName.get(provider);
         if (p == null) {
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index d3244ec..2e54c99 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -1075,18 +1075,22 @@
                             com.android.internal.R.styleable.Storage_mtpReserve, 0);
                     boolean allowMassStorage = a.getBoolean(
                             com.android.internal.R.styleable.Storage_allowMassStorage, false);
+                    // resource parser does not support longs, so XML value is in megabytes
+                    long maxFileSize = a.getInt(
+                            com.android.internal.R.styleable.Storage_maxFileSize, 0) * 1024L * 1024L;
 
                     Slog.d(TAG, "got storage path: " + path + " description: " + description +
                             " primary: " + primary + " removable: " + removable +
                             " emulated: " + emulated +  " mtpReserve: " + mtpReserve +
-                            " allowMassStorage: " + allowMassStorage);
+                            " allowMassStorage: " + allowMassStorage +
+                            " maxFileSize: " + maxFileSize);
                     if (path == null || description == null) {
                         Slog.e(TAG, "path or description is null in readStorageList");
                     } else {
                         String pathString = path.toString();
                         StorageVolume volume = new StorageVolume(pathString,
                                 description.toString(), removable, emulated,
-                                mtpReserve, allowMassStorage);
+                                mtpReserve, allowMassStorage, maxFileSize);
                         if (primary) {
                             if (mPrimaryVolume == null) {
                                 mPrimaryVolume = volume;
@@ -1626,6 +1630,30 @@
         }
     }
 
+    public String getSecureContainerFilesystemPath(String id) {
+        validatePermission(android.Manifest.permission.ASEC_ACCESS);
+        waitForReady();
+        warnOnNotMounted();
+
+        try {
+            ArrayList<String> rsp = mConnector.doCommand(String.format("asec fspath %s", id));
+            String []tok = rsp.get(0).split(" ");
+            int code = Integer.parseInt(tok[0]);
+            if (code != VoldResponseCode.AsecPathResult) {
+                throw new IllegalStateException(String.format("Unexpected response code %d", code));
+            }
+            return tok[1];
+        } catch (NativeDaemonConnectorException e) {
+            int code = e.getCode();
+            if (code == VoldResponseCode.OpFailedStorageNotFound) {
+                Slog.i(TAG, String.format("Container '%s' not found", id));
+                return null;
+            } else {
+                throw new IllegalStateException(String.format("Unexpected response code %d", code));
+            }
+        }
+    }
+
     public void finishMediaUpdate() {
         mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE);
     }
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 2b01c5e..da1bf83 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -16,10 +16,11 @@
 
 package com.android.server;
 
+import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
 import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
-import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
+import static android.provider.Settings.Secure.NETSTATS_ENABLED;
 
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -35,8 +36,14 @@
 import android.os.INetworkManagementService;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.provider.Settings;
 import android.util.Log;
 import android.util.Slog;
+import android.util.SparseBooleanArray;
+
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
+import com.google.android.collect.Sets;
 
 import java.io.BufferedReader;
 import java.io.DataInputStream;
@@ -47,7 +54,10 @@
 import java.io.InputStreamReader;
 import java.net.Inet4Address;
 import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.NoSuchElementException;
 import java.util.StringTokenizer;
 import java.util.concurrent.CountDownLatch;
@@ -65,9 +75,18 @@
     private static final int ADD = 1;
     private static final int REMOVE = 2;
 
+    /** Path to {@code /proc/uid_stat}. */
     @Deprecated
-    private static final File STATS_UIDSTAT = new File("/proc/uid_stat");
-    private static final File STATS_NETFILTER = new File("/proc/net/xt_qtaguid/stats");
+    private final File mProcStatsUidstat;
+    /** Path to {@code /proc/net/xt_qtaguid/stats}. */
+    private final File mProcStatsNetfilter;
+
+    /** {@link #mProcStatsNetfilter} headers. */
+    private static final String KEY_IFACE = "iface";
+    private static final String KEY_TAG_HEX = "acct_tag_hex";
+    private static final String KEY_UID = "uid_tag_int";
+    private static final String KEY_RX = "rx_bytes";
+    private static final String KEY_TX = "tx_bytes";
 
     class NetdResponseCode {
         public static final int InterfaceListResult       = 110;
@@ -102,15 +121,25 @@
 
     private ArrayList<INetworkManagementEventObserver> mObservers;
 
+    /** Set of interfaces with active quotas. */
+    private HashSet<String> mInterfaceQuota = Sets.newHashSet();
+    /** Set of UIDs with active reject rules. */
+    private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();
+
+    private boolean mBandwidthControlEnabled;
+
     /**
      * Constructs a new NetworkManagementService instance
      *
      * @param context  Binder context for this service
      */
-    private NetworkManagementService(Context context) {
+    private NetworkManagementService(Context context, File procRoot) {
         mContext = context;
         mObservers = new ArrayList<INetworkManagementEventObserver>();
 
+        mProcStatsUidstat = new File(procRoot, "uid_stat");
+        mProcStatsNetfilter = new File(procRoot, "net/xt_qtaguid/stats");
+
         if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
             return;
         }
@@ -121,7 +150,8 @@
     }
 
     public static NetworkManagementService create(Context context) throws InterruptedException {
-        NetworkManagementService service = new NetworkManagementService(context);
+        NetworkManagementService service = new NetworkManagementService(
+                context, new File("/proc/"));
         if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
         service.mThread.start();
         if (DBG) Slog.d(TAG, "Awaiting socket connection");
@@ -130,6 +160,35 @@
         return service;
     }
 
+    // @VisibleForTesting
+    public static NetworkManagementService createForTest(Context context, File procRoot) {
+        // TODO: eventually connect with mock netd
+        return new NetworkManagementService(context, procRoot);
+    }
+
+    public void systemReady() {
+
+        // only enable bandwidth control when support exists, and requested by
+        // system setting.
+        // TODO: eventually migrate to be always enabled
+        final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
+        final boolean shouldEnable =
+                Settings.Secure.getInt(mContext.getContentResolver(), NETSTATS_ENABLED, 0) != 0;
+
+        mBandwidthControlEnabled = false;
+        if (hasKernelSupport && shouldEnable) {
+            Slog.d(TAG, "enabling bandwidth control");
+            try {
+                mConnector.doCommand("bandwidth enable");
+                mBandwidthControlEnabled = true;
+            } catch (NativeDaemonConnectorException e) {
+                Slog.e(TAG, "problem enabling bandwidth controls", e);
+            }
+        } else {
+            Slog.d(TAG, "not enabling bandwidth control");
+        }
+    }
+
     public void registerObserver(INetworkManagementEventObserver obs) {
         Slog.d(TAG, "Registering observer");
         mObservers.add(obs);
@@ -141,12 +200,26 @@
     }
 
     /**
-     * Notify our observers of an interface link status change
+     * Notify our observers of an interface status change
      */
-    private void notifyInterfaceLinkStatusChanged(String iface, boolean link) {
+    private void notifyInterfaceStatusChanged(String iface, boolean up) {
         for (INetworkManagementEventObserver obs : mObservers) {
             try {
-                obs.interfaceLinkStatusChanged(iface, link);
+                obs.interfaceStatusChanged(iface, up);
+            } catch (Exception ex) {
+                Slog.w(TAG, "Observer notifier failed", ex);
+            }
+        }
+    }
+
+    /**
+     * Notify our observers of an interface link state change
+     * (typically, an Ethernet cable has been plugged-in or unplugged).
+     */
+    private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
+        for (INetworkManagementEventObserver obs : mObservers) {
+            try {
+                obs.interfaceLinkStateChanged(iface, up);
             } catch (Exception ex) {
                 Slog.w(TAG, "Observer notifier failed", ex);
             }
@@ -207,6 +280,7 @@
                  * Format: "NNN Iface added <name>"
                  *         "NNN Iface removed <name>"
                  *         "NNN Iface changed <name> <up/down>"
+                 *         "NNN Iface linkstatus <name> <up/down>"
                  */
                 if (cooked.length < 4 || !cooked[1].equals("Iface")) {
                     throw new IllegalStateException(
@@ -219,7 +293,10 @@
                     notifyInterfaceRemoved(cooked[3]);
                     return true;
                 } else if (cooked[2].equals("changed") && cooked.length == 5) {
-                    notifyInterfaceLinkStatusChanged(cooked[3], cooked[4].equals("up"));
+                    notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
+                    return true;
+                } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
+                    notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
                     return true;
                 }
                 throw new IllegalStateException(
@@ -870,7 +947,7 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
 
-        if (STATS_NETFILTER.exists()) {
+        if (mBandwidthControlEnabled) {
             return getNetworkStatsDetailNetfilter(UID_ALL);
         } else {
             return getNetworkStatsDetailUidstat(UID_ALL);
@@ -878,13 +955,103 @@
     }
 
     @Override
+    public void setInterfaceQuota(String iface, long quota) {
+        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+        // silently discard when control disabled
+        // TODO: eventually migrate to be always enabled
+        if (!mBandwidthControlEnabled) return;
+
+        synchronized (mInterfaceQuota) {
+            if (mInterfaceQuota.contains(iface)) {
+                // TODO: eventually consider throwing
+                return;
+            }
+
+            final StringBuilder command = new StringBuilder();
+            command.append("bandwidth setiquota ").append(iface).append(" ").append(quota);
+
+            try {
+                // TODO: add support for quota shared across interfaces
+                mConnector.doCommand(command.toString());
+                mInterfaceQuota.add(iface);
+            } catch (NativeDaemonConnectorException e) {
+                throw new IllegalStateException("Error communicating to native daemon", e);
+            }
+        }
+    }
+
+    @Override
+    public void removeInterfaceQuota(String iface) {
+        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+        // silently discard when control disabled
+        // TODO: eventually migrate to be always enabled
+        if (!mBandwidthControlEnabled) return;
+
+        synchronized (mInterfaceQuota) {
+            if (!mInterfaceQuota.contains(iface)) {
+                // TODO: eventually consider throwing
+                return;
+            }
+
+            final StringBuilder command = new StringBuilder();
+            command.append("bandwidth removeiquota ").append(iface);
+
+            try {
+                // TODO: add support for quota shared across interfaces
+                mConnector.doCommand(command.toString());
+                mInterfaceQuota.remove(iface);
+            } catch (NativeDaemonConnectorException e) {
+                throw new IllegalStateException("Error communicating to native daemon", e);
+            }
+        }
+    }
+
+    @Override
+    public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
+        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+        // silently discard when control disabled
+        // TODO: eventually migrate to be always enabled
+        if (!mBandwidthControlEnabled) return;
+
+        synchronized (mUidRejectOnQuota) {
+            final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false);
+            if (oldRejectOnQuota == rejectOnQuotaInterfaces) {
+                // TODO: eventually consider throwing
+                return;
+            }
+
+            final StringBuilder command = new StringBuilder();
+            command.append("bandwidth");
+            if (rejectOnQuotaInterfaces) {
+                command.append(" addnaughtyapps");
+            } else {
+                command.append(" removenaughtyapps");
+            }
+            command.append(" ").append(uid);
+
+            try {
+                mConnector.doCommand(command.toString());
+                if (rejectOnQuotaInterfaces) {
+                    mUidRejectOnQuota.put(uid, true);
+                } else {
+                    mUidRejectOnQuota.delete(uid);
+                }
+            } catch (NativeDaemonConnectorException e) {
+                throw new IllegalStateException("Error communicating to native daemon", e);
+            }
+        }
+    }
+
     public NetworkStats getNetworkStatsUidDetail(int uid) {
         if (Binder.getCallingUid() != uid) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
         }
 
-        if (STATS_NETFILTER.exists()) {
+        if (mBandwidthControlEnabled) {
             return getNetworkStatsDetailNetfilter(uid);
         } else {
             return getNetworkStatsDetailUidstat(uid);
@@ -896,35 +1063,36 @@
      */
     private NetworkStats getNetworkStatsDetailNetfilter(int limitUid) {
         final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24);
+        final ArrayList<String> keys = Lists.newArrayList();
+        final ArrayList<String> values = Lists.newArrayList();
+        final HashMap<String, String> parsed = Maps.newHashMap();
 
         BufferedReader reader = null;
         try {
-            reader = new BufferedReader(new FileReader(STATS_NETFILTER));
+            reader = new BufferedReader(new FileReader(mProcStatsNetfilter));
 
-            // assumes format from kernel:
-            // idx iface acct_tag_hex uid_tag_int rx_bytes tx_bytes
-
-            // skip first line, which is legend
+            // parse first line as header
             String line = reader.readLine();
-            while ((line = reader.readLine()) != null) {
-                final StringTokenizer t = new StringTokenizer(line);
+            splitLine(line, keys);
 
-                final String idx = t.nextToken();
-                final String iface = t.nextToken();
+            // parse remaining lines
+            while ((line = reader.readLine()) != null) {
+                splitLine(line, values);
+                parseLine(keys, values, parsed);
 
                 try {
-                    // TODO: kernel currently emits tag in upper half of long;
-                    // eventually switch to directly using int.
-                    final int tag = (int) (Long.parseLong(t.nextToken().substring(2), 16) >> 32);
-                    final int uid = Integer.parseInt(t.nextToken());
-                    final long rx = Long.parseLong(t.nextToken());
-                    final long tx = Long.parseLong(t.nextToken());
+                    final String iface = parsed.get(KEY_IFACE);
+                    final int tag = NetworkManagementSocketTagger.kernelToTag(
+                            parsed.get(KEY_TAG_HEX));
+                    final int uid = Integer.parseInt(parsed.get(KEY_UID));
+                    final long rx = Long.parseLong(parsed.get(KEY_RX));
+                    final long tx = Long.parseLong(parsed.get(KEY_TX));
 
                     if (limitUid == UID_ALL || limitUid == uid) {
                         stats.addEntry(iface, uid, tag, rx, tx);
                     }
                 } catch (NumberFormatException e) {
-                    Slog.w(TAG, "problem parsing stats for idx " + idx + ": " + e);
+                    Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
                 }
             }
         } catch (IOException e) {
@@ -946,7 +1114,7 @@
     private NetworkStats getNetworkStatsDetailUidstat(int limitUid) {
         final String[] knownUids;
         if (limitUid == UID_ALL) {
-            knownUids = STATS_UIDSTAT.list();
+            knownUids = mProcStatsUidstat.list();
         } else {
             knownUids = new String[] { String.valueOf(limitUid) };
         }
@@ -955,7 +1123,7 @@
                 SystemClock.elapsedRealtime(), knownUids.length);
         for (String uid : knownUids) {
             final int uidInt = Integer.parseInt(uid);
-            final File uidPath = new File(STATS_UIDSTAT, uid);
+            final File uidPath = new File(mProcStatsUidstat, uid);
             final long rx = readSingleLongFromFile(new File(uidPath, "tcp_rcv"));
             final long tx = readSingleLongFromFile(new File(uidPath, "tcp_snd"));
             stats.addEntry(IFACE_ALL, uidInt, TAG_NONE, rx, tx);
@@ -1023,10 +1191,30 @@
         return getInterfaceThrottle(iface, false);
     }
 
-    @Override
-    public void setBandwidthControlEnabled(boolean enabled) {
-        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
-        mConnector.doCommand(String.format("bandwidth %s", (enabled ? "enable" : "disable")));
+    /**
+     * Split given line into {@link ArrayList}.
+     */
+    private static void splitLine(String line, ArrayList<String> outSplit) {
+        outSplit.clear();
+
+        final StringTokenizer t = new StringTokenizer(line);
+        while (t.hasMoreTokens()) {
+            outSplit.add(t.nextToken());
+        }
+    }
+
+    /**
+     * Zip the two given {@link ArrayList} as key and value pairs into
+     * {@link HashMap}.
+     */
+    private static void parseLine(
+            ArrayList<String> keys, ArrayList<String> values, HashMap<String, String> outParsed) {
+        outParsed.clear();
+
+        final int size = Math.min(keys.size(), values.size());
+        for (int i = 0; i < size; i++) {
+            outParsed.put(keys.get(i), values.get(i));
+        }
     }
 
     /**
@@ -1043,4 +1231,65 @@
             return -1;
         }
     }
+
+    public void setDefaultInterfaceForDns(String iface) throws IllegalStateException {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
+        try {
+            String cmd = "resolver setdefaultif " + iface;
+
+            mConnector.doCommand(cmd);
+        } catch (NativeDaemonConnectorException e) {
+            throw new IllegalStateException(
+                    "Error communicating with native daemon to set default interface", e);
+        }
+    }
+
+    public void setDnsServersForInterface(String iface, String[] servers)
+            throws IllegalStateException {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_NETWORK_STATE,
+                "NetworkManagementService");
+        try {
+            String cmd = "resolver setifdns " + iface;
+            for (String s : servers) {
+                if (s != null && !"0.0.0.0".equals(s) &&
+                        !"::".equals(s) && !"0:0:0:0:0:0:0:0".equals(s)) {
+                    cmd += " " + InetAddress.getByName(s).getHostAddress();
+                }
+            }
+
+            mConnector.doCommand(cmd);
+        } catch (UnknownHostException e) {
+            throw new IllegalStateException("failed to resolve dns address.", e);
+        } catch (NativeDaemonConnectorException e) {
+            throw new IllegalStateException(
+                    "Error communicating with native deamon to set dns for interface", e);
+        }
+    }
+
+    public void flushDefaultDnsCache() throws IllegalStateException {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
+        try {
+            String cmd = "resolver flushdefaultif";
+
+            mConnector.doCommand(cmd);
+        } catch (NativeDaemonConnectorException e) {
+            throw new IllegalStateException(
+                    "Error communicating with native deamon to flush default interface", e);
+        }
+    }
+
+    public void flushInterfaceDnsCache(String iface) throws IllegalStateException {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
+        try {
+            String cmd = "resolver flushif " + iface;
+
+            mConnector.doCommand(cmd);
+        } catch (NativeDaemonConnectorException e) {
+            throw new IllegalStateException(
+                    "Error communicating with native deamon to flush interface " + iface, e);
+        }
+    }
 }
diff --git a/services/java/com/android/server/NetworkTimeUpdateService.java b/services/java/com/android/server/NetworkTimeUpdateService.java
index 15f22c0..f7fe39e 100644
--- a/services/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/java/com/android/server/NetworkTimeUpdateService.java
@@ -16,8 +16,6 @@
 
 package com.android.server;
 
-import com.android.internal.telephony.TelephonyIntents;
-
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
@@ -28,7 +26,6 @@
 import android.database.ContentObserver;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
-import android.net.SntpClient;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -36,12 +33,10 @@
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.util.Log;
-import android.util.Slog;
+import android.util.NtpTrustedTime;
+import android.util.TrustedTime;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Properties;
+import com.android.internal.telephony.TelephonyIntents;
 
 /**
  * Monitors the network time and updates the system time if it is out of sync
@@ -68,14 +63,11 @@
     private static final long POLLING_INTERVAL_SHORTER_MS = 60 * 1000L; // 60 seconds
     /** Number of times to try again */
     private static final int TRY_AGAIN_TIMES_MAX = 3;
-    /** How long to wait for the NTP server to respond. */
-    private static final int MAX_NTP_FETCH_WAIT_MS = 20 * 1000;
     /** If the time difference is greater than this threshold, then update the time. */
     private static final int TIME_ERROR_THRESHOLD_MS = 5 * 1000;
 
     private static final String ACTION_POLL =
             "com.android.server.NetworkTimeUpdateService.action.POLL";
-    private static final String PROPERTIES_FILE = "/etc/gps.conf";
     private static int POLL_REQUEST = 0;
 
     private static final long NOT_SET = -1;
@@ -84,14 +76,14 @@
     private long mNitzZoneSetTime = NOT_SET;
 
     private Context mContext;
+    private TrustedTime mTime;
+
     // NTP lookup is done on this thread and handler
     private Handler mHandler;
     private HandlerThread mThread;
     private AlarmManager mAlarmManager;
     private PendingIntent mPendingPollIntent;
     private SettingsObserver mSettingsObserver;
-    // Address of the NTP server
-    private String mNtpServer;
     // The last time that we successfully fetched the NTP time.
     private long mLastNtpFetchTime = NOT_SET;
     // Keeps track of how many quick attempts were made to fetch NTP time.
@@ -101,6 +93,7 @@
 
     public NetworkTimeUpdateService(Context context) {
         mContext = context;
+        mTime = NtpTrustedTime.getInstance(context);
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
         Intent pollIntent = new Intent(ACTION_POLL, null);
         mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
@@ -108,12 +101,6 @@
 
     /** Initialize the receivers and initiate the first NTP request */
     public void systemReady() {
-        mNtpServer = getNtpServerAddress();
-        if (mNtpServer == null) {
-            Slog.e(TAG, "NTP server address not found, not syncing to NTP time");
-            return;
-        }
-
         registerForTelephonyIntents();
         registerForAlarms();
         registerForConnectivityIntents();
@@ -128,27 +115,6 @@
         mSettingsObserver.observe(mContext);
     }
 
-    private String getNtpServerAddress() {
-        String serverAddress = null;
-        FileInputStream stream = null;
-        try {
-            Properties properties = new Properties();
-            File file = new File(PROPERTIES_FILE);
-            stream = new FileInputStream(file);
-            properties.load(stream);
-            serverAddress = properties.getProperty("NTP_SERVER", null);
-        } catch (IOException e) {
-            Slog.e(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
-        } finally {
-            if (stream != null) {
-                try {
-                    stream.close();
-                } catch (Exception e) {}
-            }
-        }
-        return serverAddress;
-    }
-
     private void registerForTelephonyIntents() {
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIME);
@@ -189,9 +155,15 @@
         if (mLastNtpFetchTime == NOT_SET || refTime >= mLastNtpFetchTime + POLLING_INTERVAL_MS
                 || event == EVENT_AUTO_TIME_CHANGED) {
             if (DBG) Log.d(TAG, "Before Ntp fetch");
-            long ntp = getNtpTime();
-            if (DBG) Log.d(TAG, "Ntp = " + ntp);
-            if (ntp > 0) {
+
+            // force refresh NTP cache when outdated
+            if (mTime.getCacheAge() >= POLLING_INTERVAL_MS) {
+                mTime.forceRefresh();
+            }
+
+            // only update when NTP time is fresh
+            if (mTime.getCacheAge() < POLLING_INTERVAL_MS) {
+                final long ntp = mTime.currentTimeMillis();
                 mTryAgainCounter = 0;
                 mLastNtpFetchTime = SystemClock.elapsedRealtime();
                 if (Math.abs(ntp - currentTime) > TIME_ERROR_THRESHOLD_MS) {
@@ -232,15 +204,6 @@
         mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent);
     }
 
-    private long getNtpTime() {
-        SntpClient client = new SntpClient();
-        if (client.requestTime(mNtpServer, MAX_NTP_FETCH_WAIT_MS)) {
-            return client.getNtpTime();
-        } else {
-            return 0;
-        }
-    }
-
     /**
      * Checks if the user prefers to automatically set the time.
      */
diff --git a/services/java/com/android/server/SystemBackupAgent.java b/services/java/com/android/server/SystemBackupAgent.java
index 08c6699..950f3b6 100644
--- a/services/java/com/android/server/SystemBackupAgent.java
+++ b/services/java/com/android/server/SystemBackupAgent.java
@@ -138,7 +138,7 @@
             if (outFile == null) {
                 Slog.w(TAG, "Skipping unrecognized system file: [ " + domain + " : " + path + " ]");
             }
-            FullBackup.restoreToFile(data, size, type, mode, mtime, outFile, true);
+            FullBackup.restoreFile(data, size, type, mode, mtime, outFile);
 
             if (restoredWallpaper) {
                 WallpaperManagerService wallpaper =
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index a23bacf..8c7e279 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -209,9 +209,11 @@
                                           bluetoothA2dp);
                 bluetooth.initAfterA2dpRegistration();
 
+                int airplaneModeOn = Settings.System.getInt(mContentResolver,
+                        Settings.System.AIRPLANE_MODE_ON, 0);
                 int bluetoothOn = Settings.Secure.getInt(mContentResolver,
                     Settings.Secure.BLUETOOTH_ON, 0);
-                if (bluetoothOn > 0) {
+                if (airplaneModeOn == 0 && bluetoothOn != 0) {
                     bluetooth.enable();
                 }
             }
@@ -281,7 +283,8 @@
             try {
                 Slog.i(TAG, "NetworkPolicy Service");
                 networkPolicy = new NetworkPolicyManagerService(
-                        context, ActivityManagerService.self(), power, networkStats);
+                        context, ActivityManagerService.self(), power,
+                        networkStats, networkManagement);
                 ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
             } catch (Throwable e) {
                 Slog.e(TAG, "Failure starting NetworkPolicy Service", e);
@@ -520,6 +523,7 @@
         // These are needed to propagate to the runnable below.
         final Context contextF = context;
         final BatteryService batteryF = battery;
+        final NetworkManagementService networkManagementF = networkManagement;
         final NetworkStatsService networkStatsF = networkStats;
         final NetworkPolicyManagerService networkPolicyF = networkPolicy;
         final ConnectivityService connectivityF = connectivity;
@@ -547,6 +551,7 @@
 
                 startSystemUi(contextF);
                 if (batteryF != null) batteryF.systemReady();
+                if (networkManagementF != null) networkManagementF.systemReady();
                 if (networkStatsF != null) networkStatsF.systemReady();
                 if (networkPolicyF != null) networkPolicyF.systemReady();
                 if (connectivityF != null) connectivityF.systemReady();
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index 7266d7d..24d4dd3 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -16,9 +16,6 @@
 
 package com.android.server;
 
-import com.android.internal.R;
-import com.android.internal.telephony.TelephonyProperties;
-
 import android.app.AlarmManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -54,6 +51,9 @@
 import android.util.Slog;
 import android.util.TrustedTime;
 
+import com.android.internal.R;
+import com.android.internal.telephony.TelephonyProperties;
+
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileDescriptor;
@@ -63,7 +63,6 @@
 import java.io.PrintWriter;
 import java.util.Calendar;
 import java.util.GregorianCalendar;
-import java.util.Properties;
 import java.util.Random;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
@@ -87,7 +86,6 @@
     private static final long TESTING_THRESHOLD = 1 * 1024 * 1024;
 
     private static final long MAX_NTP_CACHE_AGE = 24 * 60 * 60 * 1000;
-    private static final long MAX_NTP_FETCH_WAIT = 20 * 1000;
 
     private long mMaxNtpCacheAge = MAX_NTP_CACHE_AGE;
 
@@ -127,8 +125,6 @@
     private static final int THROTTLE_INDEX_UNINITIALIZED = -1;
     private static final int THROTTLE_INDEX_UNTHROTTLED   =  0;
 
-    private static final String PROPERTIES_FILE = "/etc/gps.conf";
-
     private Intent mPollStickyBroadcast;
 
     private TrustedTime mTime;
@@ -139,8 +135,7 @@
     }
 
     public ThrottleService(Context context) {
-        // TODO: move to using cached NtpTrustedTime
-        this(context, getNetworkManagementService(), new NtpTrustedTime(),
+        this(context, getNetworkManagementService(), NtpTrustedTime.getInstance(context),
                 context.getResources().getString(R.string.config_datause_iface));
     }
 
@@ -179,14 +174,17 @@
             mIface = iface;
         }
 
-        public void interfaceLinkStatusChanged(String iface, boolean link) {
-            if (link) {
+        public void interfaceStatusChanged(String iface, boolean up) {
+            if (up) {
                 if (TextUtils.equals(iface, mIface)) {
                     mHandler.obtainMessage(mMsg).sendToTarget();
                 }
             }
         }
 
+        public void interfaceLinkStateChanged(String iface, boolean up) {
+        }
+
         public void interfaceAdded(String iface) {
             // TODO - an interface added in the UP state should also trigger a StatusChanged
             // notification..
@@ -338,26 +336,6 @@
                 }
             }, new IntentFilter(ACTION_RESET));
 
-        FileInputStream stream = null;
-        try {
-            Properties properties = new Properties();
-            File file = new File(PROPERTIES_FILE);
-            stream = new FileInputStream(file);
-            properties.load(stream);
-            final String ntpServer = properties.getProperty("NTP_SERVER", null);
-            if (mTime instanceof NtpTrustedTime) {
-                ((NtpTrustedTime) mTime).setNtpServer(ntpServer, MAX_NTP_FETCH_WAIT);
-            }
-        } catch (IOException e) {
-            Slog.e(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
-        } finally {
-            if (stream != null) {
-                try {
-                    stream.close();
-                } catch (Exception e) {}
-            }
-        }
-
         // use a new thread as we don't want to stall the system for file writes
         mThread = new HandlerThread(TAG);
         mThread.start();
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index cb55451..5f0922e 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -36,6 +36,7 @@
 import android.net.wifi.WifiStateMachine;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiWatchdogService;
 import android.net.wifi.WpsConfiguration;
 import android.net.wifi.WpsResult;
 import android.net.ConnectivityManager;
@@ -342,6 +343,7 @@
      * Protected by mWifiStateTracker lock.
      */
     private final WorkSource mTmpWorkSource = new WorkSource();
+    private WifiWatchdogService mWifiWatchdogService;
 
     WifiService(Context context) {
         mContext = context;
@@ -431,6 +433,9 @@
         Slog.i(TAG, "WifiService starting up with Wi-Fi " +
                 (wifiEnabled ? "enabled" : "disabled"));
         setWifiEnabled(wifiEnabled);
+
+        //TODO: as part of WWS refactor, create only when needed
+        mWifiWatchdogService = new WifiWatchdogService(mContext);
     }
 
     private boolean testAndClearWifiSavedState() {
@@ -1155,6 +1160,10 @@
         pw.println();
         pw.println("Locks held:");
         mLocks.dump(pw);
+
+        pw.println();
+        pw.println("WifiWatchdogService dump");
+        mWifiWatchdogService.dump(pw);
     }
 
     private class WifiLock extends DeathRecipient {
diff --git a/services/java/com/android/server/WifiWatchdogService.java b/services/java/com/android/server/WifiWatchdogService.java
deleted file mode 100644
index 56bfbe0..0000000
--- a/services/java/com/android/server/WifiWatchdogService.java
+++ /dev/null
@@ -1,1450 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.database.ContentObserver;
-import android.net.ConnectivityManager;
-import android.net.LinkProperties;
-import android.net.NetworkInfo;
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiInfo;
-import android.net.wifi.WifiManager;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Slog;
-
-import java.io.BufferedInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.HttpURLConnection;
-import java.net.InetAddress;
-import java.net.SocketException;
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-import java.net.URL;
-import java.util.Collection;
-import java.util.List;
-import java.util.Random;
-import java.util.Scanner;
-
-/**
- * {@link WifiWatchdogService} monitors the initial connection to a Wi-Fi
- * network with multiple access points. After the framework successfully
- * connects to an access point, the watchdog verifies whether the DNS server is
- * reachable. If not, the watchdog blacklists the current access point, leading
- * to a connection on another access point within the same network.
- * <p>
- * The watchdog has a few safeguards:
- * <ul>
- * <li>Only monitor networks with multiple access points
- * <li>Only check at most {@link #getMaxApChecks()} different access points
- * within the network before giving up
- * <p>
- * The watchdog checks for connectivity on an access point by ICMP pinging the
- * DNS. There are settings that allow disabling the watchdog, or tweaking the
- * acceptable packet loss (and other various parameters).
- * <p>
- * The core logic of the watchdog is done on the main watchdog thread. Wi-Fi
- * callbacks can come in on other threads, so we must queue messages to the main
- * watchdog thread's handler. Most (if not all) state is only written to from
- * the main thread.
- * 
- * {@hide}
- */
-public class WifiWatchdogService {
-    private static final String TAG = "WifiWatchdogService";
-    private static final boolean V = false;
-    private static final boolean D = true;
-
-    private Context mContext;
-    private ContentResolver mContentResolver;
-    private WifiManager mWifiManager;
-    private ConnectivityManager mConnectivityManager;
-
-    /**
-     * The main watchdog thread.
-     */
-    private WifiWatchdogThread mThread;
-    /**
-     * The handler for the main watchdog thread.
-     */
-    private WifiWatchdogHandler mHandler;
-
-    private ContentObserver mContentObserver;
-
-    /**
-     * The current watchdog state. Only written from the main thread!
-     */
-    private WatchdogState mState = WatchdogState.IDLE;
-    /**
-     * The SSID of the network that the watchdog is currently monitoring. Only
-     * touched in the main thread!
-     */
-    private String mSsid;
-    /**
-     * The number of access points in the current network ({@link #mSsid}) that
-     * have been checked. Only touched in the main thread, using getter/setter methods.
-     */
-    private int mBssidCheckCount;
-    /** Whether the current AP check should be canceled. */
-    private boolean mShouldCancel;
-
-    WifiWatchdogService(Context context) {
-        mContext = context;
-        mContentResolver = context.getContentResolver();
-        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
-        createThread();
-        
-        // The content observer to listen needs a handler, which createThread creates
-        registerForSettingsChanges();
-        if (isWatchdogEnabled()) {
-            registerForWifiBroadcasts();
-        }
-        
-        if (V) {
-            myLogV("WifiWatchdogService: Created");
-        }
-    }
-
-    /**
-     * Observes the watchdog on/off setting, and takes action when changed.
-     */
-    private void registerForSettingsChanges() {
-        ContentResolver contentResolver = mContext.getContentResolver();
-        contentResolver.registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON), false,
-                mContentObserver = new ContentObserver(mHandler) {
-            @Override
-            public void onChange(boolean selfChange) {
-                if (isWatchdogEnabled()) {
-                    registerForWifiBroadcasts();
-                } else {
-                    unregisterForWifiBroadcasts();
-                    if (mHandler != null) {
-                        mHandler.disableWatchdog();
-                    }
-                }
-            }
-        });
-    }
-
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_ON
-     */
-    private boolean isWatchdogEnabled() {
-        return Settings.Secure.getInt(mContentResolver, Settings.Secure.WIFI_WATCHDOG_ON, 1) == 1;
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_AP_COUNT
-     */
-    private int getApCount() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_AP_COUNT, 2);
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT
-     */
-    private int getInitialIgnoredPingCount() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT , 2);
-    }
-
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_PING_COUNT
-     */
-    private int getPingCount() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_PING_COUNT, 4);
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_PING_TIMEOUT_MS
-     */
-    private int getPingTimeoutMs() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS, 500);
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_PING_DELAY_MS
-     */
-    private int getPingDelayMs() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_PING_DELAY_MS, 250);
-    }
-
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED
-     */
-     private Boolean isWalledGardenTestEnabled() {
-        return Settings.Secure.getInt(mContentResolver,
-                 Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, 1) == 1;
-     }
-
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_URL
-     */
-     private String getWalledGardenUrl() {
-        String url = Settings.Secure.getString(mContentResolver,
-                 Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL);
-        if (TextUtils.isEmpty(url)) return "http://www.google.com/";
-        return url;
-     }
-
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_PATTERN
-     */
-     private String getWalledGardenPattern() {
-        String pattern = Settings.Secure.getString(mContentResolver,
-                 Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN);
-        if (TextUtils.isEmpty(pattern)) return "<title>.*Google.*</title>";
-        return pattern;
-     }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE
-     */
-    private int getAcceptablePacketLossPercentage() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE, 25);
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_MAX_AP_CHECKS
-     */
-    private int getMaxApChecks() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_MAX_AP_CHECKS, 7);
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED
-     */
-    private boolean isBackgroundCheckEnabled() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED, 1) == 1;
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS
-     */
-    private int getBackgroundCheckDelayMs() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS, 60000);
-    }
-    
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS
-     */
-    private int getBackgroundCheckTimeoutMs() {
-        return Settings.Secure.getInt(mContentResolver,
-            Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS, 1000);
-    }
-
-    /**
-     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WATCH_LIST
-     * @return the comma-separated list of SSIDs
-     */
-    private String getWatchList() {
-        return Settings.Secure.getString(mContentResolver,
-                Settings.Secure.WIFI_WATCHDOG_WATCH_LIST);
-    }
-    
-    /**
-     * Registers to receive the necessary Wi-Fi broadcasts.
-     */
-    private void registerForWifiBroadcasts() {
-        IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
-        intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
-        mContext.registerReceiver(mReceiver, intentFilter);
-    }
-
-    /**
-     * Unregisters from receiving the Wi-Fi broadcasts.
-     */
-    private void unregisterForWifiBroadcasts() {
-        mContext.unregisterReceiver(mReceiver);
-    }
-
-    /**
-     * Creates the main watchdog thread, including waiting for the handler to be
-     * created.
-     */
-    private void createThread() {
-        mThread = new WifiWatchdogThread();
-        mThread.start();
-        waitForHandlerCreation();
-    }
-
-    /**
-     * Unregister broadcasts and quit the watchdog thread
-     */
-    //TODO: Change back to running WWS when needed
-//    private void quit() {
-//        unregisterForWifiBroadcasts();
-//        mContext.getContentResolver().unregisterContentObserver(mContentObserver);
-//        mHandler.removeAllActions();
-//        mHandler.getLooper().quit();
-//    }
-
-    /**
-     * Waits for the main watchdog thread to create the handler.
-     */
-    private void waitForHandlerCreation() {
-        synchronized(this) {
-            while (mHandler == null) {
-                try {
-                    // Wait for the handler to be set by the other thread
-                    wait();
-                } catch (InterruptedException e) {
-                    Slog.e(TAG, "Interrupted while waiting on handler.");
-                }
-            }
-        }
-    }
-
-    // Utility methods
-    
-    /**
-     * Logs with the current thread.
-     */
-    private static void myLogV(String message) {
-        Slog.v(TAG, "(" + Thread.currentThread().getName() + ") " + message);
-    }
-    
-    private static void myLogD(String message) {
-        Slog.d(TAG, "(" + Thread.currentThread().getName() + ") " + message);
-    }
-    
-    /**
-     * Gets the first DNS of the current AP.
-     * 
-     * @return The first DNS of the current AP.
-     */
-    private InetAddress getDns() {
-        if (mConnectivityManager == null) {
-            mConnectivityManager = (ConnectivityManager)mContext.getSystemService(
-                    Context.CONNECTIVITY_SERVICE);
-        }
-
-        LinkProperties linkProperties = mConnectivityManager.getLinkProperties(
-                ConnectivityManager.TYPE_WIFI);
-        if (linkProperties == null) return null;
-
-        Collection<InetAddress> dnses = linkProperties.getDnses();
-        if (dnses == null || dnses.size() == 0) return null;
-
-        return dnses.iterator().next();
-    }
-
-    /**
-     * Checks whether the DNS can be reached using multiple attempts according
-     * to the current setting values.
-     * 
-     * @return Whether the DNS is reachable
-     */
-    private boolean checkDnsConnectivity() {
-        InetAddress dns = getDns();
-        if (dns == null) {
-            if (V) {
-                myLogV("checkDnsConnectivity: Invalid DNS, returning false");
-            }
-            return false;
-        }
-
-        if (V) {
-            myLogV("checkDnsConnectivity: Checking " + dns.getHostAddress() + " for connectivity");
-        }
-
-        int numInitialIgnoredPings = getInitialIgnoredPingCount();
-        int numPings = getPingCount();
-        int pingDelay = getPingDelayMs();
-        int acceptableLoss = getAcceptablePacketLossPercentage();
-
-        /** See {@link Secure#WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT} */
-        int ignoredPingCounter = 0;
-        int pingCounter = 0;
-        int successCounter = 0;
-
-        // No connectivity check needed
-        if (numPings == 0) {
-            return true;
-        }
-
-        // Do the initial pings that we ignore
-        for (; ignoredPingCounter < numInitialIgnoredPings; ignoredPingCounter++) {
-            if (shouldCancel()) return false;
-
-            boolean dnsAlive = DnsPinger.isDnsReachable(dns, getPingTimeoutMs());
-            if (dnsAlive) {
-                /*
-                 * Successful "ignored" pings are *not* ignored (they count in the total number
-                 * of pings), but failures are really ignored.
-                 */
-
-                // TODO: This is confusing logic and should be rewitten
-                // Here, successful 'ignored' pings are interpreted as a success in the below loop
-                pingCounter++;
-                successCounter++;
-            }
-
-            if (V) {
-                Slog.v(TAG, (dnsAlive ? "  +" : "  Ignored: -"));
-            }
-
-            if (shouldCancel()) return false;
-
-            try {
-                Thread.sleep(pingDelay);
-            } catch (InterruptedException e) {
-                Slog.w(TAG, "Interrupted while pausing between pings", e);
-            }
-        }
-
-        // Do the pings that we use to measure packet loss
-        for (; pingCounter < numPings; pingCounter++) {
-            if (shouldCancel()) return false;
-
-            if (DnsPinger.isDnsReachable(dns, getPingTimeoutMs())) {
-                successCounter++;
-                if (V) {
-                    Slog.v(TAG, "  +");
-                }
-            } else {
-                if (V) {
-                    Slog.v(TAG, "  -");
-                }
-            }
-
-            if (shouldCancel()) return false;
-
-            try {
-                Thread.sleep(pingDelay);
-            } catch (InterruptedException e) {
-                Slog.w(TAG, "Interrupted while pausing between pings", e);
-            }
-        }
-
-        //TODO: Integer division might cause problems down the road...
-        int packetLossPercentage = 100 * (numPings - successCounter) / numPings;
-        if (D) {
-            Slog.d(TAG, packetLossPercentage
-                    + "% packet loss (acceptable is " + acceptableLoss + "%)");
-        }
-
-        return !shouldCancel() && (packetLossPercentage <= acceptableLoss);
-    }
-
-    private boolean backgroundCheckDnsConnectivity() {
-        InetAddress dns = getDns();
-
-        if (dns == null) {
-            if (V) {
-                myLogV("backgroundCheckDnsConnectivity: DNS is empty, returning false");
-            }
-            return false;
-        }
-
-        if (V) {
-            myLogV("backgroundCheckDnsConnectivity: Background checking " +
-                    dns.getHostAddress() + " for connectivity");
-        }
-
-        return DnsPinger.isDnsReachable(dns, getBackgroundCheckTimeoutMs());
-    }
-
-    /**
-     * Signals the current action to cancel.
-     */
-    private void cancelCurrentAction() {
-        mShouldCancel = true;
-    }
-    
-    /**
-     * Helper to check whether to cancel. 
-     * 
-     * @return Whether to cancel processing the action.
-     */
-    private boolean shouldCancel() {
-        if (V && mShouldCancel) {
-            myLogV("shouldCancel: Cancelling");
-        }
-        
-        return mShouldCancel;
-    }
-    
-    // Wi-Fi initiated callbacks (could be executed in another thread)
-
-    /**
-     * Called when connected to an AP (this can be the next AP in line, or
-     * it can be a completely different network).
-     * 
-     * @param ssid The SSID of the access point.
-     * @param bssid The BSSID of the access point.
-     */
-    private void onConnected(String ssid, String bssid) {
-        if (V) {
-            myLogV("onConnected: SSID: " + ssid + ", BSSID: " + bssid);
-        }
-
-        /*
-         * The current action being processed by the main watchdog thread is now
-         * stale, so cancel it.
-         */
-        cancelCurrentAction();
-        
-        if ((mSsid == null) || !mSsid.equals(ssid)) {
-            /*
-             * This is a different network than what the main watchdog thread is
-             * processing, dispatch the network change message on the main thread.
-             */
-            mHandler.dispatchNetworkChanged(ssid);
-        }
-        
-        if (requiresWatchdog(ssid, bssid)) {
-            if (D) {
-                myLogD(ssid + " (" + bssid + ") requires the watchdog");
-            }
-
-            // This access point requires a watchdog, so queue the check on the main thread
-            mHandler.checkAp(new AccessPoint(ssid, bssid));
-            
-        } else {
-            if (D) {
-                myLogD(ssid + " (" + bssid + ") does not require the watchdog");
-            }
-
-            // This access point does not require a watchdog, so queue idle on the main thread
-            mHandler.idle();
-        }
-        if (isWalledGardenTestEnabled()) mHandler.checkWalledGarden(ssid);
-    }
-    
-    /**
-     * Called when Wi-Fi is enabled.
-     */
-    private void onEnabled() {
-        cancelCurrentAction();
-        // Queue a hard-reset of the state on the main thread
-        mHandler.reset();
-    }
-    
-    /**
-     * Called when disconnected (or some other event similar to being disconnected).
-     */
-    private void onDisconnected() {
-        if (V) {
-            myLogV("onDisconnected");
-        }
-        
-        /*
-         * Disconnected from an access point, the action being processed by the
-         * watchdog thread is now stale, so cancel it.
-         */
-        cancelCurrentAction();
-        // Dispatch the disconnected to the main watchdog thread
-        mHandler.dispatchDisconnected();
-        // Queue the action to go idle
-        mHandler.idle();
-    }
-
-    /**
-     * Checks whether an access point requires watchdog monitoring.
-     * 
-     * @param ssid The SSID of the access point.
-     * @param bssid The BSSID of the access point.
-     * @return Whether the access point/network should be monitored by the
-     *         watchdog.
-     */
-    private boolean requiresWatchdog(String ssid, String bssid) {
-        if (V) {
-            myLogV("requiresWatchdog: SSID: " + ssid + ", BSSID: " + bssid);
-        }
-        
-        WifiInfo info = null;
-        if (ssid == null) {
-            /*
-             * This is called from a Wi-Fi callback, so assume the WifiInfo does
-             * not have stale data.
-             */
-            info = mWifiManager.getConnectionInfo();
-            ssid = info.getSSID();
-            if (ssid == null) {
-                // It's still null, give up
-                if (V) {
-                    Slog.v(TAG, "  Invalid SSID, returning false");
-                }
-                return false;
-            }
-        }
-        
-        if (TextUtils.isEmpty(bssid)) {
-            // Similar as above
-            if (info == null) {
-                info = mWifiManager.getConnectionInfo();
-            }
-            bssid = info.getBSSID();
-            if (TextUtils.isEmpty(bssid)) {
-                // It's still null, give up
-                if (V) {
-                    Slog.v(TAG, "  Invalid BSSID, returning false");
-                }
-                return false;
-            }
-        }
-
-        if (!isOnWatchList(ssid)) {
-            if (V) {
-                Slog.v(TAG, "  SSID not on watch list, returning false");
-            }
-            return false;
-        }
-
-        // The watchdog only monitors networks with multiple APs
-        if (!hasRequiredNumberOfAps(ssid)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    private boolean isOnWatchList(String ssid) {
-        String watchList;
-
-        if (ssid == null || (watchList = getWatchList()) == null) {
-            return false;
-        }
-
-        String[] list = watchList.split(" *, *");
-
-        for (String name : list) {
-            if (ssid.equals(name)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-    
-    /**
-     * Checks if the current scan results have multiple access points with an SSID.
-     * 
-     * @param ssid The SSID to check.
-     * @return Whether the SSID has multiple access points.
-     */
-    private boolean hasRequiredNumberOfAps(String ssid) {
-        List<ScanResult> results = mWifiManager.getScanResults();
-        if (results == null) {
-            if (V) {
-                myLogV("hasRequiredNumberOfAps: Got null scan results, returning false");
-            }
-            return false;
-        }
-        
-        int numApsRequired = getApCount();
-        int numApsFound = 0;
-        int resultsSize = results.size();
-        for (int i = 0; i < resultsSize; i++) {
-            ScanResult result = results.get(i);
-            if (result == null) continue;
-            if (result.SSID == null) continue;
-            
-            if (result.SSID.equals(ssid)) {
-                numApsFound++;
-                
-                if (numApsFound >= numApsRequired) {
-                    if (V) {
-                        myLogV("hasRequiredNumberOfAps: SSID: " + ssid + ", returning true");
-                    }
-                    return true;
-                }
-            }
-        }
-        
-        if (V) {
-            myLogV("hasRequiredNumberOfAps: SSID: " + ssid + ", returning false");
-        }
-        return false;
-    }
-    
-    // Watchdog logic (assume all of these methods will be in our main thread)
-    
-    /**
-     * Handles a Wi-Fi network change (for example, from networkA to networkB).
-     */
-    private void handleNetworkChanged(String ssid) {
-        // Set the SSID being monitored to the new SSID 
-        mSsid = ssid;
-        // Set various state to that when being idle 
-        setIdleState(true);
-    }
-    
-    /**
-     * Handles checking whether an AP is a "good" AP.  If not, it will be blacklisted.
-     * 
-     * @param ap The access point to check.
-     */
-    private void handleCheckAp(AccessPoint ap) {
-        // Reset the cancel state since this is the entry point of this action
-        mShouldCancel = false;
-        
-        if (V) {
-            myLogV("handleCheckAp: AccessPoint: " + ap);
-        }
-        
-        // Make sure we are not sleeping
-        if (mState == WatchdogState.SLEEP) {
-            if (V) {
-                Slog.v(TAG, "  Sleeping (in " + mSsid + "), so returning");
-            }
-            return;
-        }
-        
-        mState = WatchdogState.CHECKING_AP;
-        
-        /*
-         * Checks to make sure we haven't exceeded the max number of checks
-         * we're allowed per network
-         */
-        incrementBssidCheckCount();
-        if (getBssidCheckCount() > getMaxApChecks()) {
-            if (V) {
-                Slog.v(TAG, "  Passed the max attempts (" + getMaxApChecks()
-                        + "), going to sleep for " + mSsid);
-            }
-            mHandler.sleep(mSsid);
-            return;
-        }
-
-        // Do the check
-        boolean isApAlive = checkDnsConnectivity();
-        
-        if (V) {
-            Slog.v(TAG, "  Is it alive: " + isApAlive);
-        }
-
-        // Take action based on results
-        if (isApAlive) {
-            handleApAlive(ap);
-        } else {
-            handleApUnresponsive(ap);
-        }
-    }
-
-    /**
-     * Handles the case when an access point is alive.
-     * 
-     * @param ap The access point.
-     */
-    private void handleApAlive(AccessPoint ap) {
-        // Check whether we are stale and should cancel
-        if (shouldCancel()) return;
-        // We're satisfied with this AP, so go idle
-        setIdleState(false);
-        
-        if (D) {
-            myLogD("AP is alive: " + ap.toString());
-        }
-        
-        // Queue the next action to be a background check
-        mHandler.backgroundCheckAp(ap);
-    }
-    
-    /**
-     * Handles an unresponsive AP by blacklisting it.
-     * 
-     * @param ap The access point.
-     */
-    private void handleApUnresponsive(AccessPoint ap) {
-        // Check whether we are stale and should cancel
-        if (shouldCancel()) return;
-        // This AP is "bad", switch to another
-        mState = WatchdogState.SWITCHING_AP;
-
-        if (D) {
-            myLogD("AP is dead: " + ap.toString());
-        }
-        
-        // Black list this "bad" AP, this will cause an attempt to connect to another
-        blacklistAp(ap.bssid);
-        // Initiate an association to an alternate AP
-        mWifiManager.reassociate();
-    }
-
-    private void blacklistAp(String bssid) {
-        if (TextUtils.isEmpty(bssid)) {
-            return;
-        }
-        
-        // Before taking action, make sure we should not cancel our processing
-        if (shouldCancel()) return;
-        
-        mWifiManager.addToBlacklist(bssid);
-
-        if (D) {
-            myLogD("Blacklisting " + bssid);
-        }
-    }
-
-    /**
-     * Handles a single background check. If it fails, it should trigger a
-     * normal check. If it succeeds, it should queue another background check.
-     * 
-     * @param ap The access point to do a background check for. If this is no
-     *        longer the current AP, it is okay to return without any
-     *        processing.
-     */
-    private void handleBackgroundCheckAp(AccessPoint ap) {
-        // Reset the cancel state since this is the entry point of this action
-        mShouldCancel = false;
-        
-        if (V) {
-            myLogV("handleBackgroundCheckAp: AccessPoint: " + ap);
-        }
-        
-        // Make sure we are not sleeping
-        if (mState == WatchdogState.SLEEP) {
-            if (V) {
-                Slog.v(TAG, "  handleBackgroundCheckAp: Sleeping (in " + mSsid + "), so returning");
-            }
-            return;
-        }
-        
-        // Make sure the AP we're supposed to be background checking is still the active one
-        WifiInfo info = mWifiManager.getConnectionInfo();
-        if (info.getSSID() == null || !info.getSSID().equals(ap.ssid)) {
-            if (V) {
-                myLogV("handleBackgroundCheckAp: We are no longer connected to "
-                        + ap + ", and instead are on " + info);
-            }
-            return;
-        }
-        
-        if (info.getBSSID() == null || !info.getBSSID().equals(ap.bssid)) {
-            if (V) {
-                myLogV("handleBackgroundCheckAp: We are no longer connected to "
-                        + ap + ", and instead are on " + info);
-            }
-            return;
-        }
-
-        // Do the check
-        boolean isApAlive = backgroundCheckDnsConnectivity();
-        
-        if (V && !isApAlive) {
-            Slog.v(TAG, "  handleBackgroundCheckAp: Is it alive: " + isApAlive);
-        }
-
-        if (shouldCancel()) {
-            return;
-        }
-        
-        // Take action based on results
-        if (isApAlive) {
-            // Queue another background check
-            mHandler.backgroundCheckAp(ap);
-            
-        } else {
-            if (D) {
-                myLogD("Background check failed for " + ap.toString());
-            }
-            
-            // Queue a normal check, so it can take proper action
-            mHandler.checkAp(ap);
-        }
-    }
-    
-    /**
-     * Handles going to sleep for this network. Going to sleep means we will not
-     * monitor this network anymore.
-     * 
-     * @param ssid The network that will not be monitored anymore.
-     */
-    private void handleSleep(String ssid) {
-        // Make sure the network we're trying to sleep in is still the current network
-        if (ssid != null && ssid.equals(mSsid)) {
-            mState = WatchdogState.SLEEP;
-
-            if (D) {
-                myLogD("Going to sleep for " + ssid);
-            }
-            
-            /*
-             * Before deciding to go to sleep, we may have checked a few APs
-             * (and blacklisted them). Clear the blacklist so the AP with best
-             * signal is chosen.
-             */
-            mWifiManager.clearBlacklist();
-            
-            if (V) {
-                myLogV("handleSleep: Set state to SLEEP and cleared blacklist");
-            }
-        }
-    }
-
-    /**
-     * Handles an access point disconnection.
-     */
-    private void handleDisconnected() {
-        /*
-         * We purposefully do not change mSsid to null. This is to handle
-         * disconnected followed by connected better (even if there is some
-         * duration in between). For example, if the watchdog went to sleep in a
-         * network, and then the phone goes to sleep, when the phone wakes up we
-         * still want to be in the sleeping state. When the phone went to sleep,
-         * we would have gotten a disconnected event which would then set mSsid
-         * = null. This is bad, since the following connect would cause us to do
-         * the "network is good?" check all over again. */
-        
-        /* 
-         * Set the state as if we were idle (don't come out of sleep, only
-         * hard reset and network changed should do that.
-         */
-        setIdleState(false);
-    }
-
-    /**
-     * Handles going idle. Idle means we are satisfied with the current state of
-     * things, but if a new connection occurs we'll re-evaluate.
-     */
-    private void handleIdle() {
-        // Reset the cancel state since this is the entry point for this action
-        mShouldCancel = false;
-        
-        if (V) {
-            myLogV("handleSwitchToIdle");
-        }
-        
-        // If we're sleeping, don't do anything
-        if (mState == WatchdogState.SLEEP) {
-            Slog.v(TAG, "  Sleeping (in " + mSsid + "), so returning");
-            return;
-        }
-        
-        // Set the idle state
-        setIdleState(false);
-        
-        if (V) {
-            Slog.v(TAG, "  Set state to IDLE");
-        }
-    }
-    
-    /**
-     * Sets the state as if we are going idle.
-     */
-    private void setIdleState(boolean forceIdleState) {
-        // Setting idle state does not kick us out of sleep unless the forceIdleState is set
-        if (forceIdleState || (mState != WatchdogState.SLEEP)) {
-            mState = WatchdogState.IDLE;
-        }
-        resetBssidCheckCount();
-    }
-
-    /**
-     * Handles a hard reset. A hard reset is rarely used, but when used it
-     * should revert anything done by the watchdog monitoring.
-     */
-    private void handleReset() {
-        mWifiManager.clearBlacklist();
-        setIdleState(true);
-    }
-    
-    // Inner classes
-
-    /**
-     * Possible states for the watchdog to be in.
-     */
-    private static enum WatchdogState {
-        /** The watchdog is currently idle, but it is still responsive to future AP checks in this network. */
-        IDLE,
-        /** The watchdog is sleeping, so it will not try any AP checks for the network. */
-        SLEEP,
-        /** The watchdog is currently checking an AP for connectivity. */
-        CHECKING_AP,
-        /** The watchdog is switching to another AP in the network. */
-        SWITCHING_AP
-    }
-
-    private int getBssidCheckCount() {
-        return mBssidCheckCount;
-    }
-
-    private void incrementBssidCheckCount() {
-        mBssidCheckCount++;
-    }
-
-    private void resetBssidCheckCount() {
-        this.mBssidCheckCount = 0;
-    }
-
-    /**
-     * The main thread for the watchdog monitoring. This will be turned into a
-     * {@link Looper} thread.
-     */
-    private class WifiWatchdogThread extends Thread {
-        WifiWatchdogThread() {
-            super("WifiWatchdogThread");
-        }
-        
-        @Override
-        public void run() {
-            // Set this thread up so the handler will work on it
-            Looper.prepare();
-            
-            synchronized(WifiWatchdogService.this) {
-                mHandler = new WifiWatchdogHandler();
-
-                // Notify that the handler has been created
-                WifiWatchdogService.this.notify();
-            }
-            
-            // Listen for messages to the handler
-            Looper.loop();
-        }
-    }
-
-    /**
-     * The main thread's handler. There are 'actions', and just general 
-     * 'messages'. There should only ever be one 'action' in the queue (aside
-     * from the one being processed, if any). There may be multiple messages in
-     * the queue. So, actions are replaced by more recent actions, where as
-     * messages will be executed for sure. Messages end up being used to just
-     * change some state, and not really take any action.
-     * <p>
-     * There is little logic inside this class, instead methods of the form
-     * "handle___" are called in the main {@link WifiWatchdogService}.
-     */
-    private class WifiWatchdogHandler extends Handler {
-        /** Check whether the AP is "good".  The object will be an {@link AccessPoint}. */
-        static final int ACTION_CHECK_AP = 1;
-        /** Go into the idle state. */
-        static final int ACTION_IDLE = 2;
-        /**
-         * Performs a periodic background check whether the AP is still "good".
-         * The object will be an {@link AccessPoint}.
-         */
-        static final int ACTION_BACKGROUND_CHECK_AP = 3;
-        /** Check whether the connection is a walled garden */
-        static final int ACTION_CHECK_WALLED_GARDEN = 4;
-
-        /**
-         * Go to sleep for the current network. We are conservative with making
-         * this a message rather than action. We want to make sure our main
-         * thread sees this message, but if it were an action it could be
-         * removed from the queue and replaced by another action. The main
-         * thread will ensure when it sees the message that the state is still
-         * valid for going to sleep.
-         * <p>
-         * For an explanation of sleep, see {@link android.provider.Settings.Secure#WIFI_WATCHDOG_MAX_AP_CHECKS}.
-         */
-        static final int MESSAGE_SLEEP = 101;
-        /** Disables the watchdog. */
-        static final int MESSAGE_DISABLE_WATCHDOG = 102;
-        /** The network has changed. */
-        static final int MESSAGE_NETWORK_CHANGED = 103;
-        /** The current access point has disconnected. */
-        static final int MESSAGE_DISCONNECTED = 104;
-        /** Performs a hard-reset on the watchdog state. */
-        static final int MESSAGE_RESET = 105;
-
-        /* Walled garden detection */
-        private String mLastSsid;
-        private long mLastTime;
-        private final long MIN_WALLED_GARDEN_TEST_INTERVAL = 15 * 60 * 1000; //15 minutes
-
-        void checkWalledGarden(String ssid) {
-            sendMessage(obtainMessage(ACTION_CHECK_WALLED_GARDEN, ssid));
-        }
-
-        void checkAp(AccessPoint ap) {
-            removeAllActions();
-            sendMessage(obtainMessage(ACTION_CHECK_AP, ap));
-        }
-        
-        void backgroundCheckAp(AccessPoint ap) {
-            if (!isBackgroundCheckEnabled()) return;
-            
-            removeAllActions();
-            sendMessageDelayed(obtainMessage(ACTION_BACKGROUND_CHECK_AP, ap),
-                    getBackgroundCheckDelayMs());
-        }
-        
-        void idle() {
-            removeAllActions();
-            sendMessage(obtainMessage(ACTION_IDLE));
-        }
-        
-        void sleep(String ssid) {
-            removeAllActions();
-            sendMessage(obtainMessage(MESSAGE_SLEEP, ssid));
-        }
-        
-        void disableWatchdog() {
-            removeAllActions();
-            sendMessage(obtainMessage(MESSAGE_DISABLE_WATCHDOG));
-        }
-        
-        void dispatchNetworkChanged(String ssid) {
-            removeAllActions();
-            sendMessage(obtainMessage(MESSAGE_NETWORK_CHANGED, ssid));
-        }
-
-        void dispatchDisconnected() {
-            removeAllActions();
-            sendMessage(obtainMessage(MESSAGE_DISCONNECTED));
-        }
-
-        void reset() {
-            removeAllActions();
-            sendMessage(obtainMessage(MESSAGE_RESET));
-        }
-        
-        private void removeAllActions() {
-            removeMessages(ACTION_CHECK_AP);
-            removeMessages(ACTION_IDLE);
-            removeMessages(ACTION_BACKGROUND_CHECK_AP);
-        }
-        
-        @Override
-        public void handleMessage(Message msg) {
-            if (V) {
-                myLogV("handleMessage: " + msg.what);
-            }
-            switch (msg.what) {
-                case MESSAGE_NETWORK_CHANGED:
-                    handleNetworkChanged((String) msg.obj);
-                    break;
-                case ACTION_CHECK_AP:
-                    handleCheckAp((AccessPoint) msg.obj);
-                    break;
-                case ACTION_BACKGROUND_CHECK_AP:
-                    handleBackgroundCheckAp((AccessPoint) msg.obj);
-                    break;
-                case ACTION_CHECK_WALLED_GARDEN:
-                    handleWalledGardenCheck((String) msg.obj);
-                    break;
-                case MESSAGE_SLEEP:
-                    handleSleep((String) msg.obj);
-                    break;
-                case ACTION_IDLE:
-                    handleIdle();
-                    break;
-                case MESSAGE_DISABLE_WATCHDOG:
-                    handleIdle();
-                    break;
-                case MESSAGE_DISCONNECTED:
-                    handleDisconnected();
-                    break;
-                case MESSAGE_RESET:
-                    handleReset();
-                    break;
-            }
-        }
-
-        /**
-         * DNS based detection techniques do not work at all hotspots. The one sure way to check
-         * a walled garden is to see if a URL fetch on a known address fetches the data we
-         * expect
-         */
-        private boolean isWalledGardenConnection() {
-            InputStream in = null;
-            HttpURLConnection  urlConnection = null;
-            try {
-                URL url = new URL(getWalledGardenUrl());
-                urlConnection = (HttpURLConnection) url.openConnection();
-                in = new BufferedInputStream(urlConnection.getInputStream());
-                Scanner scanner = new Scanner(in);
-                if (scanner.findInLine(getWalledGardenPattern()) != null) {
-                    return false;
-                } else {
-                    return true;
-                }
-            } catch (IOException e) {
-                return false;
-            } finally {
-                if (in != null) {
-                    try {
-                        in.close();
-                    } catch (IOException e) {
-                    }
-                }
-                if (urlConnection != null) urlConnection.disconnect();
-            }
-        }
-
-        private void handleWalledGardenCheck(String ssid) {
-            long currentTime = System.currentTimeMillis();
-            //Avoid a walled garden test on the same network if one was already done
-            //within MIN_WALLED_GARDEN_TEST_INTERVAL. This will handle scenarios where
-            //there are frequent network disconnections
-            if (ssid.equals(mLastSsid) &&
-                    (currentTime - mLastTime) < MIN_WALLED_GARDEN_TEST_INTERVAL) {
-                return;
-            }
-
-            mLastTime = currentTime;
-            mLastSsid = ssid;
-
-            if (isWalledGardenConnection()) {
-                Uri uri = Uri.parse("http://www.google.com");
-                Intent intent = new Intent(Intent.ACTION_VIEW, uri);
-                intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
-                        Intent.FLAG_ACTIVITY_NEW_TASK);
-                mContext.startActivity(intent);
-            }
-        }
-    }
-
-    /**
-     * Receives Wi-Fi broadcasts.
-     * <p>
-     * There is little logic in this class, instead methods of the form "on___"
-     * are called in the {@link WifiWatchdogService}.
-     */
-    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
-                handleNetworkStateChanged(
-                        (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO));
-            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
-                handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
-                        WifiManager.WIFI_STATE_UNKNOWN));
-            }
-        }
-
-        private void handleNetworkStateChanged(NetworkInfo info) {
-            if (V) {
-                myLogV("Receiver.handleNetworkStateChanged: NetworkInfo: "
-                        + info);
-            }
-            
-            switch (info.getState()) {
-                case CONNECTED:
-                    WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
-                    if (wifiInfo.getSSID() == null || wifiInfo.getBSSID() == null) {
-                        if (V) {
-                            myLogV("handleNetworkStateChanged: Got connected event but SSID or BSSID are null. SSID: "
-                                + wifiInfo.getSSID()
-                                + ", BSSID: "
-                                + wifiInfo.getBSSID() + ", ignoring event");
-                        }
-                        return;
-                    }
-                    onConnected(wifiInfo.getSSID(), wifiInfo.getBSSID());
-                    break;
-
-                case DISCONNECTED:
-                    onDisconnected();
-                    break;
-            }
-        }
-
-        private void handleWifiStateChanged(int wifiState) {
-            if (wifiState == WifiManager.WIFI_STATE_DISABLED) {
-                onDisconnected();
-            } else if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
-                onEnabled();
-            }
-        }
-    };
-
-    /**
-     * Describes an access point by its SSID and BSSID.
-     *
-     */
-    private static class AccessPoint {
-        String ssid;
-        String bssid;
-        
-        /**
-         * @param ssid cannot be null
-         * @param bssid cannot be null
-         */
-        AccessPoint(String ssid, String bssid) {
-            if (ssid == null || bssid == null) {
-                Slog.e(TAG, String.format("(%s) INVALID ACCESSPOINT: (%s, %s)",
-                        Thread.currentThread().getName(),ssid,bssid));
-            }
-            this.ssid = ssid;
-            this.bssid = bssid;
-        }
-        
-        @Override
-        public boolean equals(Object o) {
-            if (!(o instanceof AccessPoint)) return false;
-            AccessPoint otherAp = (AccessPoint) o;
-
-            // Either we both have a null, or our SSIDs and BSSIDs are equal
-            return ssid.equals(otherAp.ssid) && bssid.equals(otherAp.bssid);
-        }
-        
-        @Override
-        public int hashCode() {
-            return ssid.hashCode() + bssid.hashCode();
-        }
-
-        @Override
-        public String toString() {
-            return ssid + " (" + bssid + ")";
-        }
-    }
-
-    /**
-     * Performs a simple DNS "ping" by sending a "server status" query packet to
-     * the DNS server. As long as the server replies, we consider it a success.
-     * <p>
-     * We do not use a simple hostname lookup because that could be cached and
-     * the API may not differentiate between a time out and a failure lookup
-     * (which we really care about).
-     */
-    private static class DnsPinger {
-        
-        /** Number of bytes for the query */
-        private static final int DNS_QUERY_BASE_SIZE = 33;
-        
-        /** The DNS port */
-        private static final int DNS_PORT = 53;
-        
-        /** Used to generate IDs */
-        private static Random sRandom = new Random();
-
-        static boolean isDnsReachable(InetAddress dnsAddress, int timeout) {
-            DatagramSocket socket = null;
-            try {
-                socket = new DatagramSocket();
-
-                // Set some socket properties
-                socket.setSoTimeout(timeout);
-
-                byte[] buf = new byte[DNS_QUERY_BASE_SIZE];
-                fillQuery(buf);
-
-                // Send the DNS query
-
-                DatagramPacket packet = new DatagramPacket(buf,
-                        buf.length, dnsAddress, DNS_PORT);
-                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 true;
-
-            } catch (SocketException e) {
-                if (V) {
-                    Slog.v(TAG, "DnsPinger.isReachable received SocketException", e);
-                }
-                return false;
-
-            } catch (UnknownHostException e) {
-                if (V) {
-                    Slog.v(TAG, "DnsPinger.isReachable is unable to resolve the DNS host", e);
-                }
-                return false;
-
-            } catch (SocketTimeoutException e) {
-                return false;
-                
-            } catch (IOException e) {
-                if (V) {
-                    Slog.v(TAG, "DnsPinger.isReachable got an IOException", e);
-                }
-                return false;
-                
-            } catch (Exception e) {
-                if (V) {
-                    Slog.d(TAG, "DnsPinger.isReachable got an unknown exception", e);
-                }
-                return false;
-            } finally {
-                if (socket != null) {
-                    socket.close();
-                }
-            }
-        }
-        
-        private static void fillQuery(byte[] buf) {
-
-            /*
-             * See RFC2929 (though the bit tables in there are misleading for
-             * us. For example, the recursion desired bit is the 0th bit for us,
-             * but looking there it would appear as the 7th bit of the byte
-             */
-
-            // Make sure it's all zeroed out
-            for (int i = 0; i < buf.length; i++) buf[i] = 0;
-
-            // Form a query for www.android.com
-            
-            // [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] = 1; // Recursion desired
-
-            // [4-5] bytes are for the query count
-            buf[5] = 1; // One query 
-            
-            // [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-23] for android
-            writeString(buf, 16, "android");
-            
-            // [24-27] for com
-            writeString(buf, 24, "com");
-            
-            // [29-30] bytes are for QTYPE, set to 1 
-            buf[30] = 1;
-
-            // [31-32] bytes are for QCLASS, set to 1 
-            buf[32] = 1;
-        }
-        
-        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);
-            }
-        }
-    }
-}
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index f6dd43a..80cdf6b 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -436,7 +436,8 @@
     public IAccessibilityServiceConnection registerEventListener(IEventListener listener) {
         mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT,
                 FUNCTION_REGISTER_EVENT_LISTENER);
-        ComponentName componentName = new ComponentName("foo.bar", "FakeAccessibilityService");
+        ComponentName componentName = new ComponentName("foo.bar",
+                "AutomationAccessibilityService");
         synchronized (mLock) {
             Service oldService = mComponentNameToServiceMap.get(componentName);
             if (oldService != null) {
@@ -550,6 +551,26 @@
     private void notifyEventListenerLocked(Service service, int eventType) {
         IEventListener listener = service.mServiceInterface;
         AccessibilityEvent event = service.mPendingEvents.get(eventType);
+
+        // Check for null here because there is a concurrent scenario in which this
+        // happens: 1) A binder thread calls notifyAccessibilityServiceDelayedLocked
+        // which posts a message for dispatching an event. 2) The message is pulled
+        // from the queue by the handler on the service thread and the latter is
+        // just about to acquire the lock and call this method. 3) Now another binder
+        // thread acquires the lock calling notifyAccessibilityServiceDelayedLocked
+        // so the service thread waits for the lock; 4) The binder thread replaces
+        // the event with a more recent one (assume the same event type) and posts a
+        // dispatch request releasing the lock. 5) Now the main thread is unblocked and
+        // dispatches the event which is removed from the pending ones. 6) And ... now
+        // the service thread handles the last message posted by the last binder call
+        // but the event is already dispatched and hence looking it up in the pending
+        // ones yields null. This check is much simpler that keeping count for each
+        // event type of each service to catch such a scenario since only one message
+        // is processed at a time.
+        if (event == null) {
+            return;
+        }
+
         service.mPendingEvents.remove(eventType);
         try {
             if (mSecurityPolicy.canRetrieveWindowContent(service)) {
@@ -809,7 +830,7 @@
 
         boolean mCanRetrieveScreenContent;
 
-        boolean mIsFake;
+        boolean mIsAutomation;
 
         final Callback mCallback = new Callback();
 
@@ -822,12 +843,12 @@
             new SparseArray<AccessibilityEvent>();
 
         public Service(ComponentName componentName,
-                AccessibilityServiceInfo accessibilityServiceInfo, boolean isFake) {
+                AccessibilityServiceInfo accessibilityServiceInfo, boolean isAutomation) {
             mId = sIdCounter++;
             mComponentName = componentName;
             mAccessibilityServiceInfo = accessibilityServiceInfo;
-            mIsFake = isFake;
-            if (!isFake) {
+            mIsAutomation = isAutomation;
+            if (!isAutomation) {
                 mCanRetrieveScreenContent = accessibilityServiceInfo.getCanRetrieveWindowContent();
                 mIntent = new Intent().setComponent(mComponentName);
                 mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
@@ -861,7 +882,7 @@
          * @return True if binding is successful.
          */
         public boolean bind() {
-            if (!mIsFake && mService == null) {
+            if (!mIsAutomation && mService == null) {
                 return mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE);
             }
             return false;
@@ -878,7 +899,7 @@
                 synchronized (mLock) {
                     tryRemoveServiceLocked(this);
                 }
-                if (!mIsFake) {
+                if (!mIsAutomation) {
                     mContext.unbindService(this);
                 }
                 mService = null;
@@ -918,16 +939,19 @@
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
                 final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this);
-                if (permissionGranted) {
+                if (!permissionGranted) {
+                    return null;
+                } else {
                     connection = getConnectionToRetrievalAllowingWindowLocked();
+                    if (connection == null) {
+                        if (DEBUG) {
+                            Slog.e(LOG_TAG, "No interaction connection to a retrieve "
+                                    + "allowing window.");
+                        }
+                        return null;
+                    }
                 }
             }
-            if (connection == null) {
-                if (DEBUG) {
-                    Slog.e(LOG_TAG, "No interaction connection to a retrieve allowing window.");
-                }
-                return null;
-            }
             final long identityToken = Binder.clearCallingIdentity();
             try {
                 final int interactionId = mInteractionIdCounter.getAndIncrement();
@@ -962,16 +986,18 @@
             synchronized (mLock) {
                 final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, accessibilityWindowId);
-                if (permissionGranted) {
+                if (!permissionGranted) {
+                    return null;
+                } else {
                     connection = getConnectionToRetrievalAllowingWindowLocked();
+                    if (connection == null) {
+                        if (DEBUG) {
+                            Slog.e(LOG_TAG, "No interaction connection to focused window.");
+                        }
+                        return null;
+                    }
                 }
             }
-            if (connection == null) {
-                if (DEBUG) {
-                    Slog.e(LOG_TAG, "No interaction connection to focused window.");
-                }
-                return null;
-            }
             final long identityToken = Binder.clearCallingIdentity();
             try {
                 final int interactionId = mInteractionIdCounter.getAndIncrement();
@@ -1005,17 +1031,19 @@
             synchronized (mLock) {
                 final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, accessibilityWindowId);
-                if (permissionGranted) {
+                if (!permissionGranted) {
+                    return null;
+                } else {
                     connection = mWindowIdToInteractionConnectionMap.get(accessibilityWindowId);
+                    if (connection == null) {
+                        if (DEBUG) {
+                            Slog.e(LOG_TAG, "No interaction connection to window: "
+                                    + accessibilityWindowId);
+                        }
+                        return null;
+                    }
                 }
             }
-            if (connection == null) {
-                if (DEBUG) {
-                    Slog.e(LOG_TAG, "No interaction connection to window: "
-                            + accessibilityWindowId);
-                }
-                return null;
-            }
             final long identityToken = Binder.clearCallingIdentity();
             try {
                 final int interactionId = mInteractionIdCounter.getAndIncrement();
@@ -1046,17 +1074,19 @@
             synchronized (mLock) {
                 final boolean permissionGranted = mSecurityPolicy.canPerformActionLocked(this,
                         accessibilityWindowId, action);
-                if (permissionGranted) {
+                if (!permissionGranted) {
+                    return false;
+                } else {
                     connection = mWindowIdToInteractionConnectionMap.get(accessibilityWindowId);
+                    if (connection == null) {
+                        if (DEBUG) {
+                            Slog.e(LOG_TAG, "No interaction connection to window: "
+                                    + accessibilityWindowId);
+                        }
+                        return false;
+                    }
                 }
             }
-            if (connection == null) {
-                if (DEBUG) {
-                    Slog.e(LOG_TAG, "No interaction connection to window: "
-                            + accessibilityWindowId);
-                }
-                return false;
-            }
             final long identityToken = Binder.clearCallingIdentity();
             try {
                 final int interactionId = mInteractionIdCounter.getAndIncrement();
@@ -1131,7 +1161,9 @@
             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_VIEW_SELECTED
-            | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
+            | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
+            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
+            | AccessibilityEvent.TYPE_VIEW_SCROLLED;
 
         private int mRetrievalAlowingWindowId;
 
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index aab189a..1af7015 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -26,7 +26,6 @@
 import android.os.Handler;
 import android.os.SystemClock;
 import android.util.Slog;
-import android.util.SparseArray;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 import android.view.WindowManagerPolicy;
@@ -73,15 +72,6 @@
     private static final int STATE_DRAGGING = 0x00000002;
     private static final int STATE_DELEGATING = 0x00000004;
 
-    // Human readable symbolic names for the states of the explorer.
-    private static final SparseArray<String> sStateSymbolicNames = new SparseArray<String>();
-    static {
-        SparseArray<String> symbolicNames = sStateSymbolicNames;
-        symbolicNames.append(STATE_TOUCH_EXPLORING, "STATE_TOUCH_EXPLORING");
-        symbolicNames.append(STATE_DRAGGING, "STATE_DRAGING");
-        symbolicNames.append(STATE_DELEGATING, "STATE_DELEGATING");
-    }
-
     // Invalid pointer ID.
     private static final int INVALID_POINTER_ID = -1;
 
@@ -189,7 +179,7 @@
         if (DEBUG) {
             Slog.d(LOG_TAG_RECEIVED, "Received event: " + event + ", policyFlags=0x"
                     + Integer.toHexString(policyFlags));
-            Slog.d(LOG_TAG_STATE, sStateSymbolicNames.get(mCurrentState));
+            Slog.d(LOG_TAG_STATE, getStateSymbolicName(mCurrentState));
         }
 
         // Keep track of the pointers's state.
@@ -708,8 +698,7 @@
     private void sendActionDownAndUp(MotionEvent prototype, int policyFlags) {
         final PointerProperties[] pointerProperties = mTempPointerProperties;
         final PointerCoords[] pointerCoords = mTempPointerCoords;
-        final int pointerId = mPointerTracker.getLastReceivedUpPointerId();
-        final int pointerIndex = prototype.findPointerIndex(pointerId);
+        final int pointerIndex = prototype.getActionIndex();
 
         // Send down.
         prototype.getPointerProperties(pointerIndex, pointerProperties[0]);
@@ -884,6 +873,25 @@
     }
 
     /**
+     * Gets the symbolic name of a state.
+     *
+     * @param state A state.
+     * @return The state symbolic name.
+     */
+    private static String getStateSymbolicName(int state) {
+        switch (state) {
+            case STATE_TOUCH_EXPLORING:
+                return "STATE_TOUCH_EXPLORING";
+            case STATE_DRAGGING:
+                return "STATE_DRAGGING";
+            case STATE_DELEGATING:
+                return "STATE_DELEGATING";
+            default:
+                throw new IllegalArgumentException("Unknown state: " + state);
+        }
+    }
+
+    /**
      * Helper class for tracking pointers and more specifically which of
      * them are currently down, which are active, and which are delivered
      * to the view hierarchy. The enclosing {@link TouchExplorer} uses the
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 4ec71c1..d5e8730 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -502,15 +502,6 @@
             = new ArrayList<ProcessRecord>();
 
     /**
-     * List of records for processes that we have started and are waiting
-     * for them to call back.  This is really only needed when running in
-     * single processes mode, in which case we do not have a unique pid for
-     * each process.
-     */
-    final ArrayList<ProcessRecord> mStartingProcesses
-            = new ArrayList<ProcessRecord>();
-
-    /**
      * List of persistent applications that are in the process
      * of being started.
      */
@@ -622,6 +613,11 @@
             }
             return true;
         }
+
+        @Override
+        protected String packageForFilter(BroadcastFilter filter) {
+            return filter.packageName;
+        }
     };
 
     /**
@@ -1825,6 +1821,8 @@
                 // We already have the app running, or are waiting for it to
                 // come up (we have a pid but not yet its thread), so keep it.
                 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
+                // If this is a new package in the process, add the package to the list
+                app.addPackage(info.packageName);
                 return app;
             } else {
                 // An application record is attached to a previous process,
@@ -1946,11 +1944,15 @@
             if ("1".equals(SystemProperties.get("debug.checkjni"))) {
                 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
             }
+            if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
+                debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
+            }
             if ("1".equals(SystemProperties.get("debug.assert"))) {
                 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
             }
             int pid = Process.start("android.app.ActivityThread",
-                    app.processName, uid, uid, gids, debugFlags, null);
+                    app.processName, uid, uid, gids, debugFlags,
+                    app.info.targetSdkVersion, null);
             BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
             synchronized (bs) {
                 if (bs.isOnBattery()) {
@@ -1990,12 +1992,7 @@
             }
             buf.append("}");
             Slog.i(TAG, buf.toString());
-            if (pid == 0 || pid == MY_PID) {
-                // Processes are being emulated with threads.
-                app.pid = MY_PID;
-                app.removed = false;
-                mStartingProcesses.add(app);
-            } else if (pid > 0) {
+            if (pid > 0) {
                 app.pid = pid;
                 app.removed = false;
                 synchronized (mPidsSelfLocked) {
@@ -2278,7 +2275,7 @@
             }
         }
         
-        return pir.sendInner(0, fillInIntent, resolvedType,
+        return pir.sendInner(0, fillInIntent, resolvedType, null,
                 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
     }
     
@@ -3595,9 +3592,6 @@
             synchronized (mPidsSelfLocked) {
                 app = mPidsSelfLocked.get(pid);
             }
-        } else if (mStartingProcesses.size() > 0) {
-            app = mStartingProcesses.remove(0);
-            app.setPid(pid);
         } else {
             app = null;
         }
@@ -4031,8 +4025,7 @@
         synchronized(this) {
             int callingUid = Binder.getCallingUid();
             try {
-                if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
-                        Process.supportsProcesses()) {
+                if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
                     int uid = AppGlobals.getPackageManager()
                             .getPackageUid(packageName);
                     if (uid != Binder.getCallingUid()) {
@@ -4162,6 +4155,27 @@
         return null;
     }
 
+    public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
+        if (!(pendingResult instanceof PendingIntentRecord)) {
+            return false;
+        }
+        try {
+            PendingIntentRecord res = (PendingIntentRecord)pendingResult;
+            if (res.key.allIntents == null) {
+                return false;
+            }
+            for (int i=0; i<res.key.allIntents.length; i++) {
+                Intent intent = res.key.allIntents[i];
+                if (intent.getPackage() != null && intent.getComponent() != null) {
+                    return false;
+                }
+            }
+            return true;
+        } catch (ClassCastException e) {
+        }
+        return false;
+    }
+
     public void setProcessLimit(int max) {
         enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
                 "setProcessLimit()");
@@ -4270,8 +4284,7 @@
         }
 
         // Root, system server and our own process get to do everything.
-        if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
-            !Process.supportsProcesses()) {
+        if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
             return PackageManager.PERMISSION_GRANTED;
         }
         // If there is a uid that owns whatever is being accessed, it has
@@ -4415,7 +4428,7 @@
     private final boolean checkUriPermissionLocked(Uri uri, int uid,
             int modeFlags) {
         // Root gets to do everything.
-        if (uid == 0 || !Process.supportsProcesses()) {
+        if (uid == 0) {
             return true;
         }
         HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
@@ -5143,7 +5156,7 @@
         }
     }
 
-    private void removeTaskProcessesLocked(ActivityRecord root) {
+    private void cleanUpRemovedTaskLocked(ActivityRecord root, boolean killProcesses) {
         TaskRecord tr = root.task;
         Intent baseIntent = new Intent(
                 tr.intent != null ? tr.intent : tr.affinityIntent);
@@ -5166,6 +5179,7 @@
             ServiceRecord sr = services.get(i);
             if (sr.startRequested) {
                 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
+                    Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
                     stopServiceLocked(sr);
                 } else {
                     sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
@@ -5177,26 +5191,28 @@
             }
         }
 
-        // Find any running processes associated with this app.
-        ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
-        SparseArray<ProcessRecord> appProcs
-                = mProcessNames.getMap().get(component.getPackageName());
-        if (appProcs != null) {
-            for (int i=0; i<appProcs.size(); i++) {
-                procs.add(appProcs.valueAt(i));
+        if (killProcesses) {
+            // Find any running processes associated with this app.
+            ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
+            SparseArray<ProcessRecord> appProcs
+                    = mProcessNames.getMap().get(component.getPackageName());
+            if (appProcs != null) {
+                for (int i=0; i<appProcs.size(); i++) {
+                    procs.add(appProcs.valueAt(i));
+                }
             }
-        }
 
-        // Kill the running processes.
-        for (int i=0; i<procs.size(); i++) {
-            ProcessRecord pr = procs.get(i);
-            if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
-                Slog.i(TAG, "Killing " + pr + ": remove task");
-                EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
-                        pr.processName, pr.setAdj, "remove task");
-                Process.killProcessQuiet(pr.pid);
-            } else {
-                pr.waitingToKill = "remove task";
+            // Kill the running processes.
+            for (int i=0; i<procs.size(); i++) {
+                ProcessRecord pr = procs.get(i);
+                if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
+                    Slog.i(TAG, "Killing " + pr.toShortString() + ": remove task");
+                    EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
+                            pr.processName, pr.setAdj, "remove task");
+                    Process.killProcessQuiet(pr.pid);
+                } else {
+                    pr.waitingToKill = "remove task";
+                }
             }
         }
     }
@@ -5210,11 +5226,8 @@
                 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
                 if (r != null) {
                     mRecentTasks.remove(r.task);
-
-                    if ((flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0) {
-                        removeTaskProcessesLocked(r);
-                    }
-
+                    cleanUpRemovedTaskLocked(r,
+                            (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0);
                     return true;
                 }
             } finally {
@@ -5496,8 +5509,8 @@
     // CONTENT PROVIDERS
     // =========================================================
 
-    private final List generateApplicationProvidersLocked(ProcessRecord app) {
-        List providers = null;
+    private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
+        List<ProviderInfo> providers = null;
         try {
             providers = AppGlobals.getPackageManager().
                 queryContentProviders(app.processName, app.info.uid,
@@ -5935,7 +5948,7 @@
     }
 
     public static final void installSystemProviders() {
-        List providers;
+        List<ProviderInfo> providers;
         synchronized (mSelf) {
             ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
             providers = mSelf.generateApplicationProvidersLocked(app);
@@ -6553,13 +6566,6 @@
     }
     
     public void systemReady(final Runnable goingCallback) {
-        // In the simulator, startRunning will never have been called, which
-        // normally sets a few crucial variables. Do it here instead.
-        if (!Process.supportsProcesses()) {
-            mStartRunning = true;
-            mTopAction = Intent.ACTION_MAIN;
-        }
-
         synchronized(this) {
             if (mSystemReady) {
                 if (goingCallback != null) goingCallback.run();
@@ -7923,14 +7929,6 @@
                     "Starting Norm", "Restarting PERS");
         }
 
-        if (mStartingProcesses.size() > 0) {
-            if (needSep) pw.println(" ");
-            needSep = true;
-            pw.println("  Processes that are starting:");
-            dumpProcessList(pw, this, mStartingProcesses, "    ",
-                    "Starting Norm", "Starting PERS");
-        }
-
         if (mRemovedProcesses.size() > 0) {
             if (needSep) pw.println(" ");
             needSep = true;
@@ -9895,6 +9893,7 @@
         ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
         if (app != null && app.thread != null) {
             try {
+                app.addPackage(r.appInfo.packageName);
                 realStartServiceLocked(r, app);
                 return true;
             } catch (RemoteException e) {
@@ -10945,7 +10944,7 @@
         mBroadcastsScheduled = true;
     }
 
-    public Intent registerReceiver(IApplicationThread caller,
+    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
             IIntentReceiver receiver, IntentFilter filter, String permission) {
         synchronized(this) {
             ProcessRecord callerApp = null;
@@ -10957,6 +10956,13 @@
                             + " (pid=" + Binder.getCallingPid()
                             + ") when registering receiver " + receiver);
                 }
+                if (callerApp.info.uid != Process.SYSTEM_UID &&
+                        !callerApp.pkgList.contains(callerPackage)) {
+                    throw new SecurityException("Given caller package " + callerPackage
+                            + " is not running in process " + callerApp);
+                }
+            } else {
+                callerPackage = null;
             }
 
             List allSticky = null;
@@ -11001,7 +11007,7 @@
                 }
                 mRegisteredReceivers.put(receiver.asBinder(), rl);
             }
-            BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
+            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
             rl.add(bf);
             if (!bf.debugCheck()) {
                 Slog.w(TAG, "==> For Dynamic broadast");
@@ -12155,6 +12161,7 @@
                     info.activityInfo.applicationInfo.uid);
             if (app != null && app.thread != null) {
                 try {
+                    app.addPackage(info.activityInfo.packageName);
                     processCurBroadcastLocked(r, app);
                     return;
                 } catch (RemoteException e) {
@@ -13087,74 +13094,72 @@
 
         int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
 
-        if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
-            if (app.curRawAdj != app.setRawAdj) {
-                if (app.curRawAdj > FOREGROUND_APP_ADJ
-                        && app.setRawAdj <= FOREGROUND_APP_ADJ) {
-                    // If this app is transitioning from foreground to
-                    // non-foreground, have it do a gc.
-                    scheduleAppGcLocked(app);
-                } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
-                        && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
-                    // Likewise do a gc when an app is moving in to the
-                    // background (such as a service stopping).
-                    scheduleAppGcLocked(app);
-                }
+        if (app.curRawAdj != app.setRawAdj) {
+            if (app.curRawAdj > FOREGROUND_APP_ADJ
+                    && app.setRawAdj <= FOREGROUND_APP_ADJ) {
+                // If this app is transitioning from foreground to
+                // non-foreground, have it do a gc.
+                scheduleAppGcLocked(app);
+            } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
+                    && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
+                // Likewise do a gc when an app is moving in to the
+                // background (such as a service stopping).
+                scheduleAppGcLocked(app);
+            }
 
-                if (wasKeeping && !app.keeping) {
-                    // This app is no longer something we want to keep.  Note
-                    // its current wake lock time to later know to kill it if
-                    // it is not behaving well.
-                    BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
-                    synchronized (stats) {
-                        app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
-                                app.pid, SystemClock.elapsedRealtime());
+            if (wasKeeping && !app.keeping) {
+                // This app is no longer something we want to keep.  Note
+                // its current wake lock time to later know to kill it if
+                // it is not behaving well.
+                BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
+                synchronized (stats) {
+                    app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
+                            app.pid, SystemClock.elapsedRealtime());
+                }
+                app.lastCpuTime = app.curCpuTime;
+            }
+
+            app.setRawAdj = app.curRawAdj;
+        }
+        if (adj != app.setAdj) {
+            if (Process.setOomAdj(app.pid, adj)) {
+                if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
+                    TAG, "Set app " + app.processName +
+                    " oom adj to " + adj);
+                app.setAdj = adj;
+            } else {
+                success = false;
+            }
+        }
+        if (app.setSchedGroup != app.curSchedGroup) {
+            app.setSchedGroup = app.curSchedGroup;
+            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
+                    "Setting process group of " + app.processName
+                    + " to " + app.curSchedGroup);
+            if (app.waitingToKill != null &&
+                    app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
+                Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
+                EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
+                        app.processName, app.setAdj, app.waitingToKill);
+                Process.killProcessQuiet(app.pid);
+            } else {
+                if (true) {
+                    long oldId = Binder.clearCallingIdentity();
+                    try {
+                        Process.setProcessGroup(app.pid, app.curSchedGroup);
+                    } catch (Exception e) {
+                        Slog.w(TAG, "Failed setting process group of " + app.pid
+                                + " to " + app.curSchedGroup);
+                        e.printStackTrace();
+                    } finally {
+                        Binder.restoreCallingIdentity(oldId);
                     }
-                    app.lastCpuTime = app.curCpuTime;
                 }
-
-                app.setRawAdj = app.curRawAdj;
-            }
-            if (adj != app.setAdj) {
-                if (Process.setOomAdj(app.pid, adj)) {
-                    if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
-                        TAG, "Set app " + app.processName +
-                        " oom adj to " + adj);
-                    app.setAdj = adj;
-                } else {
-                    success = false;
-                }
-            }
-            if (app.setSchedGroup != app.curSchedGroup) {
-                app.setSchedGroup = app.curSchedGroup;
-                if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
-                        "Setting process group of " + app.processName
-                        + " to " + app.curSchedGroup);
-                if (app.waitingToKill != null &&
-                        app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
-                    Slog.i(TAG, "Killing " + app + ": " + app.waitingToKill);
-                    EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
-                            app.processName, app.setAdj, app.waitingToKill);
-                    Process.killProcessQuiet(app.pid);
-                } else {
-                    if (true) {
-                        long oldId = Binder.clearCallingIdentity();
+                if (false) {
+                    if (app.thread != null) {
                         try {
-                            Process.setProcessGroup(app.pid, app.curSchedGroup);
-                        } catch (Exception e) {
-                            Slog.w(TAG, "Failed setting process group of " + app.pid
-                                    + " to " + app.curSchedGroup);
-                            e.printStackTrace();
-                        } finally {
-                            Binder.restoreCallingIdentity(oldId);
-                        }
-                    }
-                    if (false) {
-                        if (app.thread != null) {
-                            try {
-                                app.thread.setSchedulingGroup(app.curSchedGroup);
-                            } catch (RemoteException e) {
-                            }
+                            app.thread.setSchedulingGroup(app.curSchedGroup);
+                        } catch (RemoteException e) {
                         }
                     }
                 }
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index b94ee58..b1da69f 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -652,6 +652,7 @@
         
         if (app != null && app.thread != null) {
             try {
+                app.addPackage(r.info.packageName);
                 realStartActivityLocked(r, app, andResume, checkConfig);
                 return;
             } catch (RemoteException e) {
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index b4fdc9f..293702d 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -446,6 +446,15 @@
                 Binder.getCallingPid(), Binder.getCallingUid(), null);
     }
     
+    private void dumpHelp(PrintWriter pw) {
+        pw.println("Battery stats (batteryinfo) dump options:");
+        pw.println("  [--checkin] [--reset] [--write] [-h]");
+        pw.println("  --checkin: format output for a checkin report.");
+        pw.println("  --reset: reset the stats, clearing all current data.");
+        pw.println("  --write: force write current collected stats to disk.");
+        pw.println("  -h: print this help text.");
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         boolean isCheckin = false;
@@ -466,8 +475,12 @@
                         pw.println("Battery stats written.");
                         noOutput = true;
                     }
+                } else if ("-h".equals(arg)) {
+                    dumpHelp(pw);
+                    return;
                 } else {
                     pw.println("Unknown option: " + arg);
+                    dumpHelp(pw);
                 }
             }
         }
diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/java/com/android/server/am/BroadcastFilter.java
index 2e784d3..b49bc22 100644
--- a/services/java/com/android/server/am/BroadcastFilter.java
+++ b/services/java/com/android/server/am/BroadcastFilter.java
@@ -25,12 +25,14 @@
 class BroadcastFilter extends IntentFilter {
     // Back-pointer to the list this filter is in.
     final ReceiverList receiverList;
+    final String packageName;
     final String requiredPermission;
 
     BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList,
-            String _requiredPermission) {
+            String _packageName, String _requiredPermission) {
         super(_filter);
         receiverList = _receiverList;
+        packageName = _packageName;
         requiredPermission = _requiredPermission;
     }
     
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index ee6e420..8ed0cc1 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -177,13 +177,13 @@
     }
 
     public int send(int code, Intent intent, String resolvedType,
-            IIntentReceiver finishedReceiver) {
+            IIntentReceiver finishedReceiver, String requiredPermission) {
         return sendInner(code, intent, resolvedType, finishedReceiver,
-                null, null, 0, 0, 0);
+                requiredPermission, null, null, 0, 0, 0);
     }
     
     int sendInner(int code, Intent intent, String resolvedType,
-            IIntentReceiver finishedReceiver,
+            IIntentReceiver finishedReceiver, String requiredPermission,
             IBinder resultTo, String resultWho, int requestCode,
             int flagsMask, int flagsValues) {
         synchronized(owner) {
@@ -246,8 +246,8 @@
                             // that the broadcast be delivered synchronously
                             owner.broadcastIntentInPackage(key.packageName, uid,
                                     finalIntent, resolvedType,
-                                    finishedReceiver, code, null, null, null,
-                                    (finishedReceiver != null), false);
+                                    finishedReceiver, code, null, null,
+                                    requiredPermission, (finishedReceiver != null), false);
                             sendFinish = false;
                         } catch (RuntimeException e) {
                             Slog.w(ActivityManagerService.TAG,
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 911cac2..6bb7949 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -189,8 +189,8 @@
         mDnsServers[1] = DNS_DEFAULT_SERVER2;
     }
 
-    public void interfaceLinkStatusChanged(String iface, boolean link) {
-        if (DEBUG) Log.d(TAG, "interfaceLinkStatusChanged " + iface + ", " + link);
+    public void interfaceStatusChanged(String iface, boolean up) {
+        if (DEBUG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
         boolean found = false;
         boolean usb = false;
         if (isWifi(iface)) {
@@ -205,7 +205,7 @@
 
         synchronized (mIfaces) {
             TetherInterfaceSM sm = mIfaces.get(iface);
-            if (link) {
+            if (up) {
                 if (sm == null) {
                     sm = new TetherInterfaceSM(iface, mLooper, usb);
                     mIfaces.put(iface, sm);
@@ -220,6 +220,11 @@
         }
     }
 
+    public void interfaceLinkStateChanged(String iface, boolean up) {
+        if (DEBUG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up);
+        interfaceStatusChanged(iface, up);
+    }
+
     private boolean isUsb(String iface) {
         for (String regex : mTetherableUsbRegexs) {
             if (iface.matches(regex)) return true;
@@ -689,6 +694,14 @@
         return retVal;
     }
 
+    //TODO: Temporary handling upstream change triggered without
+    //      CONNECTIVITY_ACTION. Only to accomodate interface
+    //      switch during HO.
+    //      @see bug/4455071
+    public void handleTetherIfaceChange() {
+        mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
+    }
+
     class TetherInterfaceSM extends StateMachine {
         // notification from the master SM that it's not in tether mode
         static final int CMD_TETHER_MODE_DEAD            =  1;
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 47813f8..c185012 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -27,15 +27,24 @@
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.net.INetworkManagementEventObserver;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
 import android.os.Binder;
 import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
+import android.os.Process;
+import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.util.Log;
 
 import com.android.internal.R;
+import com.android.internal.net.LegacyVpnInfo;
 import com.android.internal.net.VpnConfig;
 import com.android.server.ConnectivityService.VpnCallback;
 
+import java.io.OutputStream;
+import java.nio.charset.Charsets;
+import java.util.Arrays;
+
 /**
  * @hide
  */
@@ -47,9 +56,9 @@
     private final Context mContext;
     private final VpnCallback mCallback;
 
-    private String mPackageName;
-    private String mInterfaceName;
-    private String mDnsPropertyPrefix;
+    private String mPackage = VpnConfig.LEGACY_VPN;
+    private String mInterface;
+    private LegacyVpnRunner mLegacyVpnRunner;
 
     public Vpn(Context context, VpnCallback callback) {
         mContext = context;
@@ -57,60 +66,16 @@
     }
 
     /**
-     * Prepare for a VPN application.
-     *
-     * @param packageName The package name of the new VPN application.
-     * @return The name of the current prepared package.
-     */
-    public synchronized String prepare(String packageName) {
-        // Return the current prepared package if the new one is null.
-        if (packageName == null) {
-            return mPackageName;
-        }
-
-        // Check the permission of the caller.
-        PackageManager pm = mContext.getPackageManager();
-        VpnConfig.enforceCallingPackage(pm.getNameForUid(Binder.getCallingUid()));
-
-        // Check the permission of the given package.
-        if (packageName.isEmpty()) {
-            packageName = null;
-        } else if (pm.checkPermission(VPN, packageName) != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException(packageName + " does not have " + VPN);
-        }
-
-        // Reset the interface and hide the notification.
-        if (mInterfaceName != null) {
-            nativeReset(mInterfaceName);
-            mCallback.restore();
-            hideNotification();
-            mInterfaceName = null;
-        }
-
-        // Notify the package being revoked.
-        if (mPackageName != null) {
-            Intent intent = new Intent(VpnConfig.ACTION_VPN_REVOKED);
-            intent.setPackage(mPackageName);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-            mContext.sendBroadcast(intent);
-        }
-
-        Log.i(TAG, "Switched from " + mPackageName + " to " + packageName);
-        mPackageName = packageName;
-        return mPackageName;
-    }
-
-    /**
      * Protect a socket from routing changes by binding it to the given
      * interface. The socket IS closed by this method.
      *
      * @param socket The socket to be bound.
      * @param name The name of the interface.
      */
-    public void protect(ParcelFileDescriptor socket, String name) {
+    public void protect(ParcelFileDescriptor socket, String interfaze) {
         try {
             mContext.enforceCallingPermission(VPN, "protect");
-            nativeProtect(socket.getFd(), name);
+            jniProtect(socket.getFd(), interfaze);
         } finally {
             try {
                 socket.close();
@@ -121,10 +86,78 @@
     }
 
     /**
-     * Configure a TUN interface and return its file descriptor.
+     * 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
+     * package is revoked and replaced with {@code newPackage}. If
+     * {@code oldPackage} is {@code null}, the comparison is omitted.
+     * If {@code newPackage} is the same package or {@code null}, the
+     * revocation is omitted. This method returns {@code true} if the
+     * operation is succeeded.
      *
-     * @param configuration The parameters to configure the interface.
-     * @return The file descriptor of the interface.
+     * Legacy VPN is handled specially since it is not a real package.
+     * It uses {@link VpnConfig#LEGACY_VPN} as its package name, and
+     * it can be revoked by itself.
+     *
+     * @param oldPackage The package name of the old VPN application.
+     * @param newPackage The package name of the new VPN application.
+     * @return true if the operation is succeeded.
+     */
+    public synchronized boolean prepare(String oldPackage, String newPackage) {
+        // Return false if the package does not match.
+        if (oldPackage != null && !oldPackage.equals(mPackage)) {
+            return false;
+        }
+
+        // Return true if we do not need to revoke.
+        if (newPackage == null ||
+                (newPackage.equals(mPackage) && !newPackage.equals(VpnConfig.LEGACY_VPN))) {
+            return true;
+        }
+
+        // Only system user can revoke a package.
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            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);
+            mCallback.restore();
+            hideNotification();
+            mInterface = null;
+        }
+
+        // Send out the broadcast 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);
+        } else if (mLegacyVpnRunner != null) {
+            mLegacyVpnRunner.exit();
+            mLegacyVpnRunner = null;
+        }
+
+        Log.i(TAG, "Switched from " + mPackage + " to " + newPackage);
+        mPackage = newPackage;
+        return true;
+    }
+
+    /**
+     * 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.
+     *
+     * @param config The parameters to configure the network.
+     * @return The file descriptor of the VPN interface.
      */
     public synchronized ParcelFileDescriptor establish(VpnConfig config) {
         // Check the permission of the caller.
@@ -134,7 +167,7 @@
         PackageManager pm = mContext.getPackageManager();
         ApplicationInfo app = null;
         try {
-            app = pm.getApplicationInfo(mPackageName, 0);
+            app = pm.getApplicationInfo(mPackage, 0);
         } catch (Exception e) {
             return null;
         }
@@ -142,85 +175,91 @@
             return null;
         }
 
-        // Create and configure the interface.
-        ParcelFileDescriptor descriptor = ParcelFileDescriptor.adoptFd(
-                nativeEstablish(config.mtu, config.addresses, config.routes));
+        // Load the label.
+        String label = app.loadLabel(pm).toString();
 
-        // Replace the interface and abort if it fails.
+        // Load the icon and convert it into a bitmap.
+        Drawable icon = app.loadIcon(pm);
+        Bitmap bitmap = null;
+        if (icon.getIntrinsicWidth() > 0 && icon.getIntrinsicHeight() > 0) {
+            int width = mContext.getResources().getDimensionPixelSize(
+                    android.R.dimen.notification_large_icon_width);
+            int height = mContext.getResources().getDimensionPixelSize(
+                    android.R.dimen.notification_large_icon_height);
+            icon.setBounds(0, 0, width, height);
+            bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+            icon.draw(new Canvas(bitmap));
+        }
+
+        // Configure the interface. Abort if any of these steps fails.
+        ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(
+                jniConfigure(config.mtu, config.addresses, config.routes));
         try {
-            String interfaceName = nativeGetName(descriptor.getFd());
-
-            if (mInterfaceName != null && !mInterfaceName.equals(interfaceName)) {
-                nativeReset(mInterfaceName);
+            String interfaze = jniGetName(tun.getFd());
+            if (mInterface != null && !mInterface.equals(interfaze)) {
+                jniReset(mInterface);
             }
-            mInterfaceName = interfaceName;
+            mInterface = interfaze;
         } catch (RuntimeException e) {
             try {
-                descriptor.close();
+                tun.close();
             } catch (Exception ex) {
                 // ignore
             }
             throw e;
         }
 
-        String dnsServers = (config.dnsServers == null) ? "" : config.dnsServers.trim();
-        mCallback.override(dnsServers.isEmpty() ? null : dnsServers.split(" "));
+        // Override DNS servers and search domains.
+        mCallback.override(config.dnsServers, config.searchDomains);
 
-        config.packageName = mPackageName;
-        config.interfaceName = mInterfaceName;
-        showNotification(pm, app, config);
-        return descriptor;
+        // Fill more values.
+        config.packagz = mPackage;
+        config.interfaze = mInterface;
+
+        // Show the notification!
+        showNotification(config, label, bitmap);
+        return tun;
     }
 
     // INetworkManagementEventObserver.Stub
-    public void interfaceLinkStatusChanged(String name, boolean up) {
+    public void interfaceStatusChanged(String interfaze, boolean up) {
     }
 
     // INetworkManagementEventObserver.Stub
-    public void interfaceAdded(String name) {
+    public void interfaceLinkStateChanged(String interfaze, boolean up) {
     }
 
     // INetworkManagementEventObserver.Stub
-    public synchronized void interfaceRemoved(String name) {
-        if (name.equals(mInterfaceName) && nativeCheck(name) == 0) {
-            hideNotification();
-            mInterfaceName = null;
+    public void interfaceAdded(String interfaze) {
+    }
+
+    // INetworkManagementEventObserver.Stub
+    public synchronized void interfaceRemoved(String interfaze) {
+        if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
             mCallback.restore();
+            hideNotification();
+            mInterface = null;
         }
     }
 
-    private void showNotification(PackageManager pm, ApplicationInfo app, VpnConfig config) {
+    private void showNotification(VpnConfig config, String label, Bitmap icon) {
         NotificationManager nm = (NotificationManager)
                 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
 
         if (nm != null) {
-            // Load the icon and convert it into a bitmap.
-            Drawable icon = app.loadIcon(pm);
-            Bitmap bitmap = null;
-            if (icon.getIntrinsicWidth() > 0 && icon.getIntrinsicHeight() > 0) {
-                int width = mContext.getResources().getDimensionPixelSize(
-                        android.R.dimen.notification_large_icon_width);
-                int height = mContext.getResources().getDimensionPixelSize(
-                        android.R.dimen.notification_large_icon_height);
-                icon.setBounds(0, 0, width, height);
-                bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-                icon.draw(new Canvas(bitmap));
-            }
+            String title = (label == null) ? mContext.getString(R.string.vpn_title) :
+                    mContext.getString(R.string.vpn_title_long, label);
+            String text = (config.session == null) ? mContext.getString(R.string.vpn_text) :
+                    mContext.getString(R.string.vpn_text_long, config.session);
+            config.startTime = SystemClock.elapsedRealtime();
 
-            // Load the label.
-            String label = app.loadLabel(pm).toString();
-
-            // Build the notification.
-            String text = (config.sessionName == null) ? mContext.getString(R.string.vpn_text) :
-                    mContext.getString(R.string.vpn_text_long, config.sessionName);
             long identity = Binder.clearCallingIdentity();
             Notification notification = new Notification.Builder(mContext)
                     .setSmallIcon(R.drawable.vpn_connected)
-                    .setLargeIcon(bitmap)
-                    .setTicker(mContext.getString(R.string.vpn_ticker, label))
-                    .setContentTitle(mContext.getString(R.string.vpn_title, label))
+                    .setLargeIcon(icon)
+                    .setContentTitle(title)
                     .setContentText(text)
-                    .setContentIntent(VpnConfig.getIntentForNotification(mContext, config))
+                    .setContentIntent(VpnConfig.getIntentForStatusPanel(mContext, config))
                     .setDefaults(Notification.DEFAULT_ALL)
                     .setOngoing(true)
                     .getNotification();
@@ -240,9 +279,264 @@
         }
     }
 
-    private native int nativeEstablish(int mtu, String addresses, String routes);
-    private native String nativeGetName(int fd);
-    private native void nativeReset(String name);
-    private native int nativeCheck(String name);
-    private native void nativeProtect(int fd, String name);
+    private native int jniConfigure(int mtu, String addresses, String routes);
+    private native String jniGetName(int tun);
+    private native void jniReset(String interfaze);
+    private native int jniCheck(String interfaze);
+    private native void jniProtect(int socket, String interfaze);
+
+    /**
+     * Start legacy VPN. This method stops the daemons and restart them
+     * if arguments are not null. Heavy things are offloaded to another
+     * thread, so callers will not be blocked for a long time.
+     *
+     * @param config The parameters to configure the network.
+     * @param raoocn The arguments to be passed to racoon.
+     * @param mtpd The arguments to be passed to mtpd.
+     */
+    public synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) {
+        // Prepare for the new request. This also checks the caller.
+        prepare(null, VpnConfig.LEGACY_VPN);
+
+        // Start a new LegacyVpnRunner and we are done!
+        mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd);
+        mLegacyVpnRunner.start();
+    }
+
+    /**
+     * Return the information of the current ongoing legacy VPN.
+     */
+    public synchronized LegacyVpnInfo getLegacyVpnInfo() {
+        // Only system user can call this method.
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("Unauthorized Caller");
+        }
+        return (mLegacyVpnRunner == null) ? null : mLegacyVpnRunner.getInfo();
+    }
+
+    /**
+     * Bringing up a VPN connection takes time, and that is all this thread
+     * does. Here we have plenty of time. The only thing we need to take
+     * care of is responding to interruptions as soon as possible. Otherwise
+     * requests will be piled up. This can be done in a Handler as a state
+     * machine, but it is much easier to read in the current form.
+     */
+    private class LegacyVpnRunner extends Thread {
+        private static final String TAG = "LegacyVpnRunner";
+        private static final String NONE = "--";
+
+        private final VpnConfig mConfig;
+        private final String[] mDaemons;
+        private final String[][] mArguments;
+        private final LegacyVpnInfo mInfo;
+
+        private long mTimer = -1;
+
+        public LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd) {
+            super(TAG);
+            mConfig = config;
+            mDaemons = new String[] {"racoon", "mtpd"};
+            mArguments = new String[][] {racoon, mtpd};
+            mInfo = new LegacyVpnInfo();
+
+            // Legacy VPN is not a real package, so we use it to carry the key.
+            mInfo.key = mConfig.packagz;
+            mConfig.packagz = VpnConfig.LEGACY_VPN;
+        }
+
+        public void exit() {
+            // We assume that everything is reset after the daemons die.
+            for (String daemon : mDaemons) {
+                SystemProperties.set("ctl.stop", daemon);
+            }
+            interrupt();
+        }
+
+        public LegacyVpnInfo getInfo() {
+            // Update the info when VPN is disconnected.
+            if (mInfo.state == LegacyVpnInfo.STATE_CONNECTED && mInterface == null) {
+                mInfo.state = LegacyVpnInfo.STATE_DISCONNECTED;
+                mInfo.intent = null;
+            }
+            return mInfo;
+        }
+
+        @Override
+        public void run() {
+            // Wait for the previous thread since it has been interrupted.
+            Log.v(TAG, "Waiting");
+            synchronized (TAG) {
+                Log.v(TAG, "Executing");
+                execute();
+            }
+        }
+
+        private void checkpoint(boolean yield) throws InterruptedException {
+            long now = SystemClock.elapsedRealtime();
+            if (mTimer == -1) {
+                mTimer = now;
+                Thread.sleep(1);
+            } else if (now - mTimer <= 30000) {
+                Thread.sleep(yield ? 200 : 1);
+            } else {
+                mInfo.state = LegacyVpnInfo.STATE_TIMEOUT;
+                throw new IllegalStateException("time is up");
+            }
+        }
+
+        private void execute() {
+            // Catch all exceptions so we can clean up few things.
+            try {
+                // Initialize the timer.
+                checkpoint(false);
+                mInfo.state = LegacyVpnInfo.STATE_INITIALIZING;
+
+                // First stop the daemons.
+                for (String daemon : mDaemons) {
+                    SystemProperties.set("ctl.stop", daemon);
+                }
+
+                // Wait for the daemons to stop.
+                for (String daemon : mDaemons) {
+                    String key = "init.svc." + daemon;
+                    while (!"stopped".equals(SystemProperties.get(key))) {
+                        checkpoint(true);
+                    }
+                }
+
+                // Reset the properties.
+                SystemProperties.set("vpn.dns", NONE);
+                SystemProperties.set("vpn.via", NONE);
+                while (!NONE.equals(SystemProperties.get("vpn.dns")) ||
+                        !NONE.equals(SystemProperties.get("vpn.via"))) {
+                    checkpoint(true);
+                }
+
+                // Check if we need to restart any of the daemons.
+                boolean restart = false;
+                for (String[] arguments : mArguments) {
+                    restart = restart || (arguments != null);
+                }
+                if (!restart) {
+                    mInfo.state = LegacyVpnInfo.STATE_DISCONNECTED;
+                    return;
+                }
+                mInfo.state = LegacyVpnInfo.STATE_CONNECTING;
+
+                // Start the daemon with arguments.
+                for (int i = 0; i < mDaemons.length; ++i) {
+                    String[] arguments = mArguments[i];
+                    if (arguments == null) {
+                        continue;
+                    }
+
+                    // Start the daemon.
+                    String daemon = mDaemons[i];
+                    SystemProperties.set("ctl.start", daemon);
+
+                    // Wait for the daemon to start.
+                    String key = "init.svc." + daemon;
+                    while (!"running".equals(SystemProperties.get(key))) {
+                        checkpoint(true);
+                    }
+
+                    // Create the control socket.
+                    LocalSocket socket = new LocalSocket();
+                    LocalSocketAddress address = new LocalSocketAddress(
+                            daemon, LocalSocketAddress.Namespace.RESERVED);
+
+                    // Wait for the socket to connect.
+                    while (true) {
+                        try {
+                            socket.connect(address);
+                            break;
+                        } catch (Exception e) {
+                            // ignore
+                        }
+                        checkpoint(true);
+                    }
+                    socket.setSoTimeout(500);
+
+                    // Send over the arguments.
+                    OutputStream out = socket.getOutputStream();
+                    for (String argument : arguments) {
+                        byte[] bytes = argument.getBytes(Charsets.UTF_8);
+                        if (bytes.length >= 0xFFFF) {
+                            throw new IllegalArgumentException("argument is too large");
+                        }
+                        out.write(bytes.length >> 8);
+                        out.write(bytes.length);
+                        out.write(bytes);
+                        checkpoint(false);
+                    }
+
+                    // Send End-Of-Arguments.
+                    out.write(0xFF);
+                    out.write(0xFF);
+                    out.flush();
+                    socket.close();
+                }
+
+                // Now here is the beast from the old days. We check few
+                // properties to figure out the current status. Ideally we
+                // can read things back from the sockets and get rid of the
+                // properties, but we have no time...
+                while (NONE.equals(SystemProperties.get("vpn.dns")) ||
+                        NONE.equals(SystemProperties.get("vpn.via"))) {
+
+                    // Check if a running daemon is dead.
+                    for (int i = 0; i < mDaemons.length; ++i) {
+                        String daemon = mDaemons[i];
+                        if (mArguments[i] != null && !"running".equals(
+                                SystemProperties.get("init.svc." + daemon))) {
+                            throw new IllegalStateException(daemon + " is dead");
+                        }
+                    }
+                    checkpoint(true);
+                }
+
+                // Now we are connected. Get the interface.
+                mConfig.interfaze = SystemProperties.get("vpn.via");
+
+                // Get the DNS servers if they are not set in config.
+                if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) {
+                    String dnsServers = SystemProperties.get("vpn.dns").trim();
+                    if (!dnsServers.isEmpty()) {
+                        mConfig.dnsServers = Arrays.asList(dnsServers.split(" "));
+                    }
+                }
+
+                // TODO: support search domains from ISAKMP mode config.
+
+                // The final step must be synchronized.
+                synchronized (Vpn.this) {
+                    // Check if the thread is interrupted while we are waiting.
+                    checkpoint(false);
+
+                    // Check if the interface is gone while we are waiting.
+                    if (jniCheck(mConfig.interfaze) == 0) {
+                        throw new IllegalStateException(mConfig.interfaze + " is gone");
+                    }
+
+                    // Now INetworkManagementEventObserver is watching our back.
+                    mInterface = mConfig.interfaze;
+                    mCallback.override(mConfig.dnsServers, mConfig.searchDomains);
+                    showNotification(mConfig, null, null);
+
+                    Log.i(TAG, "Connected!");
+                    mInfo.state = LegacyVpnInfo.STATE_CONNECTED;
+                    mInfo.intent = VpnConfig.getIntentForStatusPanel(mContext, null);
+                }
+            } catch (Exception e) {
+                Log.i(TAG, "Aborting", e);
+                exit();
+            } finally {
+                // Do not leave an unstable state.
+                if (mInfo.state == LegacyVpnInfo.STATE_INITIALIZING ||
+                        mInfo.state == LegacyVpnInfo.STATE_CONNECTING) {
+                    mInfo.state = LegacyVpnInfo.STATE_FAILED;
+                }
+            }
+        }
+    }
 }
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 67e73f5..c813d37 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -32,7 +32,6 @@
 import android.location.LocationProvider;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
-import android.net.SntpClient;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -51,6 +50,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.gsm.GsmCellLocation;
 import android.util.Log;
+import android.util.NtpTrustedTime;
 import android.util.SparseIntArray;
 
 import com.android.internal.app.IBatteryStats;
@@ -61,7 +61,7 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
-import java.io.StringBufferInputStream;
+import java.io.StringReader;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.Map.Entry;
@@ -132,7 +132,7 @@
     private static final int GPS_CAPABILITY_MSB = 0x0000002;
     private static final int GPS_CAPABILITY_MSA = 0x0000004;
     private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
-
+    private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
 
     // these need to match AGpsType enum in gps.h
     private static final int AGPS_TYPE_SUPL = 1;
@@ -200,6 +200,9 @@
     private boolean mInjectNtpTimePending = true;
     private boolean mDownloadXtraDataPending = true;
 
+    // set to true if the GPS engine does not do on-demand NTP time requests
+    private boolean mPeriodicTimeInjection;
+
     // true if GPS is navigating
     private boolean mNavigating;
 
@@ -232,13 +235,13 @@
 
     // properties loaded from PROPERTIES_FILE
     private Properties mProperties;
-    private String mNtpServer;
     private String mSuplServerHost;
     private int mSuplServerPort;
     private String mC2KServerHost;
     private int mC2KServerPort;
 
     private final Context mContext;
+    private final NtpTrustedTime mNtpTime;
     private final ILocationManager mLocationManager;
     private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
     private Bundle mLocationExtras = new Bundle();
@@ -283,10 +286,6 @@
     // current setting - 5 minutes
     private static final long RETRY_INTERVAL = 5*60*1000;
 
-    // to avoid injecting bad NTP time, we reject any time fixes that differ from system time
-    // by more than 5 minutes.
-    private static final long MAX_NTP_SYSTEM_TIME_OFFSET = 5*60*1000;
-
     private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
         public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
             if (listener == null) {
@@ -375,6 +374,7 @@
 
     public GpsLocationProvider(Context context, ILocationManager locationManager) {
         mContext = context;
+        mNtpTime = NtpTrustedTime.getInstance(context);
         mLocationManager = locationManager;
         mNIHandler = new GpsNetInitiatedHandler(context);
 
@@ -415,7 +415,6 @@
             FileInputStream stream = new FileInputStream(file);
             mProperties.load(stream);
             stream.close();
-            mNtpServer = mProperties.getProperty("NTP_SERVER", null);
 
             mSuplServerHost = mProperties.getProperty("SUPL_HOST");
             String portString = mProperties.getProperty("SUPL_PORT");
@@ -527,13 +526,18 @@
         }
         mInjectNtpTimePending = false;
 
-        SntpClient client = new SntpClient();
         long delay;
 
-        if (client.requestTime(mNtpServer, 10000)) {
-            long time = client.getNtpTime();
-            long timeReference = client.getNtpTimeReference();
-            int certainty = (int)(client.getRoundTripTime()/2);
+        // force refresh NTP cache when outdated
+        if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
+            mNtpTime.forceRefresh();
+        }
+
+        // only update when NTP time is fresh
+        if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
+            long time = mNtpTime.getCachedNtpTime();
+            long timeReference = mNtpTime.getCachedNtpTimeReference();
+            long certainty = mNtpTime.getCacheCertainty();
             long now = System.currentTimeMillis();
 
             Log.d(TAG, "NTP server returned: "
@@ -542,17 +546,19 @@
                     + " certainty: " + certainty
                     + " system time offset: " + (time - now));
 
-            native_inject_time(time, timeReference, certainty);
+            native_inject_time(time, timeReference, (int) certainty);
             delay = NTP_INTERVAL;
         } else {
             if (DEBUG) Log.d(TAG, "requestTime failed");
             delay = RETRY_INTERVAL;
         }
 
-        // send delayed message for next NTP injection
-        // since this is delayed and not urgent we do not hold a wake lock here
-        mHandler.removeMessages(INJECT_NTP_TIME);
-        mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
+        if (mPeriodicTimeInjection) {
+            // send delayed message for next NTP injection
+            // since this is delayed and not urgent we do not hold a wake lock here
+            mHandler.removeMessages(INJECT_NTP_TIME);
+            mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
+        }
     }
 
     private void handleDownloadXtraData() {
@@ -1305,6 +1311,11 @@
      */
     private void setEngineCapabilities(int capabilities) {
         mEngineCapabilities = capabilities;
+
+        if (!hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME) && !mPeriodicTimeInjection) {
+            mPeriodicTimeInjection = true;
+            requestUtcTime();
+        }
     }
 
     /**
@@ -1385,7 +1396,7 @@
         Properties extraProp = new Properties();
 
         try {
-            extraProp.load(new StringBufferInputStream(extras));
+            extraProp.load(new StringReader(extras));
         }
         catch (IOException e)
         {
@@ -1438,6 +1449,14 @@
     }
 
     /**
+     * Called from native code to request utc time info
+     */
+
+    private void requestUtcTime() {
+        sendMessage(INJECT_NTP_TIME, 0, null);
+    }
+
+    /**
      * Called from native code to request reference location info
      */
 
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 584cd03..d23d0f4 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -25,6 +25,7 @@
 import static android.content.Intent.ACTION_UID_REMOVED;
 import static android.content.Intent.EXTRA_UID;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.*;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.NetworkPolicy.LIMIT_DISABLED;
 import static android.net.NetworkPolicy.WARNING_DISABLED;
@@ -57,6 +58,8 @@
 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.res.Resources;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
@@ -71,7 +74,9 @@
 import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.INetworkManagementService;
 import android.os.IPowerManager;
+import android.os.Message;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.telephony.TelephonyManager;
@@ -108,6 +113,7 @@
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 
 import libcore.io.IoUtils;
 
@@ -148,10 +154,14 @@
 
     private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
 
+    private static final int MSG_RULES_CHANGED = 0x1;
+    private static final int MSG_METERED_IFACES_CHANGED = 0x2;
+
     private final Context mContext;
     private final IActivityManager mActivityManager;
     private final IPowerManager mPowerManager;
     private final INetworkStatsService mNetworkStats;
+    private final INetworkManagementService mNetworkManagement;
     private final TrustedTime mTime;
 
     private IConnectivityManager mConnManager;
@@ -160,6 +170,7 @@
     private final Object mRulesLock = new Object();
 
     private boolean mScreenOn;
+    private boolean mBackgroundData;
 
     /** Current policy for network templates. */
     private ArrayList<NetworkPolicy> mNetworkPolicy = Lists.newArrayList();
@@ -188,11 +199,13 @@
     // TODO: keep whitelist of system-critical services that should never have
     // rules enforced, such as system, phone, and radio UIDs.
 
+    // TODO: watch for package added broadcast to catch new UIDs.
+
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
-            IPowerManager powerManager, INetworkStatsService networkStats) {
-        // TODO: move to using cached NtpTrustedTime
-        this(context, activityManager, powerManager, networkStats, new NtpTrustedTime(),
-                getSystemDir());
+            IPowerManager powerManager, INetworkStatsService networkStats,
+            INetworkManagementService networkManagement) {
+        this(context, activityManager, powerManager, networkStats, networkManagement,
+                NtpTrustedTime.getInstance(context), getSystemDir());
     }
 
     private static File getSystemDir() {
@@ -200,17 +213,19 @@
     }
 
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
-            IPowerManager powerManager, INetworkStatsService networkStats, TrustedTime time,
-            File systemDir) {
+            IPowerManager powerManager, INetworkStatsService networkStats,
+            INetworkManagementService networkManagement,
+            TrustedTime time, File systemDir) {
         mContext = checkNotNull(context, "missing context");
         mActivityManager = checkNotNull(activityManager, "missing activityManager");
         mPowerManager = checkNotNull(powerManager, "missing powerManager");
         mNetworkStats = checkNotNull(networkStats, "missing networkStats");
+        mNetworkManagement = checkNotNull(networkManagement, "missing networkManagement");
         mTime = checkNotNull(time, "missing TrustedTime");
 
         mHandlerThread = new HandlerThread(TAG);
         mHandlerThread.start();
-        mHandler = new Handler(mHandlerThread.getLooper());
+        mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
 
         mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
     }
@@ -231,6 +246,7 @@
         }
 
         updateScreenOn();
+        updateBackgroundData(true);
 
         try {
             mActivityManager.registerProcessObserver(mProcessObserver);
@@ -256,11 +272,15 @@
         final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
         mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
 
-        // listen for warning polling events; currently dispatched by
+        // listen for stats update events
         final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
         mContext.registerReceiver(
                 mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
 
+        // listen for changes to background data flag
+        final IntentFilter bgFilter = new IntentFilter(ACTION_BACKGROUND_DATA_SETTING_CHANGED);
+        mContext.registerReceiver(mBgReceiver, bgFilter, CONNECTIVITY_INTERNAL, mHandler);
+
     }
 
     private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
@@ -269,9 +289,6 @@
             // only someone like AMS should only be calling us
             mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
 
-            // skip when UID couldn't have any policy
-            if (!isUidValidForPolicy(mContext, uid)) return;
-
             synchronized (mRulesLock) {
                 // because a uid can have multiple pids running inside, we need to
                 // remember all pid states and summarize foreground at uid level.
@@ -292,9 +309,6 @@
             // only someone like AMS should only be calling us
             mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
 
-            // skip when UID couldn't have any policy
-            if (!isUidValidForPolicy(mContext, uid)) return;
-
             synchronized (mRulesLock) {
                 // clear records and recompute, when they exist
                 final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
@@ -349,6 +363,22 @@
     };
 
     /**
+     * Receiver that watches for
+     * {@link #ACTION_BACKGROUND_DATA_SETTING_CHANGED}.
+     */
+    private BroadcastReceiver mBgReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // on background handler thread, and verified CONNECTIVITY_INTERNAL
+            // permission above.
+
+            synchronized (mRulesLock) {
+                updateBackgroundData(false);
+            }
+        }
+    };
+
+    /**
      * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
      * to show visible notifications as needed.
      */
@@ -561,7 +591,7 @@
         final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
                 : System.currentTimeMillis();
 
-        mMeteredIfaces.clear();
+        final HashSet<String> newMeteredIfaces = Sets.newHashSet();
 
         // apply each policy that we found ifaces for; compute remaining data
         // based on current cycle and historical stats, and push to kernel.
@@ -591,28 +621,30 @@
             if (policy.limitBytes != NetworkPolicy.LIMIT_DISABLED) {
                 // remaining "quota" is based on usage in current cycle
                 final long quota = Math.max(0, policy.limitBytes - total);
-                //kernelSetIfacesQuota(ifaces, quota);
+
+                if (ifaces.length > 1) {
+                    // TODO: switch to shared quota once NMS supports
+                    Slog.w(TAG, "shared quota unsupported; generating rule for each iface");
+                }
 
                 for (String iface : ifaces) {
-                    mMeteredIfaces.add(iface);
+                    removeInterfaceQuota(iface);
+                    setInterfaceQuota(iface, quota);
+                    newMeteredIfaces.add(iface);
                 }
             }
         }
 
-        // dispatch changed rule to existing listeners
-        // TODO: dispatch outside of holding lock
-        final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
-        final int length = mListeners.beginBroadcast();
-        for (int i = 0; i < length; i++) {
-            final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
-            if (listener != null) {
-                try {
-                    listener.onMeteredIfacesChanged(meteredIfaces);
-                } catch (RemoteException e) {
-                }
+        // remove quota on any trailing interfaces
+        for (String iface : mMeteredIfaces) {
+            if (!newMeteredIfaces.contains(iface)) {
+                removeInterfaceQuota(iface);
             }
         }
-        mListeners.finishBroadcast();
+        mMeteredIfaces = newMeteredIfaces;
+
+        final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
+        mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
     }
 
     /**
@@ -804,32 +836,7 @@
 
         mListeners.register(listener);
 
-        synchronized (mRulesLock) {
-            // dispatch any existing rules to new listeners
-            // TODO: dispatch outside of holding lock
-            final int size = mUidRules.size();
-            for (int i = 0; i < size; i++) {
-                final int uid = mUidRules.keyAt(i);
-                final int uidRules = mUidRules.valueAt(i);
-                if (uidRules != RULE_ALLOW_ALL) {
-                    try {
-                        listener.onUidRulesChanged(uid, uidRules);
-                    } catch (RemoteException e) {
-                    }
-                }
-            }
-
-            // dispatch any metered ifaces to new listeners
-            // TODO: dispatch outside of holding lock
-            if (mMeteredIfaces.size() > 0) {
-                final String[] meteredIfaces = mMeteredIfaces.toArray(
-                        new String[mMeteredIfaces.size()]);
-                try {
-                    listener.onMeteredIfacesChanged(meteredIfaces);
-                } catch (RemoteException e) {
-                }
-            }
-        }
+        // TODO: consider dispatching existing rules to new listeners
     }
 
     @Override
@@ -963,6 +970,21 @@
         }
     }
 
+    private void updateBackgroundData(boolean systemReady) {
+        synchronized (mRulesLock) {
+            try {
+                mBackgroundData = mConnManager.getBackgroundDataSetting();
+            } catch (RemoteException e) {
+            }
+            if (systemReady && mBackgroundData) {
+                // typical behavior of background enabled during systemReady;
+                // no need to clear rules for all UIDs.
+            } else {
+                updateRulesForBackgroundDataLocked();
+            }
+        }
+    }
+
     /**
      * Update rules that might be changed by {@link #mScreenOn} value.
      */
@@ -977,9 +999,34 @@
         }
     }
 
-    private void updateRulesForUidLocked(int uid) {
-        if (!isUidValidForPolicy(mContext, uid)) return;
+    /**
+     * Update rules that might be changed by {@link #mBackgroundData} value.
+     */
+    private void updateRulesForBackgroundDataLocked() {
+        // update rules for all installed applications
+        final PackageManager pm = mContext.getPackageManager();
+        final List<ApplicationInfo> apps = pm.getInstalledApplications(0);
+        for (ApplicationInfo app : apps) {
+            updateRulesForUidLocked(app.uid);
+        }
 
+        // and catch system UIDs
+        // TODO: keep in sync with android_filesystem_config.h
+        for (int uid = 1000; uid <= 1025; uid++) {
+            updateRulesForUidLocked(uid);
+        }
+        for (int uid = 2000; uid <= 2002; uid++) {
+            updateRulesForUidLocked(uid);
+        }
+        for (int uid = 3000; uid <= 3007; uid++) {
+            updateRulesForUidLocked(uid);
+        }
+        for (int uid = 9998; uid <= 9999; uid++) {
+            updateRulesForUidLocked(uid);
+        }
+    }
+
+    private void updateRulesForUidLocked(int uid) {
         final int uidPolicy = getUidPolicy(uid);
         final boolean uidForeground = isUidForeground(uid);
 
@@ -989,28 +1036,96 @@
             // uid in background, and policy says to block metered data
             uidRules = RULE_REJECT_METERED;
         }
+        if (!uidForeground && !mBackgroundData) {
+            // uid in background, and global background disabled
+            uidRules = RULE_REJECT_METERED;
+        }
 
         // TODO: only dispatch when rules actually change
 
-        // record rule locally to dispatch to new listeners
-        mUidRules.put(uid, uidRules);
+        if (uidRules == RULE_ALLOW_ALL) {
+            mUidRules.delete(uid);
+        } else {
+            mUidRules.put(uid, uidRules);
+        }
 
         final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0;
-        //kernelSetUidRejectPaid(uid, rejectPaid);
+        setUidNetworkRules(uid, rejectMetered);
 
         // dispatch changed rule to existing listeners
-        // TODO: dispatch outside of holding lock
-        final int length = mListeners.beginBroadcast();
-        for (int i = 0; i < length; i++) {
-            final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
-            if (listener != null) {
-                try {
-                    listener.onUidRulesChanged(uid, uidRules);
-                } catch (RemoteException e) {
+        mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget();
+    }
+
+    private Handler.Callback mHandlerCallback = new Handler.Callback() {
+        /** {@inheritDoc} */
+        public boolean handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_RULES_CHANGED: {
+                    final int uid = msg.arg1;
+                    final int uidRules = msg.arg2;
+                    final int length = mListeners.beginBroadcast();
+                    for (int i = 0; i < length; i++) {
+                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
+                        if (listener != null) {
+                            try {
+                                listener.onUidRulesChanged(uid, uidRules);
+                            } catch (RemoteException e) {
+                            }
+                        }
+                    }
+                    mListeners.finishBroadcast();
+                    return true;
+                }
+                case MSG_METERED_IFACES_CHANGED: {
+                    final String[] meteredIfaces = (String[]) msg.obj;
+                    final int length = mListeners.beginBroadcast();
+                    for (int i = 0; i < length; i++) {
+                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
+                        if (listener != null) {
+                            try {
+                                listener.onMeteredIfacesChanged(meteredIfaces);
+                            } catch (RemoteException e) {
+                            }
+                        }
+                    }
+                    mListeners.finishBroadcast();
+                    return true;
+                }
+                default: {
+                    return false;
                 }
             }
         }
-        mListeners.finishBroadcast();
+    };
+
+    private void setInterfaceQuota(String iface, long quota) {
+        try {
+            mNetworkManagement.setInterfaceQuota(iface, quota);
+        } catch (IllegalStateException e) {
+            Slog.e(TAG, "problem setting interface quota", e);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "problem setting interface quota", e);
+        }
+    }
+
+    private void removeInterfaceQuota(String iface) {
+        try {
+            mNetworkManagement.removeInterfaceQuota(iface);
+        } catch (IllegalStateException e) {
+            Slog.e(TAG, "problem removing interface quota", e);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "problem removing interface quota", e);
+        }
+    }
+
+    private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
+        try {
+            mNetworkManagement.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
+        } catch (IllegalStateException e) {
+            Slog.e(TAG, "problem setting uid rules", e);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "problem setting uid rules", e);
+        }
     }
 
     private String getActiveSubscriberId() {
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 524dd40..b6834f6 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -27,7 +27,6 @@
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
 import static android.net.TrafficStats.UID_REMOVED;
-import static android.provider.Settings.Secure.NETSTATS_ENABLED;
 import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
 import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
 import static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD;
@@ -71,7 +70,6 @@
 import android.util.TrustedTime;
 
 import com.android.internal.os.AtomicFile;
-import com.android.server.NativeDaemonConnectorException;
 import com.google.android.collect.Maps;
 import com.google.android.collect.Sets;
 
@@ -124,8 +122,6 @@
     private PendingIntent mPollIntent;
 
     // TODO: listen for kernel push events through netd instead of polling
-    // TODO: watch for UID uninstall, and transfer stats into single bucket
-
     // TODO: trim empty history objects entirely
 
     private static final long KB_IN_BYTES = 1024;
@@ -136,7 +132,6 @@
      * Settings that can be changed externally.
      */
     public interface NetworkStatsSettings {
-        public boolean getEnabled();
         public long getPollInterval();
         public long getPersistThreshold();
         public long getNetworkBucketDuration();
@@ -178,9 +173,8 @@
 
     public NetworkStatsService(
             Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) {
-        // TODO: move to using cached NtpTrustedTime
-        this(context, networkManager, alarmManager, new NtpTrustedTime(), getSystemDir(),
-                new DefaultNetworkStatsSettings(context));
+        this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context),
+                getSystemDir(), new DefaultNetworkStatsSettings(context));
     }
 
     private static File getSystemDir() {
@@ -209,20 +203,6 @@
     }
 
     public void systemReady() {
-        if (mSettings.getEnabled()) {
-            try {
-                // enable low-level bandwidth stats and control
-                // TODO: consider shipping with this enabled by default
-                mNetworkManager.setBandwidthControlEnabled(true);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "problem talking to netd while enabling bandwidth controls", e);
-            } catch (NativeDaemonConnectorException ndce) {
-                Slog.e(TAG, "problem enabling bandwidth controls", ndce);
-            }
-        } else {
-            Slog.w(TAG, "detailed network stats disabled");
-        }
-
         synchronized (mStatsLock) {
             // read historical network stats from disk, since policy service
             // might need them right away. we delay loading detailed UID stats
@@ -391,6 +371,15 @@
         }
     }
 
+    @Override
+    public void forceUpdate() {
+        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+
+        synchronized (mStatsLock) {
+            performPollLocked(true, false);
+        }
+    }
+
     /**
      * Receiver that watches for {@link IConnectivityManager} to claim network
      * interfaces. Used to associate {@link TelephonyManager#getSubscriberId()}
@@ -506,8 +495,11 @@
         try {
             networkSnapshot = mNetworkManager.getNetworkStatsSummary();
             uidSnapshot = detailedPoll ? mNetworkManager.getNetworkStatsDetail() : null;
+        } catch (IllegalStateException e) {
+            Slog.w(TAG, "problem reading network stats: " + e);
+            return;
         } catch (RemoteException e) {
-            Slog.w(TAG, "problem reading network stats");
+            Slog.w(TAG, "problem reading network stats: " + e);
             return;
         }
 
@@ -904,6 +896,8 @@
             argSet.add(arg);
         }
 
+        final boolean fullHistory = argSet.contains("full");
+
         synchronized (mStatsLock) {
             // TODO: remove this testing code, since it corrupts stats
             if (argSet.contains("generate")) {
@@ -929,7 +923,7 @@
             for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
                 final NetworkStatsHistory history = mNetworkStats.get(ident);
                 pw.print("  ident="); pw.println(ident.toString());
-                history.dump("  ", pw);
+                history.dump("  ", pw, fullHistory);
             }
 
             if (argSet.contains("detail")) {
@@ -949,7 +943,7 @@
                         final NetworkStatsHistory history = uidStats.valueAt(i);
                         pw.print("    UID="); pw.print(uid);
                         pw.print(" tag="); pw.println(tag);
-                        history.dump("    ", pw);
+                        history.dump("    ", pw, fullHistory);
                     }
                 }
             }
@@ -1057,13 +1051,6 @@
             return Settings.Secure.getLong(mResolver, name, def);
         }
 
-        public boolean getEnabled() {
-            if (!new File("/proc/net/xt_qtaguid/ctrl").exists()) {
-                Slog.w(TAG, "kernel does not support bandwidth control");
-                return false;
-            }
-            return Settings.Secure.getInt(mResolver, NETSTATS_ENABLED, 1) != 0;
-        }
         public long getPollInterval() {
             return getSecureLong(NETSTATS_POLL_INTERVAL, 15 * MINUTE_IN_MILLIS);
         }
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index d10aa97..11ccd60 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -307,7 +307,7 @@
     }
 
     public int getSizeInfo(String pkgName, String apkPath, String fwdLockApkPath,
-            PackageStats pStats) {
+            String asecPath, PackageStats pStats) {
         StringBuilder builder = new StringBuilder("getsize");
         builder.append(' ');
         builder.append(pkgName);
@@ -315,17 +315,20 @@
         builder.append(apkPath);
         builder.append(' ');
         builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
+        builder.append(' ');
+        builder.append(asecPath != null ? asecPath : "!");
 
         String s = transaction(builder.toString());
         String res[] = s.split(" ");
 
-        if ((res == null) || (res.length != 4)) {
+        if ((res == null) || (res.length != 5)) {
             return -1;
         }
         try {
             pStats.codeSize = Long.parseLong(res[1]);
             pStats.dataSize = Long.parseLong(res[2]);
             pStats.cacheSize = Long.parseLong(res[3]);
+            pStats.externalCodeSize = Long.parseLong(res[4]);
             return Integer.parseInt(res[0]);
         } catch (NumberFormatException e) {
             return -1;
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 5a9dae9..d6a15e6 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -75,6 +75,7 @@
 import android.os.Environment;
 import android.os.FileObserver;
 import android.os.FileUtils;
+import android.os.FileUtils.FileStatus;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -156,7 +157,6 @@
     private static final int RADIO_UID = Process.PHONE_UID;
     private static final int LOG_UID = Process.LOG_UID;
     private static final int NFC_UID = Process.NFC_UID;
-    private static final int KEYCHAIN_UID = Process.KEYCHAIN_UID;
     static final int FIRST_APPLICATION_UID =
         Process.FIRST_APPLICATION_UID;
     static final int MAX_APPLICATION_UIDS = 1000;
@@ -760,10 +760,6 @@
                 MULTIPLE_APPLICATION_UIDS
                         ? NFC_UID : FIRST_APPLICATION_UID,
                 ApplicationInfo.FLAG_SYSTEM);
-        mSettings.addSharedUserLPw("android.uid.keychain",
-                MULTIPLE_APPLICATION_UIDS
-                        ? KEYCHAIN_UID : FIRST_APPLICATION_UID,
-                ApplicationInfo.FLAG_SYSTEM);
 
         String separateProcesses = SystemProperties.get("debug.separate_processes");
         if (separateProcesses != null && separateProcesses.length() > 0) {
@@ -782,16 +778,7 @@
             mSeparateProcesses = null;
         }
 
-        Installer installer = new Installer();
-        // Little hacky thing to check if installd is here, to determine
-        // whether we are running on the simulator and thus need to take
-        // care of building the /data file structure ourself.
-        // (apparently the sim now has a working installer)
-        if (installer.ping() && Process.supportsProcesses()) {
-            mInstaller = installer;
-        } else {
-            mInstaller = null;
-        }
+        mInstaller = new Installer();
 
         WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
         Display d = wm.getDefaultDisplay();
@@ -810,17 +797,6 @@
 
             mUserManager = new UserManager(mInstaller, mUserAppDataDir);
 
-            if (mInstaller == null) {
-                // Make sure these dirs exist, when we are running in
-                // the simulator.
-                // Make a wide-open directory for random misc stuff.
-                File miscDir = new File(dataDir, "misc");
-                miscDir.mkdirs();
-                mAppDataDir.mkdirs();
-                mUserAppDataDir.mkdirs();
-                mDrmAppPrivateInstallDir.mkdirs();
-            }
-
             readPermissions();
 
             mRestoredSettings = mSettings.readLPw();
@@ -842,104 +818,102 @@
             mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
             mDalvikCacheDir = new File(dataDir, "dalvik-cache");
 
-            if (mInstaller != null) {
-                boolean didDexOpt = false;
+            boolean didDexOpt = false;
 
-                /**
-                 * Out of paranoia, ensure that everything in the boot class
-                 * path has been dexed.
-                 */
-                String bootClassPath = System.getProperty("java.boot.class.path");
-                if (bootClassPath != null) {
-                    String[] paths = splitString(bootClassPath, ':');
-                    for (int i=0; i<paths.length; i++) {
-                        try {
-                            if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
-                                libFiles.add(paths[i]);
-                                mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
-                                didDexOpt = true;
-                            }
-                        } catch (FileNotFoundException e) {
-                            Slog.w(TAG, "Boot class path not found: " + paths[i]);
-                        } catch (IOException e) {
-                            Slog.w(TAG, "Exception reading boot class path: " + paths[i], e);
+            /**
+             * Out of paranoia, ensure that everything in the boot class
+             * path has been dexed.
+             */
+            String bootClassPath = System.getProperty("java.boot.class.path");
+            if (bootClassPath != null) {
+                String[] paths = splitString(bootClassPath, ':');
+                for (int i=0; i<paths.length; i++) {
+                    try {
+                        if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
+                            libFiles.add(paths[i]);
+                            mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
+                            didDexOpt = true;
                         }
-                    }
-                } else {
-                    Slog.w(TAG, "No BOOTCLASSPATH found!");
-                }
-
-                /**
-                 * Also ensure all external libraries have had dexopt run on them.
-                 */
-                if (mSharedLibraries.size() > 0) {
-                    Iterator<String> libs = mSharedLibraries.values().iterator();
-                    while (libs.hasNext()) {
-                        String lib = libs.next();
-                        try {
-                            if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
-                                libFiles.add(lib);
-                                mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
-                                didDexOpt = true;
-                            }
-                        } catch (FileNotFoundException e) {
-                            Slog.w(TAG, "Library not found: " + lib);
-                        } catch (IOException e) {
-                            Slog.w(TAG, "Exception reading library: " + lib, e);
-                        }
+                    } catch (FileNotFoundException e) {
+                        Slog.w(TAG, "Boot class path not found: " + paths[i]);
+                    } catch (IOException e) {
+                        Slog.w(TAG, "Exception reading boot class path: " + paths[i], e);
                     }
                 }
+            } else {
+                Slog.w(TAG, "No BOOTCLASSPATH found!");
+            }
 
-                // Gross hack for now: we know this file doesn't contain any
-                // code, so don't dexopt it to avoid the resulting log spew.
-                libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
-
-                /**
-                 * And there are a number of commands implemented in Java, which
-                 * we currently need to do the dexopt on so that they can be
-                 * run from a non-root shell.
-                 */
-                String[] frameworkFiles = mFrameworkDir.list();
-                if (frameworkFiles != null) {
-                    for (int i=0; i<frameworkFiles.length; i++) {
-                        File libPath = new File(mFrameworkDir, frameworkFiles[i]);
-                        String path = libPath.getPath();
-                        // Skip the file if we alrady did it.
-                        if (libFiles.contains(path)) {
-                            continue;
+            /**
+             * Also ensure all external libraries have had dexopt run on them.
+             */
+            if (mSharedLibraries.size() > 0) {
+                Iterator<String> libs = mSharedLibraries.values().iterator();
+                while (libs.hasNext()) {
+                    String lib = libs.next();
+                    try {
+                        if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
+                            libFiles.add(lib);
+                            mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
+                            didDexOpt = true;
                         }
-                        // Skip the file if it is not a type we want to dexopt.
-                        if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
-                            continue;
-                        }
-                        try {
-                            if (dalvik.system.DexFile.isDexOptNeeded(path)) {
-                                mInstaller.dexopt(path, Process.SYSTEM_UID, true);
-                                didDexOpt = true;
-                            }
-                        } catch (FileNotFoundException e) {
-                            Slog.w(TAG, "Jar not found: " + path);
-                        } catch (IOException e) {
-                            Slog.w(TAG, "Exception reading jar: " + path, e);
-                        }
+                    } catch (FileNotFoundException e) {
+                        Slog.w(TAG, "Library not found: " + lib);
+                    } catch (IOException e) {
+                        Slog.w(TAG, "Exception reading library: " + lib, e);
                     }
                 }
+            }
 
-                if (didDexOpt) {
-                    // If we had to do a dexopt of one of the previous
-                    // things, then something on the system has changed.
-                    // Consider this significant, and wipe away all other
-                    // existing dexopt files to ensure we don't leave any
-                    // dangling around.
-                    String[] files = mDalvikCacheDir.list();
-                    if (files != null) {
-                        for (int i=0; i<files.length; i++) {
-                            String fn = files[i];
-                            if (fn.startsWith("data@app@")
-                                    || fn.startsWith("data@app-private@")) {
-                                Slog.i(TAG, "Pruning dalvik file: " + fn);
-                                (new File(mDalvikCacheDir, fn)).delete();
-                            }
+            // Gross hack for now: we know this file doesn't contain any
+            // code, so don't dexopt it to avoid the resulting log spew.
+            libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
+
+            /**
+             * And there are a number of commands implemented in Java, which
+             * we currently need to do the dexopt on so that they can be
+             * run from a non-root shell.
+             */
+            String[] frameworkFiles = mFrameworkDir.list();
+            if (frameworkFiles != null) {
+                for (int i=0; i<frameworkFiles.length; i++) {
+                    File libPath = new File(mFrameworkDir, frameworkFiles[i]);
+                    String path = libPath.getPath();
+                    // Skip the file if we alrady did it.
+                    if (libFiles.contains(path)) {
+                        continue;
+                    }
+                    // Skip the file if it is not a type we want to dexopt.
+                    if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
+                        continue;
+                    }
+                    try {
+                        if (dalvik.system.DexFile.isDexOptNeeded(path)) {
+                            mInstaller.dexopt(path, Process.SYSTEM_UID, true);
+                            didDexOpt = true;
+                        }
+                    } catch (FileNotFoundException e) {
+                        Slog.w(TAG, "Jar not found: " + path);
+                    } catch (IOException e) {
+                        Slog.w(TAG, "Exception reading jar: " + path, e);
+                    }
+                }
+            }
+
+            if (didDexOpt) {
+                // If we had to do a dexopt of one of the previous
+                // things, then something on the system has changed.
+                // Consider this significant, and wipe away all other
+                // existing dexopt files to ensure we don't leave any
+                // dangling around.
+                String[] files = mDalvikCacheDir.list();
+                if (files != null) {
+                    for (int i=0; i<files.length; i++) {
+                        String fn = files[i];
+                        if (fn.startsWith("data@app@")
+                                || fn.startsWith("data@app-private@")) {
+                            Slog.i(TAG, "Pruning dalvik file: " + fn);
+                            (new File(mDalvikCacheDir, fn)).delete();
                         }
                     }
                 }
@@ -969,11 +943,9 @@
             scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
 
-            if (mInstaller != null) {
-                if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
-                mInstaller.moveFiles();
-            }
-            
+            if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
+            mInstaller.moveFiles();
+
             // Prune any system packages that no longer exist.
             Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
             while (psit.hasNext()) {
@@ -985,19 +957,12 @@
                     String msg = "System package " + ps.name
                             + " no longer exists; wiping its data";
                     reportSettingsProblem(Log.WARN, msg);
-                    if (mInstaller != null) {
-                        mInstaller.remove(ps.name, 0);
-                        mUserManager.removePackageForAllUsers(ps.name);
-                    }
+                    mInstaller.remove(ps.name, 0);
+                    mUserManager.removePackageForAllUsers(ps.name);
                 }
             }
             
             mAppInstallDir = new File(dataDir, "app");
-            if (mInstaller == null) {
-                // Make sure these dirs exist, when we are running in
-                // the simulator.
-                mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
-            }
             //look for any incomplete package installations
             ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
             //clean up list
@@ -1071,19 +1036,12 @@
 
     void cleanupInstallFailedPackage(PackageSetting ps) {
         Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
-        if (mInstaller != null) {
-            int retCode = mInstaller.remove(ps.name, 0);
-            if (retCode < 0) {
-                Slog.w(TAG, "Couldn't remove app data directory for package: "
-                           + ps.name + ", retcode=" + retCode);
-            } else {
-                mUserManager.removePackageForAllUsers(ps.name);
-            }
+        int retCode = mInstaller.remove(ps.name, 0);
+        if (retCode < 0) {
+            Slog.w(TAG, "Couldn't remove app data directory for package: "
+                       + ps.name + ", retcode=" + retCode);
         } else {
-            //for emulator
-            PackageParser.Package pkg = mPackages.get(ps.name);
-            File dataDir = new File(pkg.applicationInfo.dataDir);
-            dataDir.delete();
+            mUserManager.removePackageForAllUsers(ps.name);
         }
         if (ps.codePath != null) {
             if (!ps.codePath.delete()) {
@@ -1566,12 +1524,10 @@
             public void run() {
                 mHandler.removeCallbacks(this);
                 int retCode = -1;
-                if (mInstaller != null) {
-                    retCode = mInstaller.freeCache(freeStorageSize);
-                    if (retCode < 0) {
-                        Slog.w(TAG, "Couldn't clear application caches");
-                    }
-                } //end if mInstaller
+                retCode = mInstaller.freeCache(freeStorageSize);
+                if (retCode < 0) {
+                    Slog.w(TAG, "Couldn't clear application caches");
+                }
                 if (observer != null) {
                     try {
                         observer.onRemoveCompleted(null, (retCode >= 0));
@@ -1591,11 +1547,9 @@
             public void run() {
                 mHandler.removeCallbacks(this);
                 int retCode = -1;
-                if (mInstaller != null) {
-                    retCode = mInstaller.freeCache(freeStorageSize);
-                    if (retCode < 0) {
-                        Slog.w(TAG, "Couldn't clear application caches");
-                    }
+                retCode = mInstaller.freeCache(freeStorageSize);
+                if (retCode < 0) {
+                    Slog.w(TAG, "Couldn't clear application caches");
                 }
                 if(pi != null) {
                     try {
@@ -2854,7 +2808,7 @@
 
     private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
         boolean performed = false;
-        if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
+        if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
             String path = pkg.mScanPath;
             int ret = 0;
             try {
@@ -3239,42 +3193,39 @@
                 mOutPermissions[1] = 0;
                 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
 
-                // If we have mismatched owners for the data path, we have a
-                // problem (unless we're running in the simulator.)
-                if (mOutPermissions[1] != pkg.applicationInfo.uid && Process.supportsProcesses()) {
+                // If we have mismatched owners for the data path, we have a problem.
+                if (mOutPermissions[1] != pkg.applicationInfo.uid) {
                     boolean recovered = false;
                     if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
                         // If this is a system app, we can at least delete its
                         // current data so the application will still work.
-                        if (mInstaller != null) {
-                            int ret = mInstaller.remove(pkgName, 0);
-                            if (ret >= 0) {
-                                // TODO: Kill the processes first
-                                // Remove the data directories for all users
-                                mUserManager.removePackageForAllUsers(pkgName);
-                                // Old data gone!
-                                String msg = "System package " + pkg.packageName
-                                        + " has changed from uid: "
-                                        + mOutPermissions[1] + " to "
-                                        + pkg.applicationInfo.uid + "; old data erased";
-                                reportSettingsProblem(Log.WARN, msg);
-                                recovered = true;
+                        int ret = mInstaller.remove(pkgName, 0);
+                        if (ret >= 0) {
+                            // TODO: Kill the processes first
+                            // Remove the data directories for all users
+                            mUserManager.removePackageForAllUsers(pkgName);
+                            // Old data gone!
+                            String msg = "System package " + pkg.packageName
+                                    + " has changed from uid: "
+                                    + mOutPermissions[1] + " to "
+                                    + pkg.applicationInfo.uid + "; old data erased";
+                            reportSettingsProblem(Log.WARN, msg);
+                            recovered = true;
 
-                                // And now re-install the app.
-                                ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
-                                        pkg.applicationInfo.uid);
-                                if (ret == -1) {
-                                    // Ack should not happen!
-                                    msg = "System package " + pkg.packageName
-                                            + " could not have data directory re-created after delete.";
-                                    reportSettingsProblem(Log.WARN, msg);
-                                    mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                                    return null;
-                                }
-                                // Create data directories for all users
-                                mUserManager.installPackageForAllUsers(pkgName,
-                                        pkg.applicationInfo.uid);
+                            // And now re-install the app.
+                            ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
+                                    pkg.applicationInfo.uid);
+                            if (ret == -1) {
+                                // Ack should not happen!
+                                msg = "System package " + pkg.packageName
+                                        + " could not have data directory re-created after delete.";
+                                reportSettingsProblem(Log.WARN, msg);
+                                mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+                                return null;
                             }
+                            // Create data directories for all users
+                            mUserManager.installPackageForAllUsers(pkgName,
+                                    pkg.applicationInfo.uid);
                         }
                         if (!recovered) {
                             mHasSystemUidErrors = true;
@@ -3307,25 +3258,16 @@
                         Log.v(TAG, "Want this data dir: " + dataPath);
                 }
                 //invoke installer to do the actual installation
-                if (mInstaller != null) {
-                    int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
-                            pkg.applicationInfo.uid);
-                    if (ret < 0) {
-                        // Error from installer
-                        mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                        return null;
-                    }
-                    // Create data directories for all users
-                    mUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);
-                } else {
-                    dataPath.mkdirs();
-                    if (dataPath.exists()) {
-                        FileUtils.setPermissions(
-                            dataPath.toString(),
-                            FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
-                            pkg.applicationInfo.uid, pkg.applicationInfo.uid);
-                    }
+                int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
+                        pkg.applicationInfo.uid);
+                if (ret < 0) {
+                    // Error from installer
+                    mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+                    return null;
                 }
+                // Create data directories for all users
+                mUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);
+
                 if (dataPath.exists()) {
                     pkg.applicationInfo.dataDir = dataPath.getPath();
                 } else {
@@ -3356,65 +3298,62 @@
             pkgSetting.uidError = uidError;
         }
 
-        // If we're running in the simulator, we don't need to unpack anything.
-        if (mInstaller != null) {
-            String path = scanFile.getPath();
-            /* Note: We don't want to unpack the native binaries for
-             *        system applications, unless they have been updated
-             *        (the binaries are already under /system/lib).
-             *        Also, don't unpack libs for apps on the external card
-             *        since they should have their libraries in the ASEC
-             *        container already.
-             *
-             *        In other words, we're going to unpack the binaries
-             *        only for non-system apps and system app upgrades.
-             */
-            if (pkg.applicationInfo.nativeLibraryDir != null) {
-                try {
-                    final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
-                    final String dataPathString = dataPath.getCanonicalFile().getPath();
+        String path = scanFile.getPath();
+        /* Note: We don't want to unpack the native binaries for
+         *        system applications, unless they have been updated
+         *        (the binaries are already under /system/lib).
+         *        Also, don't unpack libs for apps on the external card
+         *        since they should have their libraries in the ASEC
+         *        container already.
+         *
+         *        In other words, we're going to unpack the binaries
+         *        only for non-system apps and system app upgrades.
+         */
+        if (pkg.applicationInfo.nativeLibraryDir != null) {
+            try {
+                final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
+                final String dataPathString = dataPath.getCanonicalFile().getPath();
 
-                    if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
-                        /*
-                         * Upgrading from a previous version of the OS sometimes
-                         * leaves native libraries in the /data/data/<app>/lib
-                         * directory for system apps even when they shouldn't be.
-                         * Recent changes in the JNI library search path
-                         * necessitates we remove those to match previous behavior.
-                         */
-                        if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
-                            Log.i(TAG, "removed obsolete native libraries for system package "
-                                    + path);
-                        }
-                    } else if (nativeLibraryDir.getCanonicalFile().getParent()
-                            .equals(dataPathString)) {
-                        /*
-                         * If this is an internal application or our
-                         * nativeLibraryPath points to our data directory, unpack
-                         * the libraries. The native library path pointing to the
-                         * data directory for an application in an ASEC container
-                         * can happen for older apps that existed before an OTA to
-                         * Gingerbread.
-                         */
-                        Slog.i(TAG, "Unpacking native libraries for " + path);
-                        mInstaller.unlinkNativeLibraryDirectory(dataPathString);
-                        NativeLibraryHelper.copyNativeBinariesLI(scanFile, nativeLibraryDir);
-                    } else {
-                        Slog.i(TAG, "Linking native library dir for " + path);
-                        mInstaller.linkNativeLibraryDirectory(dataPathString,
-                                pkg.applicationInfo.nativeLibraryDir);
+                if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
+                    /*
+                     * Upgrading from a previous version of the OS sometimes
+                     * leaves native libraries in the /data/data/<app>/lib
+                     * directory for system apps even when they shouldn't be.
+                     * Recent changes in the JNI library search path
+                     * necessitates we remove those to match previous behavior.
+                     */
+                    if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
+                        Log.i(TAG, "removed obsolete native libraries for system package "
+                                + path);
                     }
-                } catch (IOException ioe) {
-                    Log.e(TAG, "Unable to get canonical file " + ioe.toString());
+                } else if (nativeLibraryDir.getCanonicalFile().getParent()
+                        .equals(dataPathString)) {
+                    /*
+                     * If this is an internal application or our
+                     * nativeLibraryPath points to our data directory, unpack
+                     * the libraries. The native library path pointing to the
+                     * data directory for an application in an ASEC container
+                     * can happen for older apps that existed before an OTA to
+                     * Gingerbread.
+                     */
+                    Slog.i(TAG, "Unpacking native libraries for " + path);
+                    mInstaller.unlinkNativeLibraryDirectory(dataPathString);
+                    NativeLibraryHelper.copyNativeBinariesLI(scanFile, nativeLibraryDir);
+                } else {
+                    Slog.i(TAG, "Linking native library dir for " + path);
+                    mInstaller.linkNativeLibraryDirectory(dataPathString,
+                            pkg.applicationInfo.nativeLibraryDir);
                 }
+            } catch (IOException ioe) {
+                Log.e(TAG, "Unable to get canonical file " + ioe.toString());
             }
-            pkg.mScanPath = path;
+        }
+        pkg.mScanPath = path;
 
-            if ((scanMode&SCAN_NO_DEX) == 0) {
-                if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
-                    mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
-                    return null;
-                }
+        if ((scanMode&SCAN_NO_DEX) == 0) {
+            if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
+                mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
+                return null;
             }
         }
 
@@ -4887,8 +4826,7 @@
 
         private final IPackageStatsObserver mObserver;
 
-        public MeasureParams(PackageStats stats, boolean success,
-                IPackageStatsObserver observer) {
+        public MeasureParams(PackageStats stats, boolean success, IPackageStatsObserver observer) {
             mObserver = observer;
             mStats = stats;
             mSuccess = success;
@@ -5439,7 +5377,7 @@
 
         void cleanUpResourcesLI() {
             String sourceDir = getCodePath();
-            if (cleanUp() && mInstaller != null) {
+            if (cleanUp()) {
                 int retCode = mInstaller.rmdex(sourceDir);
                 if (retCode < 0) {
                     Slog.w(TAG, "Couldn't remove dex file for package: "
@@ -5480,6 +5418,17 @@
         }
     }
 
+    /**
+     * Extract the MountService "container ID" from the full code path of an
+     * .apk.
+     */
+    static String cidFromCodePath(String fullCodePath) {
+        int eidx = fullCodePath.lastIndexOf("/");
+        String subStr1 = fullCodePath.substring(0, eidx);
+        int sidx = subStr1.lastIndexOf("/");
+        return subStr1.substring(sidx+1, eidx);
+    }
+
     class SdInstallArgs extends InstallArgs {
         static final String RES_FILE_NAME = "pkg.apk";
 
@@ -5656,14 +5605,12 @@
         void cleanUpResourcesLI() {
             String sourceFile = getCodePath();
             // Remove dex file
-            if (mInstaller != null) {
-                int retCode = mInstaller.rmdex(sourceFile);
-                if (retCode < 0) {
-                    Slog.w(TAG, "Couldn't remove dex file for package: "
-                            + " at location "
-                            + sourceFile.toString() + ", retcode=" + retCode);
-                    // we don't consider this to be a failure of the core package deletion
-                }
+            int retCode = mInstaller.rmdex(sourceFile);
+            if (retCode < 0) {
+                Slog.w(TAG, "Couldn't remove dex file for package: "
+                        + " at location "
+                        + sourceFile.toString() + ", retcode=" + retCode);
+                // we don't consider this to be a failure of the core package deletion
             }
             cleanUp();
         }
@@ -6071,9 +6018,7 @@
         }
         if((res.returnCode = setPermissionsLI(newPackage))
                 != PackageManager.INSTALL_SUCCEEDED) {
-            if (mInstaller != null) {
-                mInstaller.rmdex(newPackage.mScanPath);
-            }
+            mInstaller.rmdex(newPackage.mScanPath);
             return;
         } else {
             Log.d(TAG, "New package installed in " + newPackage.mPath);
@@ -6201,15 +6146,8 @@
             } finally {
                 //TODO clean up the extracted public files
             }
-            if (mInstaller != null) {
-                retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
-                        newPackage.applicationInfo.uid);
-            } else {
-                final int filePermissions =
-                        FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
-                retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
-                                                   newPackage.applicationInfo.uid);
-            }
+            retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
+                    newPackage.applicationInfo.uid);
         } else {
             // The permissions on the resource file was set when it was copied for
             // non forward locked apps and apps on sdcard
@@ -6472,25 +6410,14 @@
             deletedPs = mSettings.mPackages.get(packageName);
         }
         if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
-            if (mInstaller != null) {
-                int retCode = mInstaller.remove(packageName, 0);
-                if (retCode < 0) {
-                    Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
-                               + packageName + ", retcode=" + retCode);
-                    // we don't consider this to be a failure of the core package deletion
-                } else {
-                    // TODO: Kill the processes first
-                    mUserManager.removePackageForAllUsers(packageName);
-                }
+            int retCode = mInstaller.remove(packageName, 0);
+            if (retCode < 0) {
+                Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
+                           + packageName + ", retcode=" + retCode);
+                // we don't consider this to be a failure of the core package deletion
             } else {
-                // for simulator
-                File dataDir;
-                // reader
-                synchronized (mPackages) {
-                    PackageParser.Package pkg = mPackages.get(packageName);
-                    dataDir = new File(pkg.applicationInfo.dataDir);
-                }
-                dataDir.delete();
+                // TODO: Kill the processes first
+                mUserManager.removePackageForAllUsers(packageName);
             }
             schedulePackageCleaning(packageName);
         }
@@ -6739,13 +6666,11 @@
                 return false;
             }
         }
-        if (mInstaller != null) {
-            int retCode = mInstaller.clearUserData(packageName, 0); // TODO - correct userId
-            if (retCode < 0) {
-                Slog.w(TAG, "Couldn't remove cache files for package: "
-                        + packageName);
-                return false;
-            }
+        int retCode = mInstaller.clearUserData(packageName, 0); // TODO - correct userId
+        if (retCode < 0) {
+            Slog.w(TAG, "Couldn't remove cache files for package: "
+                    + packageName);
+            return false;
         }
         return true;
     }
@@ -6791,13 +6716,11 @@
             Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
             return false;
         }
-        if (mInstaller != null) {
-            int retCode = mInstaller.deleteCacheFiles(packageName);
-            if (retCode < 0) {
-                Slog.w(TAG, "Couldn't remove cache files for package: "
-                           + packageName);
-                return false;
-            }
+        int retCode = mInstaller.deleteCacheFiles(packageName);
+        if (retCode < 0) {
+            Slog.w(TAG, "Couldn't remove cache files for package: "
+                       + packageName);
+            return false;
         }
         return true;
     }
@@ -6831,6 +6754,7 @@
         }
         PackageParser.Package p;
         boolean dataOnly = false;
+        String asecPath = null;
         synchronized (mPackages) {
             p = mPackages.get(packageName);
             if(p == null) {
@@ -6842,6 +6766,12 @@
                 }
                 p = ps.pkg;
             }
+            if (p != null && isExternal(p)) {
+                String secureContainerId = cidFromCodePath(p.applicationInfo.sourceDir);
+                if (secureContainerId != null) {
+                    asecPath = PackageHelper.getSdFilesystem(secureContainerId);
+                }
+            }
         }
         String publicSrcDir = null;
         if(!dataOnly) {
@@ -6850,16 +6780,15 @@
                 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
                 return false;
             }
-            publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
-        }
-        if (mInstaller != null) {
-            int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir, pStats);
-            if (res < 0) {
-                return false;
-            } else {
-                return true;
+            if (isForwardLocked(p)) {
+                publicSrcDir = applicationInfo.publicSourceDir;
             }
         }
+        int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir,
+                asecPath, pStats);
+        if (res < 0) {
+            return false;
+        }
         return true;
     }
 
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index 918f1b6..1ab570a 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -45,7 +45,6 @@
 import android.os.SystemProperties;
 import android.os.UEventObserver;
 import android.provider.Settings;
-import android.util.Log;
 import android.util.Slog;
 
 import java.io.File;
@@ -62,7 +61,7 @@
 public class UsbDeviceManager {
 
     private static final String TAG = UsbDeviceManager.class.getSimpleName();
-    private static final boolean LOG = false;
+    private static final boolean DEBUG = false;
 
     private static final String USB_STATE_MATCH =
             "DEVPATH=/devices/virtual/android_usb/android0";
@@ -73,7 +72,9 @@
     private static final String STATE_PATH =
             "/sys/class/android_usb/android0/state";
     private static final String MASS_STORAGE_FILE_PATH =
-            "/sys/class/android_usb/f_mass_storage/lun/file";
+            "/sys/class/android_usb/android0/f_mass_storage/lun/file";
+    private static final String RNDIS_ETH_ADDR_PATH =
+            "/sys/class/android_usb/android0/f_rndis/ethaddr";
 
     private static final int MSG_UPDATE_STATE = 0;
     private static final int MSG_ENABLE_ADB = 1;
@@ -93,18 +94,9 @@
     private final UsbSettingsManager mSettingsManager;
     private NotificationManager mNotificationManager;
     private final boolean mHasUsbAccessory;
-
-    // for USB connected notification
-    private boolean mUsbNotificationShown;
     private boolean mUseUsbNotification;
-    private Notification mUsbNotification;
-
-    // for adb connected notification
-    private boolean mAdbNotificationShown;
-    private Notification mAdbNotification;
     private boolean mAdbEnabled;
 
-
     private class AdbSettingsObserver extends ContentObserver {
         public AdbSettingsObserver() {
             super(null);
@@ -117,115 +109,20 @@
         }
     }
 
-    private void updateUsbNotification(boolean connected) {
-        if (mNotificationManager == null || !mUseUsbNotification) return;
-        if (connected) {
-            if (!mUsbNotificationShown) {
-                Resources r = mContext.getResources();
-                CharSequence title = r.getText(
-                        com.android.internal.R.string.usb_preferences_notification_title);
-                CharSequence message = r.getText(
-                        com.android.internal.R.string.usb_preferece_notification_message);
-
-                if (mUsbNotification == null) {
-                    mUsbNotification = new Notification();
-                    mUsbNotification.icon = com.android.internal.R.drawable.stat_sys_data_usb;
-                    mUsbNotification.when = 0;
-                    mUsbNotification.flags = Notification.FLAG_ONGOING_EVENT;
-                    mUsbNotification.tickerText = title;
-                    mUsbNotification.defaults = 0; // please be quiet
-                    mUsbNotification.sound = null;
-                    mUsbNotification.vibrate = null;
-                }
-
-                Intent intent = new Intent();
-                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                        Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-                intent.setClassName("com.android.systemui",
-                        "com.android.systemui.usb.UsbPreferenceActivity");
-                PendingIntent pi = PendingIntent.getActivity(mContext, 0,
-                        intent, 0);
-
-                mUsbNotification.setLatestEventInfo(mContext, title, message, pi);
-
-                mUsbNotificationShown = true;
-                mNotificationManager.notify(
-                        com.android.internal.R.string.usb_preferences_notification_title,
-                        mUsbNotification);
-            }
-
-        } else if (mUsbNotificationShown) {
-            mUsbNotificationShown = false;
-            mNotificationManager.cancel(
-                    com.android.internal.R.string.usb_preferences_notification_title);
-        }
-    }
-
-    private void updateAdbNotification(boolean adbEnabled) {
-        if (mNotificationManager == null) return;
-        if (adbEnabled) {
-            if ("0".equals(SystemProperties.get("persist.adb.notify"))) return;
-
-            if (!mAdbNotificationShown) {
-                Resources r = mContext.getResources();
-                CharSequence title = r.getText(
-                        com.android.internal.R.string.adb_active_notification_title);
-                CharSequence message = r.getText(
-                        com.android.internal.R.string.adb_active_notification_message);
-
-                if (mAdbNotification == null) {
-                    mAdbNotification = new Notification();
-                    mAdbNotification.icon = com.android.internal.R.drawable.stat_sys_adb;
-                    mAdbNotification.when = 0;
-                    mAdbNotification.flags = Notification.FLAG_ONGOING_EVENT;
-                    mAdbNotification.tickerText = title;
-                    mAdbNotification.defaults = 0; // please be quiet
-                    mAdbNotification.sound = null;
-                    mAdbNotification.vibrate = null;
-                }
-
-                Intent intent = new Intent(
-                        Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
-                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                        Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-                // Note: we are hard-coding the component because this is
-                // an important security UI that we don't want anyone
-                // intercepting.
-                intent.setComponent(new ComponentName("com.android.settings",
-                        "com.android.settings.DevelopmentSettings"));
-                PendingIntent pi = PendingIntent.getActivity(mContext, 0,
-                        intent, 0);
-
-                mAdbNotification.setLatestEventInfo(mContext, title, message, pi);
-
-                mAdbNotificationShown = true;
-                mNotificationManager.notify(
-                        com.android.internal.R.string.adb_active_notification_title,
-                        mAdbNotification);
-            }
-        } else if (mAdbNotificationShown) {
-            mAdbNotificationShown = false;
-            mNotificationManager.cancel(
-                    com.android.internal.R.string.adb_active_notification_title);
-        }
-    }
-
     /*
      * Listens for uevent messages from the kernel to monitor the USB state
      */
     private final UEventObserver mUEventObserver = new UEventObserver() {
         @Override
         public void onUEvent(UEventObserver.UEvent event) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Slog.v(TAG, "USB UEVENT: " + event.toString());
-            }
+            if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());
 
             String state = event.get("USB_STATE");
             String accessory = event.get("ACCESSORY");
             if (state != null) {
                 mHandler.updateState(state);
             } else if ("START".equals(accessory)) {
-                Slog.d(TAG, "got accessory start");
+                if (DEBUG) Slog.d(TAG, "got accessory start");
                 setCurrentFunction(UsbManager.USB_FUNCTION_ACCESSORY, false);
             }
         }
@@ -237,6 +134,7 @@
         mSettingsManager = settingsManager;
         PackageManager pm = mContext.getPackageManager();
         mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
+        initRndisAddress();
 
         // create a thread for our Handler
         HandlerThread thread = new HandlerThread("UsbDeviceManager",
@@ -271,6 +169,29 @@
         mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
     }
 
+    private static void initRndisAddress() {
+        // configure RNDIS ethernet address based on our serial number using the same algorithm
+        // we had been previously using in kernel board files
+        final int ETH_ALEN = 6;
+        int address[] = new int[ETH_ALEN];
+        // first byte is 0x02 to signify a locally administered address
+        address[0] = 0x02;
+
+        String serial = SystemProperties.get("ro.serialno", "1234567890ABCDEF");
+        int serialLength = serial.length();
+        // XOR the USB serial across the remaining 5 bytes
+        for (int i = 0; i < serialLength; i++) {
+            address[i % (ETH_ALEN - 1) + 1] ^= (int)serial.charAt(i);
+        }
+        String addrString = String.format("%02X:%02X:%02X:%02X:%02X:%02X",
+            address[0], address[1], address[2], address[3], address[4], address[5]);
+        try {
+            FileUtils.stringToFile(RNDIS_ETH_ADDR_PATH, addrString);
+        } catch (IOException e) {
+           Slog.e(TAG, "failed to write to " + RNDIS_ETH_ADDR_PATH);
+        }
+    }
+
      private static String addFunction(String functions, String function) {
         if (!containsFunction(functions, function)) {
             if (functions.length() > 0) {
@@ -319,16 +240,32 @@
         private String mDefaultFunctions;
         private UsbAccessory mCurrentAccessory;
         private boolean mDeferAccessoryAttached;
+        private int mUsbNotificationId;
+        private boolean mAdbNotificationShown;
+
+        private static final int NOTIFICATION_NONE = 0;
+        private static final int NOTIFICATION_MTP = 1;
+        private static final int NOTIFICATION_PTP = 2;
+        private static final int NOTIFICATION_INSTALLER = 3;
+        private static final int NOTIFICATION_ADB = 4;
 
         public UsbHandler() {
-            // Read initial USB state
             try {
+                // sanity check the sys.usb.config system property
+                // this may be necessary if we crashed while switching USB configurations
+                String config = SystemProperties.get("sys.usb.config", "none");
+                if (config.equals("none")) {
+                    String persistConfig = SystemProperties.get("persist.sys.usb.config", "none");
+                    Slog.w(TAG, "resetting config to persistent property: " + persistConfig);
+                    SystemProperties.set("sys.usb.config", persistConfig);
+                }
+
+                // Read initial USB state
                 mCurrentFunctions = FileUtils.readTextFile(
                         new File(FUNCTIONS_PATH), 0, null).trim();
                 mDefaultFunctions = mCurrentFunctions;
                 String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
                 updateState(state);
-
                 mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
 
                 // Upgrade step for previous versions that used persist.service.adb.enable
@@ -414,12 +351,12 @@
                 } catch (InterruptedException e) {
                 }
             }
-            Log.e(TAG, "waitForState(" + state + ") FAILED");
+            Slog.e(TAG, "waitForState(" + state + ") FAILED");
             return false;
         }
 
         private boolean setUsbConfig(String config) {
-            Log.d(TAG, "setUsbConfig(" + config + ")");
+            if (DEBUG) Slog.d(TAG, "setUsbConfig(" + config + ")");
             // set the new configuration
             SystemProperties.set("sys.usb.config", config);
             return waitForState(config);
@@ -428,7 +365,7 @@
         private void doSetCurrentFunctions(String functions) {
             if (!mCurrentFunctions.equals(functions)) {
                 if (!setUsbConfig("none") || !setUsbConfig(functions)) {
-                    Log.e(TAG, "Failed to switch USB configuration to " + functions);
+                    Slog.e(TAG, "Failed to switch USB configuration to " + functions);
                     // revert to previous configuration if we fail
                     setUsbConfig(mCurrentFunctions);
                 } else {
@@ -438,6 +375,7 @@
         }
 
         private void setAdbEnabled(boolean enable) {
+            if (DEBUG) Slog.d(TAG, "setAdbEnabled: " + enable);
             if (enable != mAdbEnabled) {
                 mAdbEnabled = enable;
                 String functions;
@@ -449,7 +387,7 @@
                     functions = removeFunction(mDefaultFunctions, UsbManager.USB_FUNCTION_ADB);
                 }
                 setCurrentFunction(functions, true);
-                updateAdbNotification(mAdbEnabled && mConnected);
+                updateAdbNotification();
             }
         }
 
@@ -469,7 +407,7 @@
                 String[] strings = nativeGetAccessoryStrings();
                 if (strings != null) {
                     mCurrentAccessory = new UsbAccessory(strings);
-                    Log.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
+                    Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
                     // defer accessoryAttached if system is not ready
                     if (mSystemReady) {
                         mSettingsManager.accessoryAttached(mCurrentAccessory);
@@ -477,12 +415,12 @@
                         mDeferAccessoryAttached = true;
                     }
                 } else {
-                    Log.e(TAG, "nativeGetAccessoryStrings failed");
+                    Slog.e(TAG, "nativeGetAccessoryStrings failed");
                 }
             } else if (!mConnected) {
                 // make sure accessory mode is off
                 // and restore default functions
-                Log.d(TAG, "exited USB accessory mode");
+                Slog.d(TAG, "exited USB accessory mode");
                 setEnabledFunctions(mDefaultFunctions);
 
                 if (mCurrentAccessory != null) {
@@ -517,8 +455,8 @@
                 case MSG_UPDATE_STATE:
                     mConnected = (msg.arg1 == 1);
                     mConfigured = (msg.arg2 == 1);
-                    updateUsbNotification(mConnected);
-                    updateAdbNotification(mAdbEnabled && mConnected);
+                    updateUsbNotification();
+                    updateAdbNotification();
                     if (containsFunction(mCurrentFunctions,
                             UsbManager.USB_FUNCTION_ACCESSORY)) {
                         updateCurrentAccessory();
@@ -562,8 +500,8 @@
                     }
                     break;
                 case MSG_SYSTEM_READY:
-                    updateUsbNotification(mConnected);
-                    updateAdbNotification(mAdbEnabled && mConnected);
+                    updateUsbNotification();
+                    updateAdbNotification();
                     updateUsbState();
                     if (mCurrentAccessory != null && mDeferAccessoryAttached) {
                         mSettingsManager.accessoryAttached(mCurrentAccessory);
@@ -576,6 +514,106 @@
             return mCurrentAccessory;
         }
 
+        private void updateUsbNotification() {
+            if (mNotificationManager == null || !mUseUsbNotification) return;
+            if (mConnected) {
+                Resources r = mContext.getResources();
+                CharSequence title = null;
+                int id = NOTIFICATION_NONE;
+                if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)) {
+                    title = r.getText(
+                        com.android.internal.R.string.usb_mtp_notification_title);
+                    id = NOTIFICATION_MTP;
+                } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP)) {
+                    title = r.getText(
+                        com.android.internal.R.string.usb_ptp_notification_title);
+                    id = NOTIFICATION_PTP;
+                } else if (containsFunction(mCurrentFunctions,
+                        UsbManager.USB_FUNCTION_MASS_STORAGE)) {
+                    title = r.getText(
+                        com.android.internal.R.string.usb_cd_installer_notification_title);
+                    id = NOTIFICATION_INSTALLER;
+                } else {
+                    Slog.e(TAG, "No known USB function in updateUsbNotification");
+                }
+                if (id != mUsbNotificationId) {
+                    // clear notification if title needs changing
+                    if (mUsbNotificationId != NOTIFICATION_NONE) {
+                        mNotificationManager.cancel(mUsbNotificationId);
+                        mUsbNotificationId = NOTIFICATION_NONE;
+                    }
+                }
+                if (mUsbNotificationId == NOTIFICATION_NONE) {
+                    CharSequence message = r.getText(
+                            com.android.internal.R.string.usb_notification_message);
+
+                    Notification notification = new Notification();
+                    notification.icon = com.android.internal.R.drawable.stat_sys_data_usb;
+                    notification.when = 0;
+                    notification.flags = Notification.FLAG_ONGOING_EVENT;
+                    notification.tickerText = title;
+                    notification.defaults = 0; // please be quiet
+                    notification.sound = null;
+                    notification.vibrate = null;
+
+                    Intent intent = new Intent(
+                            Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                    intent.setComponent(new ComponentName("com.android.settings",
+                            "com.android.settings.UsbSettings"));
+                    PendingIntent pi = PendingIntent.getActivity(mContext, 0,
+                            intent, 0);
+                    notification.setLatestEventInfo(mContext, title, message, pi);
+                    mNotificationManager.notify(id, notification);
+                    mUsbNotificationId = id;
+                }
+
+            } else if (mUsbNotificationId != NOTIFICATION_NONE) {
+                mNotificationManager.cancel(mUsbNotificationId);
+                mUsbNotificationId = NOTIFICATION_NONE;
+            }
+        }
+
+        private void updateAdbNotification() {
+            if (mNotificationManager == null) return;
+            if (mAdbEnabled && mConnected) {
+                if ("0".equals(SystemProperties.get("persist.adb.notify"))) return;
+
+                if (!mAdbNotificationShown) {
+                    Resources r = mContext.getResources();
+                    CharSequence title = r.getText(
+                            com.android.internal.R.string.adb_active_notification_title);
+                    CharSequence message = r.getText(
+                            com.android.internal.R.string.adb_active_notification_message);
+
+                    Notification notification = new Notification();
+                    notification.icon = com.android.internal.R.drawable.stat_sys_adb;
+                    notification.when = 0;
+                    notification.flags = Notification.FLAG_ONGOING_EVENT;
+                    notification.tickerText = title;
+                    notification.defaults = 0; // please be quiet
+                    notification.sound = null;
+                    notification.vibrate = null;
+
+                    Intent intent = new Intent(
+                            Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                    intent.setComponent(new ComponentName("com.android.settings",
+                            "com.android.settings.DevelopmentSettings"));
+                    PendingIntent pi = PendingIntent.getActivity(mContext, 0,
+                            intent, 0);
+                    notification.setLatestEventInfo(mContext, title, message, pi);
+                    mAdbNotificationShown = true;
+                    mNotificationManager.notify(NOTIFICATION_ADB, notification);
+                }
+            } else if (mAdbNotificationShown) {
+                mAdbNotificationShown = false;
+                mNotificationManager.cancel(NOTIFICATION_ADB);
+            }
+        }
+
         public void dump(FileDescriptor fd, PrintWriter pw) {
             pw.println("  USB Device State:");
             pw.println("    Current Functions: " + mCurrentFunctions);
@@ -592,22 +630,23 @@
     }
 
     /* opens the currently attached USB accessory */
-        public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
-            UsbAccessory currentAccessory = mHandler.getCurrentAccessory();
-            if (currentAccessory == null) {
-                throw new IllegalArgumentException("no accessory attached");
-            }
-            if (!currentAccessory.equals(accessory)) {
-                String error = accessory.toString()
-                        + " does not match current accessory "
-                        + currentAccessory;
-                throw new IllegalArgumentException(error);
-            }
-            mSettingsManager.checkPermission(accessory);
-            return nativeOpenAccessory();
+    public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
+        UsbAccessory currentAccessory = mHandler.getCurrentAccessory();
+        if (currentAccessory == null) {
+            throw new IllegalArgumentException("no accessory attached");
         }
+        if (!currentAccessory.equals(accessory)) {
+            String error = accessory.toString()
+                    + " does not match current accessory "
+                    + currentAccessory;
+            throw new IllegalArgumentException(error);
+        }
+        mSettingsManager.checkPermission(accessory);
+        return nativeOpenAccessory();
+    }
 
     public void setCurrentFunction(String function, boolean makeDefault) {
+        if (DEBUG) Slog.d(TAG, "setCurrentFunction(" + function + ") default: " + makeDefault);
         mHandler.sendMessage(MSG_SET_CURRENT_FUNCTION, function, makeDefault);
     }
 
diff --git a/services/java/com/android/server/usb/UsbHostManager.java b/services/java/com/android/server/usb/UsbHostManager.java
index 923b049..0a0ff59 100644
--- a/services/java/com/android/server/usb/UsbHostManager.java
+++ b/services/java/com/android/server/usb/UsbHostManager.java
@@ -37,7 +37,6 @@
 import android.os.ParcelFileDescriptor;
 import android.os.UEventObserver;
 import android.provider.Settings;
-import android.util.Log;
 import android.util.Slog;
 
 import java.io.File;
@@ -112,7 +111,7 @@
 
         synchronized (mLock) {
             if (mDevices.get(deviceName) != null) {
-                Log.w(TAG, "device already on mDevices list: " + deviceName);
+                Slog.w(TAG, "device already on mDevices list: " + deviceName);
                 return;
             }
 
@@ -148,7 +147,7 @@
             } catch (Exception e) {
                 // beware of index out of bound exceptions, which might happen if
                 // a device does not set bNumEndpoints correctly
-                Log.e(TAG, "error parsing USB descriptors", e);
+                Slog.e(TAG, "error parsing USB descriptors", e);
                 return;
             }
 
diff --git a/services/java/com/android/server/usb/UsbSettingsManager.java b/services/java/com/android/server/usb/UsbSettingsManager.java
index 9113677..0baafbb 100644
--- a/services/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/java/com/android/server/usb/UsbSettingsManager.java
@@ -35,7 +35,7 @@
 import android.os.Binder;
 import android.os.FileUtils;
 import android.os.Process;
-import android.util.Log;
+import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.util.Xml;
 
@@ -62,6 +62,7 @@
 class UsbSettingsManager {
 
     private static final String TAG = "UsbSettingsManager";
+    private static final boolean DEBUG = false;
     private static final File sSettingsFile = new File("/data/system/usb_device_manager.xml");
 
     private final Context mContext;
@@ -410,9 +411,9 @@
                 }
             }
         } catch (FileNotFoundException e) {
-            Log.w(TAG, "settings file not found");
+            if (DEBUG) Slog.d(TAG, "settings file not found");
         } catch (Exception e) {
-            Log.e(TAG, "error reading settings file, deleting to start fresh", e);
+            Slog.e(TAG, "error reading settings file, deleting to start fresh", e);
             sSettingsFile.delete();
         } finally {
             if (stream != null) {
@@ -428,7 +429,7 @@
         FileOutputStream fos = null;
         try {
             FileOutputStream fstr = new FileOutputStream(sSettingsFile);
-            Log.d(TAG, "writing settings to " + fstr);
+            if (DEBUG) Slog.d(TAG, "writing settings to " + fstr);
             BufferedOutputStream str = new BufferedOutputStream(fstr);
             FastXmlSerializer serializer = new FastXmlSerializer();
             serializer.setOutput(str, "utf-8");
@@ -457,7 +458,7 @@
             FileUtils.sync(fstr);
             str.close();
         } catch (Exception e) {
-            Log.e(TAG, "error writing settings file, deleting to start fresh", e);
+            Slog.e(TAG, "error writing settings file, deleting to start fresh", e);
             sSettingsFile.delete();
         }
     }
@@ -472,7 +473,7 @@
         try {
             parser = ai.loadXmlMetaData(mPackageManager, metaDataName);
             if (parser == null) {
-                Log.w(TAG, "no meta-data for " + info);
+                Slog.w(TAG, "no meta-data for " + info);
                 return false;
             }
 
@@ -494,7 +495,7 @@
                 XmlUtils.nextElement(parser);
             }
         } catch (Exception e) {
-            Log.w(TAG, "Unable to load component info " + info.toString(), e);
+            Slog.w(TAG, "Unable to load component info " + info.toString(), e);
         } finally {
             if (parser != null) parser.close();
         }
@@ -553,7 +554,7 @@
 
         Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED);
         intent.putExtra(UsbManager.EXTRA_DEVICE, device);
-        Log.d(TAG, "usbDeviceRemoved, sending " + intent);
+        if (DEBUG) Slog.d(TAG, "usbDeviceRemoved, sending " + intent);
         mContext.sendBroadcast(intent);
     }
 
@@ -604,7 +605,7 @@
                     try {
                         mContext.startActivity(dialogIntent);
                     } catch (ActivityNotFoundException e) {
-                        Log.e(TAG, "unable to start UsbAccessoryUriActivity");
+                        Slog.e(TAG, "unable to start UsbAccessoryUriActivity");
                     }
                 }
             }
@@ -652,7 +653,7 @@
                                 defaultRI.activityInfo.name));
                 mContext.startActivity(intent);
             } catch (ActivityNotFoundException e) {
-                Log.e(TAG, "startActivity failed", e);
+                Slog.e(TAG, "startActivity failed", e);
             }
         } else {
             Intent resolverIntent = new Intent();
@@ -679,7 +680,7 @@
             try {
                 mContext.startActivity(resolverIntent);
             } catch (ActivityNotFoundException e) {
-                Log.e(TAG, "unable to start activity " + resolverIntent);
+                Slog.e(TAG, "unable to start activity " + resolverIntent);
             }
         }
     }
@@ -733,7 +734,7 @@
                 XmlUtils.nextElement(parser);
             }
         } catch (Exception e) {
-            Log.w(TAG, "Unable to load component info " + aInfo.toString(), e);
+            Slog.w(TAG, "Unable to load component info " + aInfo.toString(), e);
         } finally {
             if (parser != null) parser.close();
         }
@@ -751,7 +752,7 @@
                 info = mPackageManager.getPackageInfo(packageName,
                         PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA);
             } catch (NameNotFoundException e) {
-                Log.e(TAG, "handlePackageUpdate could not find package " + packageName, e);
+                Slog.e(TAG, "handlePackageUpdate could not find package " + packageName, e);
                 return;
             }
 
@@ -831,7 +832,7 @@
         try {
             mContext.startActivity(intent);
         } catch (ActivityNotFoundException e) {
-            Log.e(TAG, "unable to start UsbPermissionActivity");
+            Slog.e(TAG, "unable to start UsbPermissionActivity");
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -847,7 +848,7 @@
             try {
                 pi.send(mContext, 0, intent);
             } catch (PendingIntent.CanceledException e) {
-                Log.w(TAG, "requestPermission PendingIntent was cancelled");
+                if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");
             }
             return;
         }
@@ -867,7 +868,7 @@
            try {
                 pi.send(mContext, 0, intent);
             } catch (PendingIntent.CanceledException e) {
-                Log.w(TAG, "requestPermission PendingIntent was cancelled");
+                if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");
             }
             return;
         }
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java
index ee69311..65007f9 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/wm/InputManager.java
@@ -551,18 +551,6 @@
                     android.Manifest.permission.INJECT_EVENTS, injectorPid, injectorUid)
                     == PackageManager.PERMISSION_GRANTED;
         }
-        
-        @SuppressWarnings("unused")
-        public boolean filterTouchEvents() {
-            return mContext.getResources().getBoolean(
-                    com.android.internal.R.bool.config_filterTouchEvents);
-        }
-        
-        @SuppressWarnings("unused")
-        public boolean filterJumpyTouchEvents() {
-            return mContext.getResources().getBoolean(
-                    com.android.internal.R.bool.config_filterJumpyTouchEvents);
-        }
 
         @SuppressWarnings("unused")
         public int getVirtualKeyQuietTimeMillis() {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 3bf309b..be21ac0 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -231,7 +231,7 @@
     // Maximum number of milliseconds to wait for input devices to be enumerated before
     // proceding with safe mode detection.
     private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
-    
+
     // Default input dispatching timeout in nanoseconds.
     static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
 
@@ -4886,8 +4886,13 @@
             int fw = frame.width();
             int fh = frame.height();
 
-            // First try reducing to fit in x dimension.
-            scale = width/(float)fw;
+            // Constrain thumbnail to smaller of screen width or height. Assumes aspect
+            // of thumbnail is the same as the screen (in landscape) or square.
+            if (dw <= dh) {
+                scale = width / (float) fw; // portrait
+            } else {
+                scale = height / (float) fh; // landscape
+            }
 
             // The screen shot will contain the entire screen.
             dw = (int)(dw*scale);
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 8a46ab0..14a4109 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -69,8 +69,6 @@
     jmethodID interceptKeyBeforeDispatching;
     jmethodID dispatchUnhandledKey;
     jmethodID checkInjectEventsPermission;
-    jmethodID filterTouchEvents;
-    jmethodID filterJumpyTouchEvents;
     jmethodID getVirtualKeyQuietTimeMillis;
     jmethodID getExcludedDeviceNames;
     jmethodID getKeyRepeatTimeout;
@@ -381,18 +379,6 @@
 void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outConfig) {
     JNIEnv* env = jniEnv();
 
-    jboolean filterTouchEvents = env->CallBooleanMethod(mCallbacksObj,
-            gCallbacksClassInfo.filterTouchEvents);
-    if (!checkAndClearExceptionFromCallback(env, "filterTouchEvents")) {
-        outConfig->filterTouchEvents = filterTouchEvents;
-    }
-
-    jboolean filterJumpyTouchEvents = env->CallBooleanMethod(mCallbacksObj,
-            gCallbacksClassInfo.filterJumpyTouchEvents);
-    if (!checkAndClearExceptionFromCallback(env, "filterJumpyTouchEvents")) {
-        outConfig->filterJumpyTouchEvents = filterJumpyTouchEvents;
-    }
-
     jint virtualKeyQuietTime = env->CallIntMethod(mCallbacksObj,
             gCallbacksClassInfo.getVirtualKeyQuietTimeMillis);
     if (!checkAndClearExceptionFromCallback(env, "getVirtualKeyQuietTimeMillis")) {
@@ -1405,12 +1391,6 @@
     GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, clazz,
             "checkInjectEventsPermission", "(II)Z");
 
-    GET_METHOD_ID(gCallbacksClassInfo.filterTouchEvents, clazz,
-            "filterTouchEvents", "()Z");
-
-    GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, clazz,
-            "filterJumpyTouchEvents", "()Z");
-
     GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyQuietTimeMillis, clazz,
             "getVirtualKeyQuietTimeMillis", "()I");
 
diff --git a/services/jni/com_android_server_connectivity_Vpn.cpp b/services/jni/com_android_server_connectivity_Vpn.cpp
index ae7fbfe..5f920f1 100644
--- a/services/jni/com_android_server_connectivity_Vpn.cpp
+++ b/services/jni/com_android_server_connectivity_Vpn.cpp
@@ -42,6 +42,9 @@
 namespace android
 {
 
+static int inet4 = -1;
+static int inet6 = -1;
+
 static inline in_addr_t *as_in_addr(sockaddr *sa) {
     return &((sockaddr_in *)sa)->sin_addr.s_addr;
 }
@@ -51,11 +54,9 @@
 #define SYSTEM_ERROR -1
 #define BAD_ARGUMENT -2
 
-static int create_interface(int mtu, char *name, int *index)
+static int create_interface(char *name, int *index, int mtu)
 {
-    int tun = open("/dev/tun", O_RDWR);
-    int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
-    int flags;
+    int tun = open("/dev/tun", O_RDWR | O_NONBLOCK);
 
     ifreq ifr4;
     memset(&ifr4, 0, sizeof(ifr4));
@@ -87,32 +88,20 @@
         goto error;
     }
 
-    // Make it non-blocking.
-    flags = fcntl(tun, F_GETFL, 0);
-    if (flags == -1 || fcntl(tun, F_SETFL, flags | O_NONBLOCK)) {
-        LOGE("Cannot set non-blocking on %s: %s", ifr4.ifr_name, strerror(errno));
-        goto error;
-    }
-
-    strcpy(name, ifr4.ifr_name);
+    strncpy(name, ifr4.ifr_name, IFNAMSIZ);
     *index = ifr4.ifr_ifindex;
-    close(inet4);
     return tun;
 
 error:
     close(tun);
-    close(inet4);
     return SYSTEM_ERROR;
 }
 
 static int set_addresses(const char *name, int index, const char *addresses)
 {
-    int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
-    int inet6 = socket(AF_INET6, SOCK_DGRAM, 0);
-
     ifreq ifr4;
     memset(&ifr4, 0, sizeof(ifr4));
-    strcpy(ifr4.ifr_name, name);
+    strncpy(ifr4.ifr_name, name, IFNAMSIZ);
     ifr4.ifr_addr.sa_family = AF_INET;
 
     in6_ifreq ifr6;
@@ -121,7 +110,6 @@
 
     char address[65];
     int prefix;
-
     int chars;
     int count = 0;
 
@@ -164,7 +152,7 @@
                 break;
             }
         }
-        LOGV("Address added on %s: %s/%d", name, address, prefix);
+        LOGD("Address added on %s: %s/%d", name, address, prefix);
         ++count;
     }
 
@@ -177,16 +165,11 @@
         count = BAD_ARGUMENT;
     }
 
-    close(inet4);
-    close(inet6);
     return count;
 }
 
 static int set_routes(const char *name, int index, const char *routes)
 {
-    int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
-    int inet6 = socket(AF_INET6, SOCK_DGRAM, 0);
-
     rtentry rt4;
     memset(&rt4, 0, sizeof(rt4));
     rt4.rt_dev = (char *)name;
@@ -201,7 +184,6 @@
 
     char address[65];
     int prefix;
-
     int chars;
     int count = 0;
 
@@ -211,32 +193,50 @@
         if (strchr(address, ':')) {
             // Add an IPv6 route.
             if (inet_pton(AF_INET6, address, &rt6.rtmsg_dst) != 1 ||
-                    prefix < 1 || prefix > 128) {
+                    prefix < 0 || prefix > 128) {
                 count = BAD_ARGUMENT;
                 break;
             }
 
-            rt6.rtmsg_dst_len = prefix;
+            rt6.rtmsg_dst_len = prefix ? prefix : 1;
             if (ioctl(inet6, SIOCADDRT, &rt6) && errno != EEXIST) {
                 count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR;
                 break;
             }
+
+            if (!prefix) {
+                // Split the route instead of replacing the default route.
+                rt6.rtmsg_dst.s6_addr[0] ^= 0x80;
+                if (ioctl(inet6, SIOCADDRT, &rt6) && errno != EEXIST) {
+                    count = SYSTEM_ERROR;
+                    break;
+                }
+            }
         } else {
             // Add an IPv4 route.
             if (inet_pton(AF_INET, address, as_in_addr(&rt4.rt_dst)) != 1 ||
-                    prefix < 1 || prefix > 32) {
+                    prefix < 0 || prefix > 32) {
                 count = BAD_ARGUMENT;
                 break;
             }
 
-            in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 0;
+            in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 0x80000000;
             *as_in_addr(&rt4.rt_genmask) = htonl(mask);
             if (ioctl(inet4, SIOCADDRT, &rt4) && errno != EEXIST) {
                 count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR;
                 break;
             }
+
+            if (!prefix) {
+                // Split the route instead of replacing the default route.
+                *as_in_addr(&rt4.rt_dst) ^= htonl(0x80000000);
+                if (ioctl(inet4, SIOCADDRT, &rt4) && errno != EEXIST) {
+                    count = SYSTEM_ERROR;
+                    break;
+                }
+            }
         }
-        LOGV("Route added on %s: %s/%d", name, address, prefix);
+        LOGD("Route added on %s: %s/%d", name, address, prefix);
         ++count;
     }
 
@@ -250,8 +250,6 @@
         count = BAD_ARGUMENT;
     }
 
-    close(inet4);
-    close(inet6);
     return count;
 }
 
@@ -262,31 +260,25 @@
         LOGE("Cannot get interface name: %s", strerror(errno));
         return SYSTEM_ERROR;
     }
-    strcpy(name, ifr4.ifr_name);
+    strncpy(name, ifr4.ifr_name, IFNAMSIZ);
     return 0;
 }
 
 static int reset_interface(const char *name)
 {
-    int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
-
     ifreq ifr4;
-    ifr4.ifr_flags = 0;
     strncpy(ifr4.ifr_name, name, IFNAMSIZ);
+    ifr4.ifr_flags = 0;
 
     if (ioctl(inet4, SIOCSIFFLAGS, &ifr4) && errno != ENODEV) {
         LOGE("Cannot reset %s: %s", name, strerror(errno));
-        close(inet4);
         return SYSTEM_ERROR;
     }
-    close(inet4);
     return 0;
 }
 
 static int check_interface(const char *name)
 {
-    int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
-
     ifreq ifr4;
     strncpy(ifr4.ifr_name, name, IFNAMSIZ);
     ifr4.ifr_flags = 0;
@@ -294,13 +286,12 @@
     if (ioctl(inet4, SIOCGIFFLAGS, &ifr4) && errno != ENODEV) {
         LOGE("Cannot check %s: %s", name, strerror(errno));
     }
-    close(inet4);
     return ifr4.ifr_flags;
 }
 
-static int bind_to_interface(int fd, const char *name)
+static int bind_to_interface(int socket, const char *name)
 {
-    if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name))) {
+    if (setsockopt(socket, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name))) {
         LOGE("Cannot bind socket to %s: %s", name, strerror(errno));
         return SYSTEM_ERROR;
     }
@@ -318,23 +309,22 @@
     }
 }
 
-static jint establish(JNIEnv *env, jobject thiz,
+static jint configure(JNIEnv *env, jobject thiz,
         jint mtu, jstring jAddresses, jstring jRoutes)
 {
     char name[IFNAMSIZ];
     int index;
-    int tun = create_interface(mtu, name, &index);
+    int tun = create_interface(name, &index, mtu);
     if (tun < 0) {
         throwException(env, tun, "Cannot create interface");
         return -1;
     }
-    LOGD("%s is created", name);
 
-    const char *addresses;
-    const char *routes;
+    const char *addresses = NULL;
+    const char *routes = NULL;
     int count;
 
-    // Addresses are required.
+    // At least one address must be set.
     addresses = jAddresses ? env->GetStringUTFChars(jAddresses, NULL) : NULL;
     if (!addresses) {
         jniThrowNullPointerException(env, "address");
@@ -348,7 +338,7 @@
     }
     LOGD("Configured %d address(es) on %s", count, name);
 
-    // Routes are optional.
+    // On the contrary, routes are optional.
     routes = jRoutes ? env->GetStringUTFChars(jRoutes, NULL) : NULL;
     if (routes) {
         count = set_routes(name, index, routes);
@@ -368,10 +358,10 @@
     return -1;
 }
 
-static jstring getName(JNIEnv *env, jobject thiz, jint fd)
+static jstring getName(JNIEnv *env, jobject thiz, jint tun)
 {
     char name[IFNAMSIZ];
-    if (get_interface_name(name, fd) < 0) {
+    if (get_interface_name(name, tun) < 0) {
         throwException(env, SYSTEM_ERROR, "Cannot get interface name");
         return NULL;
     }
@@ -380,24 +370,20 @@
 
 static void reset(JNIEnv *env, jobject thiz, jstring jName)
 {
-    const char *name = jName ?
-            env->GetStringUTFChars(jName, NULL) : NULL;
+    const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
     if (!name) {
         jniThrowNullPointerException(env, "name");
         return;
     }
     if (reset_interface(name) < 0) {
         throwException(env, SYSTEM_ERROR, "Cannot reset interface");
-    } else {
-        LOGD("%s is deactivated", name);
     }
     env->ReleaseStringUTFChars(jName, name);
 }
 
 static jint check(JNIEnv *env, jobject thiz, jstring jName)
 {
-    const char *name = jName ?
-            env->GetStringUTFChars(jName, NULL) : NULL;
+    const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
     if (!name) {
         jniThrowNullPointerException(env, "name");
         return 0;
@@ -407,15 +393,14 @@
     return flags;
 }
 
-static void protect(JNIEnv *env, jobject thiz, jint fd, jstring jName)
+static void protect(JNIEnv *env, jobject thiz, jint socket, jstring jName)
 {
-    const char *name = jName ?
-            env->GetStringUTFChars(jName, NULL) : NULL;
+    const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
     if (!name) {
         jniThrowNullPointerException(env, "name");
         return;
     }
-    if (bind_to_interface(fd, name) < 0) {
+    if (bind_to_interface(socket, name) < 0) {
         throwException(env, SYSTEM_ERROR, "Cannot protect socket");
     }
     env->ReleaseStringUTFChars(jName, name);
@@ -424,15 +409,21 @@
 //------------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
-    {"nativeEstablish", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)establish},
-    {"nativeGetName", "(I)Ljava/lang/String;", (void *)getName},
-    {"nativeReset", "(Ljava/lang/String;)V", (void *)reset},
-    {"nativeCheck", "(Ljava/lang/String;)I", (void *)check},
-    {"nativeProtect", "(ILjava/lang/String;)V", (void *)protect},
+    {"jniConfigure", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)configure},
+    {"jniGetName", "(I)Ljava/lang/String;", (void *)getName},
+    {"jniReset", "(Ljava/lang/String;)V", (void *)reset},
+    {"jniCheck", "(Ljava/lang/String;)I", (void *)check},
+    {"jniProtect", "(ILjava/lang/String;)V", (void *)protect},
 };
 
 int register_android_server_connectivity_Vpn(JNIEnv *env)
 {
+    if (inet4 == -1) {
+        inet4 = socket(AF_INET, SOCK_DGRAM, 0);
+    }
+    if (inet6 == -1) {
+        inet6 = socket(AF_INET6, SOCK_DGRAM, 0);
+    }
     return jniRegisterNativeMethods(env, "com/android/server/connectivity/Vpn",
             gMethods, NELEM(gMethods));
 }
diff --git a/services/jni/com_android_server_location_GpsLocationProvider.cpp b/services/jni/com_android_server_location_GpsLocationProvider.cpp
index 6d4ad9a..87ffcba 100755
--- a/services/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -42,6 +42,7 @@
 static jmethodID method_reportNiNotification;
 static jmethodID method_requestRefLocation;
 static jmethodID method_requestSetID;
+static jmethodID method_requestUtcTime;
 
 static const GpsInterface* sGpsInterface = NULL;
 static const GpsXtraInterface* sGpsXtraInterface = NULL;
@@ -122,6 +123,13 @@
     release_wake_lock(WAKE_LOCK_NAME);
 }
 
+static void request_utc_time_callback()
+{
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+}
+
 static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
 {
     return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
@@ -137,6 +145,7 @@
     acquire_wakelock_callback,
     release_wakelock_callback,
     create_thread_callback,
+    request_utc_time_callback,
 };
 
 static void xtra_download_request_callback()
@@ -232,6 +241,7 @@
             "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
     method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");
     method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");
+    method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
 
     err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
     if (err == 0) {
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 0ae7929..64d214b 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -31,6 +31,7 @@
 
 #include <binder/BinderService.h>
 #include <binder/IServiceManager.h>
+#include <binder/PermissionCache.h>
 
 #include <gui/ISensorServer.h>
 #include <gui/ISensorEventConnection.h>
@@ -58,8 +59,7 @@
  */
 
 SensorService::SensorService()
-    : mDump("android.permission.DUMP"),
-      mInitCheck(NO_INIT)
+    : mInitCheck(NO_INIT)
 {
 }
 
@@ -166,12 +166,14 @@
         delete mSensorMap.valueAt(i);
 }
 
+static const String16 sDump("android.permission.DUMP");
+
 status_t SensorService::dump(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 1024;
     char buffer[SIZE];
     String8 result;
-    if (!mDump.checkCalling()) {
+    if (!PermissionCache::checkCallingPermission(sDump)) {
         snprintf(buffer, SIZE, "Permission Denial: "
                 "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
                 IPCThreadState::self()->getCallingPid(),
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 4d0f1d9..85f4ecb 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -27,7 +27,6 @@
 #include <utils/RefBase.h>
 
 #include <binder/BinderService.h>
-#include <binder/Permission.h>
 
 #include <gui/Sensor.h>
 #include <gui/SensorChannel.h>
@@ -117,7 +116,6 @@
     Vector<Sensor> mUserSensorList;
     DefaultKeyedVector<int, SensorInterface*> mSensorMap;
     Vector<SensorInterface *> mVirtualSensorList;
-    Permission mDump;
     status_t mInitCheck;
 
     // protected by mLock
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index a774841..7bf3e0a 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -99,10 +99,43 @@
             mMaxViewportDims[0] : mMaxViewportDims[1];
 }
 
+static status_t selectConfigForPixelFormat(
+        EGLDisplay dpy,
+        EGLint const* attrs,
+        PixelFormat format,
+        EGLConfig* outConfig)
+{
+    EGLConfig config = NULL;
+    EGLint numConfigs = -1, n=0;
+    eglGetConfigs(dpy, NULL, 0, &numConfigs);
+    EGLConfig* const configs = new EGLConfig[numConfigs];
+    eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
+    for (int i=0 ; i<n ; i++) {
+        EGLint nativeVisualId = 0;
+        eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
+        if (nativeVisualId>0 && format == nativeVisualId) {
+            *outConfig = configs[i];
+            delete [] configs;
+            return NO_ERROR;
+        }
+    }
+    delete [] configs;
+    return NAME_NOT_FOUND;
+}
+
+
 void DisplayHardware::init(uint32_t dpy)
 {
     mNativeWindow = new FramebufferNativeWindow();
     framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
+    if (!fbDev) {
+        LOGE("Display subsystem failed to initialize. check logs. exiting...");
+        exit(0);
+    }
+
+    int format;
+    ANativeWindow const * const window = mNativeWindow.get();
+    window->query(window, NATIVE_WINDOW_FORMAT, &format);
     mDpiX = mNativeWindow->xdpi;
     mDpiY = mNativeWindow->ydpi;
     mRefreshRate = fbDev->fps;
@@ -111,11 +144,13 @@
     EGLint numConfigs=0;
     EGLSurface surface;
     EGLContext context;
+    EGLBoolean result;
+    status_t err;
 
     // initialize EGL
     EGLint attribs[] = {
-            EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
-            EGL_NONE,           0,
+            EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
+            EGL_NONE,               0,
             EGL_NONE
     };
 
@@ -136,9 +171,8 @@
     eglInitialize(display, NULL, NULL);
     eglGetConfigs(display, NULL, 0, &numConfigs);
 
-    EGLConfig config;
-    status_t err = EGLUtils::selectConfigForNativeWindow(
-            display, attribs, mNativeWindow.get(), &config);
+    EGLConfig config = NULL;
+    err = selectConfigForPixelFormat(display, attribs, format, &config);
     LOGE_IF(err, "couldn't find an EGLConfig matching the screen format");
     
     EGLint r,g,b,a;
@@ -219,7 +253,11 @@
      * Gather OpenGL ES extensions
      */
 
-    eglMakeCurrent(display, surface, surface, context);
+    result = eglMakeCurrent(display, surface, surface, context);
+    if (!result) {
+        LOGE("Couldn't create a working GLES context. check logs. exiting...");
+        exit(0);
+    }
 
     GLExtensions& extensions(GLExtensions::getInstance());
     extensions.initWithGLStrings(
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2bab6a8..35e29a6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -101,9 +101,8 @@
 }
 
 void Layer::onFrameQueued() {
-    if (android_atomic_or(1, &mQueuedFrames) == 0) {
-        mFlinger->signalEvent();
-    }
+    android_atomic_inc(&mQueuedFrames);
+    mFlinger->signalEvent();
 }
 
 // called with SurfaceFlinger::mStateLock as soon as the layer is entered
@@ -406,20 +405,18 @@
 
 void Layer::lockPageFlip(bool& recomputeVisibleRegions)
 {
-    if (android_atomic_and(0, &mQueuedFrames)) {
+    if (mQueuedFrames > 0) {
+        // signal another event if we have more frames pending
+        if (android_atomic_dec(&mQueuedFrames) > 1) {
+            mFlinger->signalEvent();
+        }
+
         if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
             // something happened!
             recomputeVisibleRegions = true;
             return;
         }
 
-        // signal another event if we have more frames waiting
-        if (mSurfaceTexture->getQueuedCount()) {
-            if (android_atomic_or(1, &mQueuedFrames) == 0) {
-                mFlinger->signalEvent();
-            }
-        }
-
         mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
         mSurfaceTexture->getTransformMatrix(mTextureMatrix);
 
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index bcd8c83..c86c659 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -228,13 +228,18 @@
     const Layer::State& s(drawingState());
     const Transform tr(planeTransform * s.transform);
     const bool transformed = tr.transformed();
-   
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    const uint32_t hw_h = hw.getHeight();
+
     uint32_t w = s.w;
     uint32_t h = s.h;    
     tr.transform(mVertices[0], 0, 0);
     tr.transform(mVertices[1], 0, h);
     tr.transform(mVertices[2], w, h);
     tr.transform(mVertices[3], w, 0);
+    for (size_t i=0 ; i<4 ; i++)
+        mVertices[i][1] = hw_h - mVertices[i][1];
+
     if (UNLIKELY(transformed)) {
         // NOTE: here we could also punt if we have too many rectangles
         // in the transparent region
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 97edfee..b0881a4 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -32,6 +32,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/MemoryHeapBase.h>
+#include <binder/PermissionCache.h>
 
 #include <utils/String8.h>
 #include <utils/String16.h>
@@ -67,17 +68,19 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
+const String16 sHardwareTest("android.permission.HARDWARE_TEST");
+const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
+const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
+const String16 sDump("android.permission.DUMP");
+
+// ---------------------------------------------------------------------------
+
 SurfaceFlinger::SurfaceFlinger()
     :   BnSurfaceComposer(), Thread(false),
         mTransactionFlags(0),
-        mTransactionCount(0),
         mResizeTransationPending(false),
         mLayersRemoved(false),
         mBootTime(systemTime()),
-        mHardwareTest("android.permission.HARDWARE_TEST"),
-        mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"),
-        mReadFramebuffer("android.permission.READ_FRAME_BUFFER"),
-        mDump("android.permission.DUMP"),
         mVisibleRegionsDirty(false),
         mHwWorkListDirty(false),
         mDeferReleaseConsole(false),
@@ -160,9 +163,34 @@
     const nsecs_t duration = now - mBootTime;
     LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
     mBootFinished = true;
+
+    // wait patiently for the window manager death
+    const String16 name("window");
+    sp<IBinder> window(defaultServiceManager()->getService(name));
+    if (window != 0) {
+        window->linkToDeath(this);
+    }
+
+    // stop boot animation
     property_set("ctl.stop", "bootanim");
 }
 
+void SurfaceFlinger::binderDied(const wp<IBinder>& who)
+{
+    // the window manager died on us. prepare its eulogy.
+
+    // unfreeze the screen in case it was... frozen
+    mFreezeDisplayTime = 0;
+    mFreezeCount = 0;
+    mFreezeDisplay = false;
+
+    // reset screen orientation
+    setOrientation(0, eOrientationDefault, 0);
+
+    // restart the boot-animation
+    property_set("ctl.start", "bootanim");
+}
+
 void SurfaceFlinger::onFirstRef()
 {
     run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
@@ -248,7 +276,8 @@
     glViewport(0, 0, w, h);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
-    glOrthof(0, w, h, 0, 0, 1);
+    // put the origin in the left-bottom corner
+    glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
 
     mReadyToRunBarrier.open();
 
@@ -381,13 +410,11 @@
         handleConsoleEvents();
     }
 
-    if (LIKELY(mTransactionCount == 0)) {
-        // if we're in a global transaction, don't do anything.
-        const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
-        uint32_t transactionFlags = peekTransactionFlags(mask);
-        if (LIKELY(transactionFlags)) {
-            handleTransaction(transactionFlags);
-        }
+    // if we're in a global transaction, don't do anything.
+    const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
+    uint32_t transactionFlags = peekTransactionFlags(mask);
+    if (UNLIKELY(transactionFlags)) {
+        handleTransaction(transactionFlags);
     }
 
     // post surfaces (if needed)
@@ -1172,28 +1199,33 @@
     return old;
 }
 
-void SurfaceFlinger::openGlobalTransaction()
-{
-    android_atomic_inc(&mTransactionCount);
-}
 
-void SurfaceFlinger::closeGlobalTransaction()
-{
-    if (android_atomic_dec(&mTransactionCount) == 1) {
-        signalEvent();
+void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state) {
+    Mutex::Autolock _l(mStateLock);
 
-        // if there is a transaction with a resize, wait for it to
-        // take effect before returning.
-        Mutex::Autolock _l(mStateLock);
-        while (mResizeTransationPending) {
-            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
-            if (CC_UNLIKELY(err != NO_ERROR)) {
-                // just in case something goes wrong in SF, return to the
-                // called after a few seconds.
-                LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
-                mResizeTransationPending = false;
-                break;
-            }
+    uint32_t flags = 0;
+    const size_t count = state.size();
+    for (size_t i=0 ; i<count ; i++) {
+        const ComposerState& s(state[i]);
+        sp<Client> client( static_cast<Client *>(s.client.get()) );
+        flags |= setClientStateLocked(client, s.state);
+    }
+    if (flags) {
+        setTransactionFlags(flags);
+    }
+
+    signalEvent();
+
+    // if there is a transaction with a resize, wait for it to
+    // take effect before returning.
+    while (mResizeTransationPending) {
+        status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+        if (CC_UNLIKELY(err != NO_ERROR)) {
+            // just in case something goes wrong in SF, return to the
+            // called after a few seconds.
+            LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
+            mResizeTransationPending = false;
+            break;
         }
     }
 }
@@ -1389,60 +1421,52 @@
     return err;
 }
 
-status_t SurfaceFlinger::setClientState(
+uint32_t SurfaceFlinger::setClientStateLocked(
         const sp<Client>& client,
-        int32_t count,
-        const layer_state_t* states)
+        const layer_state_t& s)
 {
-    Mutex::Autolock _l(mStateLock);
     uint32_t flags = 0;
-    for (int i=0 ; i<count ; i++) {
-        const layer_state_t& s(states[i]);
-        sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
-        if (layer != 0) {
-            const uint32_t what = s.what;
-            if (what & ePositionChanged) {
-                if (layer->setPosition(s.x, s.y))
-                    flags |= eTraversalNeeded;
-            }
-            if (what & eLayerChanged) {
-                ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
-                if (layer->setLayer(s.z)) {
-                    mCurrentState.layersSortedByZ.removeAt(idx);
-                    mCurrentState.layersSortedByZ.add(layer);
-                    // we need traversal (state changed)
-                    // AND transaction (list changed)
-                    flags |= eTransactionNeeded|eTraversalNeeded;
-                }
-            }
-            if (what & eSizeChanged) {
-                if (layer->setSize(s.w, s.h)) {
-                    flags |= eTraversalNeeded;
-                    mResizeTransationPending = true;
-                }
-            }
-            if (what & eAlphaChanged) {
-                if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
-                    flags |= eTraversalNeeded;
-            }
-            if (what & eMatrixChanged) {
-                if (layer->setMatrix(s.matrix))
-                    flags |= eTraversalNeeded;
-            }
-            if (what & eTransparentRegionChanged) {
-                if (layer->setTransparentRegionHint(s.transparentRegion))
-                    flags |= eTraversalNeeded;
-            }
-            if (what & eVisibilityChanged) {
-                if (layer->setFlags(s.flags, s.mask))
-                    flags |= eTraversalNeeded;
+    sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
+    if (layer != 0) {
+        const uint32_t what = s.what;
+        if (what & ePositionChanged) {
+            if (layer->setPosition(s.x, s.y))
+                flags |= eTraversalNeeded;
+        }
+        if (what & eLayerChanged) {
+            ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+            if (layer->setLayer(s.z)) {
+                mCurrentState.layersSortedByZ.removeAt(idx);
+                mCurrentState.layersSortedByZ.add(layer);
+                // we need traversal (state changed)
+                // AND transaction (list changed)
+                flags |= eTransactionNeeded|eTraversalNeeded;
             }
         }
+        if (what & eSizeChanged) {
+            if (layer->setSize(s.w, s.h)) {
+                flags |= eTraversalNeeded;
+                mResizeTransationPending = true;
+            }
+        }
+        if (what & eAlphaChanged) {
+            if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
+                flags |= eTraversalNeeded;
+        }
+        if (what & eMatrixChanged) {
+            if (layer->setMatrix(s.matrix))
+                flags |= eTraversalNeeded;
+        }
+        if (what & eTransparentRegionChanged) {
+            if (layer->setTransparentRegionHint(s.transparentRegion))
+                flags |= eTraversalNeeded;
+        }
+        if (what & eVisibilityChanged) {
+            if (layer->setFlags(s.flags, s.mask))
+                flags |= eTraversalNeeded;
+        }
     }
-    if (flags) {
-        setTransactionFlags(flags);
-    }
-    return NO_ERROR;
+    return flags;
 }
 
 void SurfaceFlinger::screenReleased(int dpy)
@@ -1464,7 +1488,8 @@
     const size_t SIZE = 4096;
     char buffer[SIZE];
     String8 result;
-    if (!mDump.checkCalling()) {
+
+    if (!PermissionCache::checkCallingPermission(sDump)) {
         snprintf(buffer, SIZE, "Permission Denial: "
                 "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
                 IPCThreadState::self()->getCallingPid(),
@@ -1583,8 +1608,7 @@
 {
     switch (code) {
         case CREATE_CONNECTION:
-        case OPEN_GLOBAL_TRANSACTION:
-        case CLOSE_GLOBAL_TRANSACTION:
+        case SET_TRANSACTION_STATE:
         case SET_ORIENTATION:
         case FREEZE_DISPLAY:
         case UNFREEZE_DISPLAY:
@@ -1596,7 +1620,8 @@
             IPCThreadState* ipc = IPCThreadState::self();
             const int pid = ipc->getCallingPid();
             const int uid = ipc->getCallingUid();
-            if ((uid != AID_GRAPHICS) && !mAccessSurfaceFlinger.check(pid, uid)) {
+            if ((uid != AID_GRAPHICS) &&
+                    !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
                 LOGE("Permission Denial: "
                         "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
                 return PERMISSION_DENIED;
@@ -1609,7 +1634,8 @@
             IPCThreadState* ipc = IPCThreadState::self();
             const int pid = ipc->getCallingPid();
             const int uid = ipc->getCallingUid();
-            if ((uid != AID_GRAPHICS) && !mReadFramebuffer.check(pid, uid)) {
+            if ((uid != AID_GRAPHICS) &&
+                    !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
                 LOGE("Permission Denial: "
                         "can't read framebuffer pid=%d, uid=%d", pid, uid);
                 return PERMISSION_DENIED;
@@ -1621,7 +1647,7 @@
     status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
     if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
         CHECK_INTERFACE(ISurfaceComposer, data, reply);
-        if (UNLIKELY(!mHardwareTest.checkCalling())) {
+        if (UNLIKELY(!PermissionCache::checkCallingPermission(sHardwareTest))) {
             IPCThreadState* ipc = IPCThreadState::self();
             const int pid = ipc->getCallingPid();
             const int uid = ipc->getCallingUid();
@@ -1766,7 +1792,7 @@
     }
 
     GLfloat vtx[8];
-    const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
+    const GLfloat texCoords[4][2] = { {0,1}, {0,1-v}, {u,1-v}, {u,1} };
     glBindTexture(GL_TEXTURE_2D, tname);
     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -1775,6 +1801,22 @@
     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     glVertexPointer(2, GL_FLOAT, 0, vtx);
 
+    /*
+     * Texture coordinate mapping
+     *
+     *                 u
+     *    1 +----------+---+
+     *      |     |    |   |  image is inverted
+     *      |     V    |   |  w.r.t. the texture
+     *  1-v +----------+   |  coordinates
+     *      |              |
+     *      |              |
+     *      |              |
+     *    0 +--------------+
+     *      0              1
+     *
+     */
+
     class s_curve_interpolator {
         const float nbFrames, s, v;
     public:
@@ -1825,7 +1867,12 @@
     };
 
     // the full animation is 24 frames
-    const int nbFrames = 12;
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.sf.electron_frames", value, "24");
+    int nbFrames = (atoi(value) + 1) >> 1;
+    if (nbFrames <= 0) // just in case
+        nbFrames = 24;
+
     s_curve_interpolator itr(nbFrames, 7.5f);
     s_curve_interpolator itg(nbFrames, 8.0f);
     s_curve_interpolator itb(nbFrames, 8.5f);
@@ -2200,10 +2247,11 @@
         // invert everything, b/c glReadPixel() below will invert the FB
         glViewport(0, 0, sw, sh);
         glScissor(0, 0, sw, sh);
+        glEnable(GL_SCISSOR_TEST);
         glMatrixMode(GL_PROJECTION);
         glPushMatrix();
         glLoadIdentity();
-        glOrthof(0, hw_w, 0, hw_h, 0, 1);
+        glOrthof(0, hw_w, hw_h, 0, 0, 1);
         glMatrixMode(GL_MODELVIEW);
 
         // redraw the screen entirely...
@@ -2219,6 +2267,7 @@
         }
 
         // XXX: this is needed on tegra
+        glEnable(GL_SCISSOR_TEST);
         glScissor(0, 0, sw, sh);
 
         // check for errors and return screen capture
@@ -2404,8 +2453,7 @@
      const int self_pid = getpid();
      if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) {
          // we're called from a different process, do the real check
-         if (!checkCallingPermission(
-                 String16("android.permission.ACCESS_SURFACE_FLINGER")))
+         if (!PermissionCache::checkCallingPermission(sAccessSurfaceFlinger))
          {
              LOGE("Permission Denial: "
                      "can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
@@ -2463,9 +2511,6 @@
 status_t Client::destroySurface(SurfaceID sid) {
     return mFlinger->removeSurface(this, sid);
 }
-status_t Client::setState(int32_t count, const layer_state_t* states) {
-    return mFlinger->setClientState(this, count, states);
-}
 
 // ---------------------------------------------------------------------------
 
@@ -2474,11 +2519,14 @@
 GraphicBufferAlloc::~GraphicBufferAlloc() {}
 
 sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
-        PixelFormat format, uint32_t usage) {
+        PixelFormat format, uint32_t usage, status_t* error) {
     sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
     status_t err = graphicBuffer->initCheck();
+    *error = err;
     if (err != 0 || graphicBuffer->handle == 0) {
-        GraphicBuffer::dumpAllocationsToSystemLog();
+        if (err == NO_MEMORY) {
+            GraphicBuffer::dumpAllocationsToSystemLog();
+        }
         LOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
              "failed (%s), handle=%p",
                 w, h, strerror(-err), graphicBuffer->handle);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index af1ef04..15661f0 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -20,21 +20,20 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
 #include <utils/Atomic.h>
 #include <utils/Errors.h>
+#include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+#include <utils/threads.h>
 
-#include <binder/IMemory.h>
-#include <binder/Permission.h>
 #include <binder/BinderService.h>
+#include <binder/IMemory.h>
 
 #include <ui/PixelFormat.h>
+#include <surfaceflinger/IGraphicBufferAlloc.h>
 #include <surfaceflinger/ISurfaceComposer.h>
 #include <surfaceflinger/ISurfaceComposerClient.h>
-#include <surfaceflinger/IGraphicBufferAlloc.h>
 
 #include "Barrier.h"
 #include "Layer.h"
@@ -71,14 +70,12 @@
     sp<LayerBaseClient> getLayerUser(int32_t i) const;
 
 private:
-
     // ISurfaceComposerClient interface
     virtual sp<ISurface> createSurface(
             surface_data_t* params, const String8& name,
             DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
             uint32_t flags);
     virtual status_t destroySurface(SurfaceID surfaceId);
-    virtual status_t setState(int32_t count, const layer_state_t* states);
     virtual status_t onTransact(
         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
 
@@ -99,7 +96,7 @@
     GraphicBufferAlloc();
     virtual ~GraphicBufferAlloc();
     virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
-        PixelFormat format, uint32_t usage);
+        PixelFormat format, uint32_t usage, status_t* error);
 };
 
 // ---------------------------------------------------------------------------
@@ -150,6 +147,7 @@
 class SurfaceFlinger :
         public BinderService<SurfaceFlinger>,
         public BnSurfaceComposer,
+        public IBinder::DeathRecipient,
         protected Thread
 {
 public:
@@ -169,8 +167,7 @@
     virtual sp<IGraphicBufferAlloc>     createGraphicBufferAlloc();
     virtual sp<IMemoryHeap>             getCblk() const;
     virtual void                        bootFinished();
-    virtual void                        openGlobalTransaction();
-    virtual void                        closeGlobalTransaction();
+    virtual void                        setTransactionState(const Vector<ComposerState>& state);
     virtual status_t                    freezeDisplay(DisplayID dpy, uint32_t flags);
     virtual status_t                    unfreezeDisplay(DisplayID dpy, uint32_t flags);
     virtual int                         setOrientation(DisplayID dpy, int orientation, uint32_t flags);
@@ -197,6 +194,10 @@
     sp<Layer> getLayer(const sp<ISurface>& sur) const;
 
 private:
+    // DeathRecipient interface
+    virtual void binderDied(const wp<IBinder>& who);
+
+private:
     friend class Client;
     friend class LayerBase;
     friend class LayerBaseClient;
@@ -221,8 +222,7 @@
 
     status_t removeSurface(const sp<Client>& client, SurfaceID sid);
     status_t destroySurface(const wp<LayerBaseClient>& layer);
-    status_t setClientState(const sp<Client>& client,
-            int32_t count, const layer_state_t* states);
+    uint32_t setClientStateLocked(const sp<Client>& client, const layer_state_t& s);
 
     class LayerVector : public SortedVector< sp<LayerBase> > {
     public:
@@ -338,7 +338,6 @@
     mutable     Mutex                   mStateLock;
                 State                   mCurrentState;
     volatile    int32_t                 mTransactionFlags;
-    volatile    int32_t                 mTransactionCount;
                 Condition               mTransactionCV;
                 SortedVector< sp<LayerBase> > mLayerPurgatory;
                 bool                    mResizeTransationPending;
@@ -353,11 +352,7 @@
                 surface_flinger_cblk_t*     mServerCblk;
                 GLuint                      mWormholeTexName;
                 nsecs_t                     mBootTime;
-                Permission                  mHardwareTest;
-                Permission                  mAccessSurfaceFlinger;
-                Permission                  mReadFramebuffer;
-                Permission                  mDump;
-                
+
                 // Can only accessed from the main thread, these members
                 // don't need synchronization
                 State                       mDrawingState;
diff --git a/services/surfaceflinger/tests/resize/resize.cpp b/services/surfaceflinger/tests/resize/resize.cpp
index 18c54b3..56b2a8f 100644
--- a/services/surfaceflinger/tests/resize/resize.cpp
+++ b/services/surfaceflinger/tests/resize/resize.cpp
@@ -43,9 +43,9 @@
             PIXEL_FORMAT_RGB_565);
 
 
-    client->openTransaction();
+    SurfaceComposerClient::openGlobalTransaction();
     surface->setLayer(100000);
-    client->closeTransaction();
+    SurfaceComposerClient::closeGlobalTransaction();
 
     Surface::SurfaceInfo info;
     surface->lock(&info);
@@ -57,9 +57,9 @@
     android_memset16((uint16_t*)info.bits, 0x07E0, bpr*info.h);
     surface->unlockAndPost();
 
-    client->openTransaction();
+    SurfaceComposerClient::openGlobalTransaction();
     surface->setSize(320, 240);
-    client->closeTransaction();
+    SurfaceComposerClient::closeGlobalTransaction();
 
     
     IPCThreadState::self()->joinThreadPool();
diff --git a/services/surfaceflinger/tests/surface/surface.cpp b/services/surfaceflinger/tests/surface/surface.cpp
index 5265f91..8e1c3fe 100644
--- a/services/surfaceflinger/tests/surface/surface.cpp
+++ b/services/surfaceflinger/tests/surface/surface.cpp
@@ -39,9 +39,9 @@
     
     sp<SurfaceControl> surfaceControl = client->createSurface(
             getpid(), 0, 160, 240, PIXEL_FORMAT_RGB_565);
-    client->openTransaction();
+    SurfaceComposerClient::openGlobalTransaction();
     surfaceControl->setLayer(100000);
-    client->closeTransaction();
+    SurfaceComposerClient::closeGlobalTransaction();
 
     // pretend it went cross-process
     Parcel parcel;
diff --git a/services/tests/servicestests/res/raw/xt_qtaguid_extended b/services/tests/servicestests/res/raw/xt_qtaguid_extended
new file mode 100644
index 0000000..5bef3dd
--- /dev/null
+++ b/services/tests/servicestests/res/raw/xt_qtaguid_extended
@@ -0,0 +1,3 @@
+acct_tag_hex uid_tag_int iface rx_bytes rx_packets tx_bytes tx_packets teleported_goats
+0x0 1000 test0 1024 10 2048 20 2716057
+0x0000F00D00000000 1000 test0 512 5 512 5 3370318
diff --git a/services/tests/servicestests/res/raw/xt_qtaguid_typical b/services/tests/servicestests/res/raw/xt_qtaguid_typical
new file mode 100644
index 0000000..7c4f04e
--- /dev/null
+++ b/services/tests/servicestests/res/raw/xt_qtaguid_typical
@@ -0,0 +1,32 @@
+idx iface acct_tag_hex uid_tag_int rx_bytes tx_bytes
+1 wlan0 0x0 0 14615 4270
+2 wlan0 0x0 1000 5175 915
+3 wlan0 0x0 1021 3381 903
+4 wlan0 0x0 10004 333821 53558
+5 wlan0 0x0 10010 4888 37363
+6 wlan0 0x0 10013 52 104
+7 wlan0 0x74182ada00000000 10004 18725 1066
+8 rmnet0 0x0 0 301274 30244
+9 rmnet0 0x0 1000 304 441
+10 rmnet0 0x0 1013 2880 2272
+11 rmnet0 0x0 1021 31407 8430
+12 rmnet0 0x0 10003 32665 3814
+13 rmnet0 0x0 10004 2373141 420112
+14 rmnet0 0x0 10010 870370 1111727
+15 rmnet0 0x0 10013 240 240
+16 rmnet0 0x0 10016 16703 13512
+17 rmnet0 0x0 10017 3990 3269
+18 rmnet0 0x0 10018 474504 14516062
+19 rmnet0 0x0 10019 782804 71077
+20 rmnet0 0x0 10022 70671 49684
+21 rmnet0 0x0 10029 5785354 397159
+22 rmnet0 0x0 10033 2102 1686
+23 rmnet0 0x0 10034 15495464 227694
+24 rmnet0 0x0 10037 31184994 684122
+25 rmnet0 0x0 10051 298687 113485
+26 rmnet0 0x0 10056 29504 20669
+27 rmnet0 0x0 10069 683 596
+28 rmnet0 0x0 10072 34051 12453
+29 rmnet0 0x0 10077 7025393 213866
+30 rmnet0 0x0 10081 354 1178
+31 rmnet0 0x74182ada00000000 10037 28507378 437004
diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
new file mode 100644
index 0000000..ac7cb5a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
+import static com.android.server.NetworkManagementSocketTagger.tagToKernel;
+
+import android.content.res.Resources;
+import android.net.NetworkStats;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import com.android.frameworks.servicestests.R;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
+/**
+ * Tests for {@link NetworkManagementService}.
+ */
+@LargeTest
+public class NetworkManagementServiceTest extends AndroidTestCase {
+    private File mTestProc;
+    private NetworkManagementService mService;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mTestProc = getContext().getFilesDir();
+        mService = NetworkManagementService.createForTest(mContext, mTestProc);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        mService = null;
+
+        super.tearDown();
+    }
+
+    public void testNetworkStatsDetail() throws Exception {
+        stageFile(R.raw.xt_qtaguid_typical, new File(mTestProc, "net/xt_qtaguid/stats"));
+
+        final NetworkStats stats = mService.getNetworkStatsDetail();
+        assertEquals(31, stats.size);
+        assertStatsEntry(stats, "wlan0", 0, 0, 14615L, 4270L);
+        assertStatsEntry(stats, "wlan0", 10004, 0, 333821L, 53558L);
+        assertStatsEntry(stats, "wlan0", 10004, 1947740890, 18725L, 1066L);
+        assertStatsEntry(stats, "rmnet0", 10037, 0, 31184994L, 684122L);
+        assertStatsEntry(stats, "rmnet0", 10037, 1947740890, 28507378L, 437004L);
+    }
+
+    public void testNetworkStatsDetailExtended() throws Exception {
+        stageFile(R.raw.xt_qtaguid_extended, new File(mTestProc, "net/xt_qtaguid/stats"));
+
+        final NetworkStats stats = mService.getNetworkStatsDetail();
+        assertEquals(2, stats.size);
+        assertStatsEntry(stats, "test0", 1000, 0, 1024L, 2048L);
+        assertStatsEntry(stats, "test0", 1000, 0xF00D, 512L, 512L);
+    }
+
+    public void testKernelTags() throws Exception {
+        assertEquals("0", tagToKernel(0x0));
+        assertEquals("214748364800", tagToKernel(0x32));
+        assertEquals("9223372032559808512", tagToKernel(Integer.MAX_VALUE));
+        assertEquals("0", tagToKernel(Integer.MIN_VALUE));
+        assertEquals("9223369837831520256", tagToKernel(Integer.MIN_VALUE - 512));
+
+        assertEquals(0, kernelToTag("0x0000000000000000"));
+        assertEquals(0x32, kernelToTag("0x0000003200000000"));
+        assertEquals(2147483647, kernelToTag("0x7fffffff00000000"));
+        assertEquals(0, kernelToTag("0x0000000000000000"));
+        assertEquals(2147483136, kernelToTag("0x7FFFFE0000000000"));
+
+    }
+
+    /**
+     * Copy a {@link Resources#openRawResource(int)} into {@link File} for
+     * testing purposes.
+     */
+    private void stageFile(int rawId, File file) throws Exception {
+        new File(file.getParent()).mkdirs();
+        InputStream in = null;
+        OutputStream out = null;
+        try {
+            in = getContext().getResources().openRawResource(rawId);
+            out = new FileOutputStream(file);
+            Streams.copy(in, out);
+        } finally {
+            IoUtils.closeQuietly(in);
+            IoUtils.closeQuietly(out);
+        }
+    }
+
+    private static void assertStatsEntry(
+            NetworkStats stats, String iface, int uid, int tag, long rx, long tx) {
+        final int i = stats.findIndex(iface, uid, tag);
+        assertEquals(rx, stats.rx[i]);
+        assertEquals(tx, stats.tx[i]);
+    }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 07e5425..b4ac987 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -41,7 +41,9 @@
 import android.app.INotificationManager;
 import android.app.IProcessObserver;
 import android.content.Intent;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.Signature;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
 import android.net.INetworkPolicyListener;
@@ -54,6 +56,7 @@
 import android.net.NetworkStats;
 import android.net.NetworkTemplate;
 import android.os.Binder;
+import android.os.INetworkManagementService;
 import android.os.IPowerManager;
 import android.test.AndroidTestCase;
 import android.test.mock.MockPackageManager;
@@ -63,12 +66,17 @@
 import android.util.TrustedTime;
 
 import com.android.server.net.NetworkPolicyManagerService;
+import com.google.common.util.concurrent.AbstractFuture;
 
 import org.easymock.Capture;
 import org.easymock.EasyMock;
+import org.easymock.IAnswer;
 
 import java.io.File;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 /**
  * Tests for {@link NetworkPolicyManagerService}.
@@ -88,6 +96,7 @@
     private IActivityManager mActivityManager;
     private IPowerManager mPowerManager;
     private INetworkStatsService mStatsService;
+    private INetworkManagementService mNetworkManagement;
     private INetworkPolicyListener mPolicyListener;
     private TrustedTime mTime;
     private IConnectivityManager mConnManager;
@@ -118,22 +127,40 @@
                     public String[] getPackagesForUid(int uid) {
                         return new String[] { "com.example" };
                     }
+
+                    @Override
+                    public PackageInfo getPackageInfo(String packageName, int flags) {
+                        final PackageInfo info = new PackageInfo();
+                        final Signature signature;
+                        if ("android".equals(packageName)) {
+                            signature = new Signature("F00D");
+                        } else {
+                            signature = new Signature("DEAD");
+                        }
+                        info.signatures = new Signature[] { signature };
+                        return info;
+                    }
                 };
             }
         };
 
         mPolicyDir = getContext().getFilesDir();
+        for (File file : mPolicyDir.listFiles()) {
+            file.delete();
+        }
 
         mActivityManager = createMock(IActivityManager.class);
         mPowerManager = createMock(IPowerManager.class);
         mStatsService = createMock(INetworkStatsService.class);
+        mNetworkManagement = createMock(INetworkManagementService.class);
         mPolicyListener = createMock(INetworkPolicyListener.class);
         mTime = createMock(TrustedTime.class);
         mConnManager = createMock(IConnectivityManager.class);
         mNotifManager = createMock(INotificationManager.class);
 
         mService = new NetworkPolicyManagerService(
-                mServiceContext, mActivityManager, mPowerManager, mStatsService, mTime, mPolicyDir);
+                mServiceContext, mActivityManager, mPowerManager, mStatsService,
+                mNetworkManagement, mTime, mPolicyDir);
         mService.bindConnectivityManager(mConnManager);
         mService.bindNotificationManager(mNotifManager);
 
@@ -152,6 +179,9 @@
         expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
         expectTime(System.currentTimeMillis());
 
+        // default behavior is background data enabled
+        expect(mConnManager.getBackgroundDataSetting()).andReturn(true);
+
         replay();
         mService.systemReady();
         verifyAndReset();
@@ -228,81 +258,123 @@
     }
 
     public void testScreenChangesRules() throws Exception {
-        // push strict policy for foreground uid, verify ALLOW rule
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        Future<Void> future;
+
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
         mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        future.get();
+        verifyAndReset();
+
+        // push strict policy for foreground uid, verify ALLOW rule
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
         mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+        future.get();
         verifyAndReset();
 
         // now turn screen off and verify REJECT rule
         expect(mPowerManager.isScreenOn()).andReturn(false).atLeastOnce();
-        expectRulesChanged(UID_A, RULE_REJECT_METERED);
+        expectSetUidNetworkRules(UID_A, true);
+        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
         replay();
         mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
+        future.get();
         verifyAndReset();
 
         // and turn screen back on, verify ALLOW rule restored
         expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
         mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
+        future.get();
         verifyAndReset();
     }
 
     public void testPolicyNone() throws Exception {
+        Future<Void> future;
+
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        future.get();
+        verifyAndReset();
+
         // POLICY_NONE should RULE_ALLOW in foreground
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
         mService.setUidPolicy(UID_A, POLICY_NONE);
-        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        future.get();
         verifyAndReset();
 
         // POLICY_NONE should RULE_ALLOW in background
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
         mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        future.get();
         verifyAndReset();
     }
 
     public void testPolicyReject() throws Exception {
+        Future<Void> future;
+
         // POLICY_REJECT should RULE_ALLOW in background
-        expectRulesChanged(UID_A, RULE_REJECT_METERED);
+        expectSetUidNetworkRules(UID_A, true);
+        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
         replay();
         mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+        future.get();
         verifyAndReset();
 
         // POLICY_REJECT should RULE_ALLOW in foreground
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
         mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        future.get();
         verifyAndReset();
 
         // POLICY_REJECT should RULE_REJECT in background
-        expectRulesChanged(UID_A, RULE_REJECT_METERED);
+        expectSetUidNetworkRules(UID_A, true);
+        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
         replay();
         mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        future.get();
         verifyAndReset();
     }
 
     public void testPolicyRejectAddRemove() throws Exception {
+        Future<Void> future;
+
         // POLICY_NONE should have RULE_ALLOW in background
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
-        mService.setUidPolicy(UID_A, POLICY_NONE);
         mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        mService.setUidPolicy(UID_A, POLICY_NONE);
+        future.get();
         verifyAndReset();
 
         // adding POLICY_REJECT should cause RULE_REJECT
-        expectRulesChanged(UID_A, RULE_REJECT_METERED);
+        expectSetUidNetworkRules(UID_A, true);
+        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
         replay();
         mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+        future.get();
         verifyAndReset();
 
         // removing POLICY_REJECT should return us to RULE_ALLOW
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
         mService.setUidPolicy(UID_A, POLICY_NONE);
+        future.get();
         verifyAndReset();
     }
 
@@ -350,6 +422,7 @@
         long elapsedRealtime = 0;
         NetworkState[] state = null;
         NetworkStats stats = null;
+        Future<Void> future;
 
         final long TIME_FEB_15 = 1171497600000L;
         final long TIME_MAR_10 = 1173484800000L;
@@ -360,10 +433,11 @@
         state = new NetworkState[] { buildWifi() };
         expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
         expectTime(TIME_MAR_10 + elapsedRealtime);
-        expectMeteredIfacesChanged();
+        future = expectMeteredIfacesChanged();
 
         replay();
         mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+        future.get();
         verifyAndReset();
 
         // now change cycle to be on 15th, and test in early march, to verify we
@@ -377,30 +451,38 @@
         expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
                 .andReturn(stats).atLeastOnce();
 
-        // expect that quota remaining should be 1536 bytes
-        // TODO: write up NetworkManagementService mock
+        // TODO: consider making strongly ordered mock
+        expectRemoveInterfaceQuota(TEST_IFACE);
+        expectSetInterfaceQuota(TEST_IFACE, 1536L);
 
         expectClearNotifications();
-        expectMeteredIfacesChanged(TEST_IFACE);
+        future = expectMeteredIfacesChanged(TEST_IFACE);
 
         replay();
         setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L));
+        future.get();
         verifyAndReset();
     }
 
     public void testUidRemovedPolicyCleared() throws Exception {
+        Future<Void> future;
+
         // POLICY_REJECT should RULE_REJECT in background
-        expectRulesChanged(UID_A, RULE_REJECT_METERED);
+        expectSetUidNetworkRules(UID_A, true);
+        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
         replay();
         mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+        future.get();
         verifyAndReset();
 
         // uninstall should clear RULE_REJECT
-        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        expectSetUidNetworkRules(UID_A, false);
+        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
         replay();
         final Intent intent = new Intent(ACTION_UID_REMOVED);
         intent.putExtra(EXTRA_UID, UID_A);
         mServiceContext.sendBroadcast(intent);
+        future.get();
         verifyAndReset();
     }
 
@@ -435,25 +517,62 @@
         expectLastCall().anyTimes();
     }
 
-    private void expectRulesChanged(int uid, int policy) throws Exception {
-        mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
+    private void expectSetInterfaceQuota(String iface, long quota) throws Exception {
+        mNetworkManagement.setInterfaceQuota(iface, quota);
         expectLastCall().atLeastOnce();
     }
 
-    private void expectMeteredIfacesChanged(String... ifaces) throws Exception {
-        mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
+    private void expectRemoveInterfaceQuota(String iface) throws Exception {
+        mNetworkManagement.removeInterfaceQuota(iface);
         expectLastCall().atLeastOnce();
     }
 
+    private void expectSetUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces)
+            throws Exception {
+        mNetworkManagement.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
+        expectLastCall().atLeastOnce();
+    }
+
+    private Future<Void> expectRulesChanged(int uid, int policy) throws Exception {
+        final FutureAnswer future = new FutureAnswer();
+        mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
+        expectLastCall().andAnswer(future);
+        return future;
+    }
+
+    private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception {
+        final FutureAnswer future = new FutureAnswer();
+        mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
+        expectLastCall().andAnswer(future);
+        return future;
+    }
+
+    private static class FutureAnswer extends AbstractFuture<Void> implements IAnswer<Void> {
+        @Override
+        public Void get() throws InterruptedException, ExecutionException {
+            try {
+                return get(5, TimeUnit.SECONDS);
+            } catch (TimeoutException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        public Void answer() {
+            set(null);
+            return null;
+        }
+    }
+
     private void replay() {
-        EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener, mTime,
-                mConnManager, mNotifManager);
+        EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
+                mNetworkManagement, mTime, mConnManager, mNotifManager);
     }
 
     private void verifyAndReset() {
-        EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener, mTime,
-                mConnManager, mNotifManager);
-        EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener, mTime,
-                mConnManager, mNotifManager);
+        EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
+                mNetworkManagement, mTime, mConnManager, mNotifManager);
+        EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
+                mNetworkManagement, mTime, mConnManager, mNotifManager);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index 636d059..f2c28bb 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -59,7 +59,6 @@
 import android.telephony.TelephonyManager;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
 import android.util.TrustedTime;
 
 import com.android.server.net.NetworkStatsService;
diff --git a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
index dea67f3..ffabb7b 100644
--- a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
+++ b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
@@ -94,9 +94,6 @@
      */
     public PhoneNumberFormattingTextWatcher(String countryCode) {
         if (countryCode == null) throw new IllegalArgumentException();
-        // TODO: remove this once CountryDetector.detectCountry().getCountryIso() is fixed to always
-        // return uppercase. Tracked at b/4941319.
-        countryCode = countryCode.toUpperCase(Locale.ENGLISH);
         mFormatter = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(countryCode);
     }
 
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index fce7cdc..2f010e5 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -473,8 +473,8 @@
                 + " EmergOnly=" + mIsEmergencyOnly);
     }
 
-    public void setStateOutOfService() {
-        mState = STATE_OUT_OF_SERVICE;
+    private void setNullState(int state) {
+        mState = state;
         mRoaming = false;
         mOperatorAlphaLong = null;
         mOperatorAlphaShort = null;
@@ -491,23 +491,12 @@
         mIsEmergencyOnly = false;
     }
 
-    // TODO - can't this be combined with the above method?
+    public void setStateOutOfService() {
+        setNullState(STATE_OUT_OF_SERVICE);
+    }
+
     public void setStateOff() {
-        mState = STATE_POWER_OFF;
-        mRoaming = false;
-        mOperatorAlphaLong = null;
-        mOperatorAlphaShort = null;
-        mOperatorNumeric = null;
-        mIsManualNetworkSelection = false;
-        mRadioTechnology = 0;
-        mCssIndicator = false;
-        mNetworkId = -1;
-        mSystemId = -1;
-        mCdmaRoamingIndicator = -1;
-        mCdmaDefaultRoamingIndicator = -1;
-        mCdmaEriIconIndex = -1;
-        mCdmaEriIconMode = -1;
-        mIsEmergencyOnly = false;
+        setNullState(STATE_POWER_OFF);
     }
 
     public void setState(int state) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 184d665..66120a1 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -191,10 +191,6 @@
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getDeviceId() {
-        if (!isVoiceCapable()) {
-            return null;
-        }
-
         try {
             return getSubscriberInfo().getDeviceId();
         } catch (RemoteException ex) {
diff --git a/telephony/java/com/android/internal/telephony/ApnContext.java b/telephony/java/com/android/internal/telephony/ApnContext.java
index 5ec00e8..a52f1ca 100644
--- a/telephony/java/com/android/internal/telephony/ApnContext.java
+++ b/telephony/java/com/android/internal/telephony/ApnContext.java
@@ -16,8 +16,6 @@
 
 package com.android.internal.telephony;
 
-import android.app.PendingIntent;
-
 import android.util.Log;
 import java.util.ArrayList;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -49,8 +47,6 @@
 
     String mReason;
 
-    PendingIntent mReconnectIntent;
-
     /**
      * user/app requested connection on this APN
      */
@@ -90,9 +86,9 @@
 
     public synchronized void setDataConnectionAc(DataConnectionAc dcac) {
         if (dcac != null) {
-            dcac.addApnContext(this);
+            dcac.addApnContextSync(this);
         } else {
-            if (mDataConnectionAc != null) mDataConnectionAc.removeApnContext(this);
+            if (mDataConnectionAc != null) mDataConnectionAc.removeApnContextSync(this);
         }
         mDataConnectionAc = dcac;
     }
@@ -169,16 +165,6 @@
         return mReason;
     }
 
-    public synchronized void setReconnectIntent(PendingIntent intent) {
-        if (DBG)
-            log("set ReconnectIntent for type " + mApnType);
-        mReconnectIntent = intent;
-    }
-
-    public synchronized PendingIntent getReconnectIntent() {
-        return mReconnectIntent;
-    }
-
     public boolean isReady() {
         return mDataEnabled.get() && mDependencyMet.get();
     }
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index ab93e2a..68e0045 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -526,16 +526,6 @@
                   + countryIso);
         }
 
-        // Temp workaround: The current libphonenumber library requires
-        // the countryIso to be uppercase (e.g. "US") but the
-        // detector.detectCountry().getCountryIso() call currently returns
-        // "us".  Passing "us" to util.parse() will just result in a
-        // NumberParseException.
-        // So force the countryIso to uppercase for now.
-        // TODO: remove this once getCountryIso() is fixed to always
-        // return uppercase.
-        countryIso = countryIso.toUpperCase();
-
         PhoneNumber pn = null;
         try {
             if (VDBG) Log.v(TAG, "parsing '" + number
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index cb8b0e5..5c84fdc 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -22,6 +22,7 @@
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
 
+import android.app.PendingIntent;
 import android.net.LinkAddress;
 import android.net.LinkCapabilities;
 import android.net.LinkProperties;
@@ -35,8 +36,10 @@
 import android.os.SystemProperties;
 import android.text.TextUtils;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -68,6 +71,8 @@
     protected static int mCount;
     protected AsyncChannel mAc;
 
+    private List<ApnContext> mApnList = null;
+    PendingIntent mReconnectIntent = null;
 
     /**
      * Used internally for saving connecting parameters.
@@ -250,6 +255,8 @@
             addState(mDisconnectingState, mDefaultState);
             addState(mDisconnectingErrorCreatingConnection, mDefaultState);
         setInitialState(mInactiveState);
+
+        mApnList = new ArrayList<ApnContext>();
         if (DBG) log("DataConnection constructor X");
     }
 
@@ -662,7 +669,41 @@
                     mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_REFCOUNT, mRefCount);
                     break;
                 }
-
+                case DataConnectionAc.REQ_ADD_APNCONTEXT: {
+                    ApnContext apnContext = (ApnContext) msg.obj;
+                    if (VDBG) log("REQ_ADD_APNCONTEXT apn=" + apnContext.getApnType());
+                    if (!mApnList.contains(apnContext)) {
+                        mApnList.add(apnContext);
+                    }
+                    mAc.replyToMessage(msg, DataConnectionAc.RSP_ADD_APNCONTEXT);
+                    break;
+                }
+                case DataConnectionAc.REQ_REMOVE_APNCONTEXT: {
+                    ApnContext apnContext = (ApnContext) msg.obj;
+                    if (VDBG) log("REQ_REMOVE_APNCONTEXT apn=" + apnContext.getApnType());
+                    mApnList.remove(apnContext);
+                    mAc.replyToMessage(msg, DataConnectionAc.RSP_REMOVE_APNCONTEXT);
+                    break;
+                }
+                case DataConnectionAc.REQ_GET_APNCONTEXT_LIST: {
+                    if (VDBG) log("REQ_GET_APNCONTEXT_LIST num in list=" + mApnList.size());
+                    mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_APNCONTEXT_LIST,
+                                       new ArrayList(mApnList));
+                    break;
+                }
+                case DataConnectionAc.REQ_SET_RECONNECT_INTENT: {
+                    PendingIntent intent = (PendingIntent) msg.obj;
+                    if (VDBG) log("REQ_SET_RECONNECT_INTENT");
+                    mReconnectIntent = intent;
+                    mAc.replyToMessage(msg, DataConnectionAc.RSP_SET_RECONNECT_INTENT);
+                    break;
+                }
+                case DataConnectionAc.REQ_GET_RECONNECT_INTENT: {
+                    if (VDBG) log("REQ_GET_RECONNECT_INTENT");
+                    mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_RECONNECT_INTENT,
+                                       mReconnectIntent);
+                    break;
+                }
                 case EVENT_CONNECT:
                     if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected");
                     ConnectionParams cp = (ConnectionParams) msg.obj;
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionAc.java b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
index e23f1cc..309dbed 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionAc.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
@@ -19,6 +19,7 @@
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 
+import android.app.PendingIntent;
 import android.net.LinkCapabilities;
 import android.net.LinkProperties;
 import android.net.ProxyProperties;
@@ -26,8 +27,6 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
 
 /**
  * AsyncChannel to a DataConnection
@@ -35,7 +34,6 @@
 public class DataConnectionAc extends AsyncChannel {
     private static final boolean DBG = false;
     private String mLogTag;
-    private List<ApnContext> mApnList = null;
 
     public DataConnection dataConnection;
 
@@ -68,6 +66,21 @@
     public static final int REQ_GET_REFCOUNT = BASE + 16;
     public static final int RSP_GET_REFCOUNT = BASE + 17;
 
+    public static final int REQ_ADD_APNCONTEXT = BASE + 18;
+    public static final int RSP_ADD_APNCONTEXT = BASE + 19;
+
+    public static final int REQ_REMOVE_APNCONTEXT = BASE + 20;
+    public static final int RSP_REMOVE_APNCONTEXT = BASE + 21;
+
+    public static final int REQ_GET_APNCONTEXT_LIST = BASE + 22;
+    public static final int RSP_GET_APNCONTEXT_LIST = BASE + 23;
+
+    public static final int REQ_SET_RECONNECT_INTENT = BASE + 24;
+    public static final int RSP_SET_RECONNECT_INTENT = BASE + 25;
+
+    public static final int REQ_GET_RECONNECT_INTENT = BASE + 26;
+    public static final int RSP_GET_RECONNECT_INTENT = BASE + 27;
+
     /**
      * enum used to notify action taken or necessary to be
      * taken after the link property is changed.
@@ -91,7 +104,6 @@
     public DataConnectionAc(DataConnection dc, String logTag) {
         dataConnection = dc;
         mLogTag = logTag;
-        mApnList = Collections.synchronizedList(new ArrayList<ApnContext>());
     }
 
     /**
@@ -379,32 +391,147 @@
     }
 
     /**
-     * Add ApnContext association.
+     * Request to add ApnContext association.
+     * Response RSP_ADD_APNCONTEXT when complete.
+     */
+    public void reqAddApnContext(ApnContext apnContext) {
+        Message response = sendMessageSynchronously(REQ_ADD_APNCONTEXT, apnContext);
+        if (DBG) log("reqAddApnContext");
+    }
+
+    /**
+     * Add ApnContext association synchronoulsy.
      *
      * @param ApnContext to associate
      */
-    public void addApnContext(ApnContext apnContext) {
-        if (!mApnList.contains(apnContext)) {
-            mApnList.add(apnContext);
+    public void addApnContextSync(ApnContext apnContext) {
+        Message response = sendMessageSynchronously(REQ_ADD_APNCONTEXT, apnContext);
+        if ((response != null) && (response.what == RSP_ADD_APNCONTEXT)) {
+            if (DBG) log("addApnContext ok");
+        } else {
+            log("addApnContext error response=" + response);
         }
     }
 
     /**
+     * Request to remove ApnContext association.
+     * Response RSP_REMOVE_APNCONTEXT when complete.
+     */
+    public void reqRemomveApnContext(ApnContext apnContext) {
+        Message response = sendMessageSynchronously(REQ_REMOVE_APNCONTEXT, apnContext);
+        if (DBG) log("reqRemomveApnContext");
+    }
+
+    /**
      * Remove ApnContext associateion.
      *
      * @param ApnContext to dissociate
      */
-    public void removeApnContext(ApnContext apnContext) {
-        mApnList.remove(apnContext);
+    public void removeApnContextSync(ApnContext apnContext) {
+        Message response = sendMessageSynchronously(REQ_REMOVE_APNCONTEXT, apnContext);
+        if ((response != null) && (response.what == RSP_REMOVE_APNCONTEXT)) {
+            if (DBG) log("removeApnContext ok");
+        } else {
+            log("removeApnContext error response=" + response);
+        }
     }
 
     /**
-     * Retrieve collection of ApnContext currently associated with the DataConnectionAc.
+     * Request to retrive ApnContext List associated with DC.
+     * Response RSP_GET_APNCONTEXT_LIST when complete.
+     */
+    public void reqGetApnList(ApnContext apnContext) {
+        Message response = sendMessageSynchronously(REQ_GET_APNCONTEXT_LIST);
+        if (DBG) log("reqGetApnList");
+    }
+
+    /**
+     * Retrieve Collection of ApnContext from the response message.
+     *
+     * @param Message sent from DC in response to REQ_GET_APNCONTEXT_LIST.
+     * @return Collection of ApnContext
+     */
+    public Collection<ApnContext> rspApnList(Message response) {
+        Collection<ApnContext> retVal = (Collection<ApnContext>)response.obj;
+        if (retVal == null) retVal = new ArrayList<ApnContext>();
+        return retVal;
+    }
+
+    /**
+     * Retrieve collection of ApnContext currently associated with
+     * the DataConnectionA synchronously.
      *
      * @return Collection of ApnContext
      */
-    public Collection<ApnContext> getApnList() {
-        return mApnList;
+    public Collection<ApnContext> getApnListSync() {
+        Message response = sendMessageSynchronously(REQ_GET_APNCONTEXT_LIST);
+        if ((response != null) && (response.what == RSP_GET_APNCONTEXT_LIST)) {
+            if (DBG) log("getApnList ok");
+            return rspApnList(response);
+        } else {
+            log("getApnList error response=" + response);
+            // return dummy list with no entry
+            return new ArrayList<ApnContext>();
+        }
+    }
+
+    /**
+     * Request to set Pending ReconnectIntent to DC.
+     * Response RSP_SET_RECONNECT_INTENT when complete.
+     */
+    public void reqSetReconnectIntent(PendingIntent intent) {
+        Message response = sendMessageSynchronously(REQ_SET_RECONNECT_INTENT, intent);
+        if (DBG) log("reqSetReconnectIntent");
+    }
+
+    /**
+     * Set pending reconnect intent to DC synchronously.
+     *
+     * @param PendingIntent to set.
+     */
+    public void setReconnectIntentSync(PendingIntent intent) {
+        Message response = sendMessageSynchronously(REQ_SET_RECONNECT_INTENT, intent);
+        if ((response != null) && (response.what == RSP_SET_RECONNECT_INTENT)) {
+            if (DBG) log("setReconnectIntent ok");
+        } else {
+            log("setReconnectIntent error response=" + response);
+        }
+    }
+
+    /**
+     * Request to get Pending ReconnectIntent to DC.
+     * Response RSP_GET_RECONNECT_INTENT when complete.
+     */
+    public void reqGetReconnectIntent() {
+        Message response = sendMessageSynchronously(REQ_GET_RECONNECT_INTENT);
+        if (DBG) log("reqGetReconnectIntent");
+    }
+
+    /**
+     * Retrieve reconnect intent from response message from DC.
+     *
+     * @param Message which contains the reconnect intent.
+     * @return PendingIntent from the response.
+     */
+    public PendingIntent rspReconnectIntent(Message response) {
+        PendingIntent retVal = (PendingIntent) response.obj;
+        return retVal;
+    }
+
+    /**
+     * Retrieve reconnect intent currently set in DC synchronously.
+     *
+     * @return PendingIntent reconnect intent current ly set in DC
+     */
+    public PendingIntent getReconnectIntentSync() {
+        Message response = sendMessageSynchronously(REQ_GET_RECONNECT_INTENT);
+        if ((response != null) && (response.what == RSP_GET_RECONNECT_INTENT)) {
+            if (DBG) log("getReconnectIntent ok");
+            return rspReconnectIntent(response);
+        } else {
+            log("getReconnectIntent error response=" + response);
+            return null;
+        }
     }
 
     private void log(String s) {
diff --git a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 910905a..aa7568b 100644
--- a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -21,6 +21,7 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
@@ -55,8 +56,13 @@
     }
 
     public void notifyServiceState(Phone sender) {
+        ServiceState ss = sender.getServiceState();
+        if (ss == null) {
+            ss = new ServiceState();
+            ss.setStateOutOfService();
+        }
         try {
-            mRegistry.notifyServiceState(sender.getServiceState());
+            mRegistry.notifyServiceState(ss);
         } catch (RemoteException ex) {
             // system process is dead
         }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index bac15a6..8a60b5a 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -1030,13 +1030,8 @@
             case EVENT_NV_READY:{
                 Log.d(LOG_TAG, "Event EVENT_NV_READY Received");
                 //Inform the Service State Tracker
-                mEriManager.loadEriFile();
                 mNvLoadedRegistrants.notifyRegistrants();
-                if(mEriManager.isEriFileLoaded()) {
-                    // when the ERI file is loaded
-                    Log.d(LOG_TAG, "ERI read, notify registrants");
-                    mEriFileLoadedRegistrants.notifyRegistrants();
-                }
+                prepareEri();
             }
             break;
 
@@ -1424,6 +1419,19 @@
         return false;
     }
 
+    public void prepareEri() {
+        mEriManager.loadEriFile();
+        if(mEriManager.isEriFileLoaded()) {
+            // when the ERI file is loaded
+            log("ERI read, notify registrants");
+            mEriFileLoadedRegistrants.notifyRegistrants();
+        }
+    }
+
+    public boolean isEriFileLoaded() {
+        return mEriManager.isEriFileLoaded();
+    }
+
     protected void log(String s) {
         if (DBG)
             Log.d(LOG_TAG, "[CDMAPhone] " + s);
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
index 318cf37..459cf87 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -21,13 +21,15 @@
 import com.android.internal.telephony.EventLogTags;
 import com.android.internal.telephony.RILConstants;
 
+import android.content.Intent;
 import android.telephony.SignalStrength;
 import android.telephony.ServiceState;
 import android.telephony.cdma.CdmaCellLocation;
 import android.os.AsyncResult;
 import android.os.Message;
+import android.provider.Telephony.Intents;
 
-
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.EventLog;
 
@@ -37,6 +39,7 @@
     CDMALTEPhone mCdmaLtePhone;
 
     private ServiceState  mLteSS;  // The last LTE state from Voice Registration
+    private String mCurrentSpn = null;
 
     public CdmaLteServiceStateTracker(CDMALTEPhone phone) {
         super(phone);
@@ -73,6 +76,9 @@
             pollState();
             // Signal strength polling stops when radio is off.
             queueNextSignalStrengthPoll();
+
+            // load ERI file
+            phone.prepareEri();
             break;
         case EVENT_SIM_RECORDS_LOADED:
             CdmaLteUiccRecords sim = (CdmaLteUiccRecords)phone.mIccRecords;
@@ -84,6 +90,10 @@
                 mIsMinInfoReady = true;
                 updateOtaspState();
             }
+            // SID/NID/PRL is loaded. Poll service state
+            // again to update to the roaming state with
+            // the latest variables.
+            pollState();
             break;
         default:
             super.handleMessage(msg);
@@ -319,7 +329,7 @@
         }
 
         if (hasChanged) {
-            if (cm.getNvState().isNVReady()) {
+            if (phone.isEriFileLoaded()) {
                 String eriText;
                 // Now the CDMAPhone sees the new ServiceState so it can get the
                 // new ERI text
@@ -334,13 +344,6 @@
                 }
                 ss.setOperatorAlphaLong(eriText);
             }
-            if (cm.getSimState().isSIMReady()) {
-                // SIM is found on the device. Read the operator name from the card.
-                ss.setOperatorAlphaLong(phone.mIccRecords.getServiceProviderName());
-
-                // If SIM card is present, Eri will not be used. Turn it off
-                ss.setCdmaEriIconIndex(EriInfo.ROAMING_INDICATOR_OFF);
-            }
 
             String operatorNumeric;
 
@@ -465,6 +468,43 @@
     }
 
     @Override
+    protected void updateSpnDisplay() {
+        // mOperatorAlphaLong contains the ERI text
+        String plmn = ss.getOperatorAlphaLong();
+
+        boolean showSpn = false;
+        String spn = null;
+        if (cm.getSimState().isSIMReady()) {
+            // SIM is found on the device. Read the operator name from the card.
+            showSpn = ((CdmaLteUiccRecords)phone.mIccRecords).getCsimSpnDisplayCondition();
+            spn = phone.mIccRecords.getServiceProviderName();
+
+            // double check we are not printing identicall test
+            if (TextUtils.equals(plmn, spn)) showSpn = false;
+        }
+
+        if (!TextUtils.equals(plmn, mCurPlmn) ||
+            !TextUtils.equals(spn, mCurrentSpn)) {
+            boolean showPlmn = plmn != null;
+            if (DBG) {
+                log(String.format("updateSpnDisplay: changed sending intent" +
+                                  " showPlmn='%b' plmn='%s' showSpn='%b' spn='%s'",
+                                  showPlmn, plmn, showSpn, spn));
+            }
+            Intent intent = new Intent(Intents.SPN_STRINGS_UPDATED_ACTION);
+            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+            intent.putExtra(Intents.EXTRA_SHOW_SPN, showSpn);
+            intent.putExtra(Intents.EXTRA_SPN, spn);
+            intent.putExtra(Intents.EXTRA_SHOW_PLMN, showPlmn);
+            intent.putExtra(Intents.EXTRA_PLMN, plmn);
+            phone.getContext().sendStickyBroadcast(intent);
+        }
+
+        mCurPlmn = plmn;
+        mCurrentSpn = spn;
+    }
+
+    @Override
     protected void log(String s) {
         Log.d(LOG_TAG, "[CdmaLteSST] " + s);
     }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
index 73b5d97..10515f7 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
@@ -38,7 +38,7 @@
     // From CSIM application
     private byte[] mEFpl = null;
     private byte[] mEFli = null;
-    boolean csimSpnDisplayCondition = false;
+    boolean mCsimSpnDisplayCondition = false;
     private String mMdn;
     private String mMin;
     private String mPrlVersion;
@@ -235,7 +235,7 @@
                      IccUtils.bytesToHexString(data));
 
         // C.S0065 for EF_SPN decoding
-        csimSpnDisplayCondition = ((0x02 & data[0]) > 0)?true:false;
+        mCsimSpnDisplayCondition = ((0x01 & data[0]) != 0) ? true : false;
 
         int encoding = data[1];
         int language = data[2];
@@ -272,7 +272,7 @@
             log("spn decode error: " + e);
         }
         if (DBG) log("spn=" + spn);
-        if (DBG) log("spnCondition=" + csimSpnDisplayCondition);
+        if (DBG) log("spnCondition=" + mCsimSpnDisplayCondition);
         phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, spn);
     }
 
@@ -437,6 +437,10 @@
         return mPrlVersion;
     }
 
+    public boolean getCsimSpnDisplayCondition() {
+        return mCsimSpnDisplayCondition;
+    }
+
     @Override
     public boolean isProvisioned() {
         // If UICC card has CSIM app, look for MDN and MIN field
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 5ebdd22..24a468a 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -127,7 +127,7 @@
     private static final String WAKELOCK_TAG = "ServiceStateTracker";
 
     /** Contains the name of the registered network in CDMA (either ONS or ERI text). */
-    private String curPlmn = null;
+    protected String mCurPlmn = null;
 
     protected String mMdn;
     private int mHomeSystemId[] = null;
@@ -484,7 +484,7 @@
 
         // mOperatorAlphaLong contains the ERI text
         String plmn = ss.getOperatorAlphaLong();
-        if (!TextUtils.equals(plmn, curPlmn)) {
+        if (!TextUtils.equals(plmn, mCurPlmn)) {
             // Allow A blank plmn, "" to set showPlmn to true. Previously, we
             // would set showPlmn to true only if plmn was not empty, i.e. was not
             // null and not blank. But this would cause us to incorrectly display
@@ -503,7 +503,7 @@
             phone.getContext().sendStickyBroadcast(intent);
         }
 
-        curPlmn = plmn;
+        mCurPlmn = plmn;
     }
 
     @Override
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
index 9695344..1f24b58 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
@@ -76,8 +76,6 @@
                 + "' APN: '" + mApn.apn
                 + "' proxy: '" + mApn.proxy + "' port: '" + mApn.port);
 
-        setHttpProxy (mApn.proxy, mApn.port);
-
         createTime = -1;
         lastFailTime = -1;
         lastFailCause = FailCause.NONE;
@@ -152,38 +150,6 @@
         Log.d(LOG_TAG, "[" + getName() + "] " + s);
     }
 
-    private void setHttpProxy(String httpProxy, String httpPort) {
-
-        if (DBG) log("set http proxy for"
-                + "' APN: '" + mActiveApnType
-                + "' proxy: '" + mApn.proxy + "' port: '" + mApn.port);
-        if(TextUtils.equals(mActiveApnType, Phone.APN_TYPE_DEFAULT)) {
-            if (httpProxy == null || httpProxy.length() == 0) {
-                phone.setSystemProperty("net.gprs.http-proxy", null);
-                return;
-            }
-
-            if (httpPort == null || httpPort.length() == 0) {
-                httpPort = "8080";     // Default to port 8080
-            }
-
-            phone.setSystemProperty("net.gprs.http-proxy",
-                    "http://" + httpProxy + ":" + httpPort + "/");
-        } else {
-            if (httpProxy == null || httpProxy.length() == 0) {
-                phone.setSystemProperty("net.gprs.http-proxy." + mActiveApnType, null);
-                return;
-            }
-
-            if (httpPort == null || httpPort.length() == 0) {
-                httpPort = "8080";  // Default to port 8080
-            }
-
-            phone.setSystemProperty("net.gprs.http-proxy." + mActiveApnType,
-                    "http://" + httpProxy + ":" + httpPort + "/");
-        }
-    }
-
     private boolean isIpAddress(String address) {
         if (address == null) return false;
 
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 1ac012f..df5898b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -125,14 +125,20 @@
         if (DBG) log("GPRS reconnect alarm. Previous state was " + mState);
 
         String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
-        String type = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE);
-        ApnContext apnContext = mApnContexts.get(type);
-        if (apnContext != null) {
-            apnContext.setReason(reason);
-            if (apnContext.getState() == State.FAILED) {
-                apnContext.setState(State.IDLE);
+        int connectionId = intent.getIntExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, -1);
+
+        DataConnectionAc dcac= mDataConnectionAsyncChannels.get(connectionId);
+
+        if (dcac != null) {
+            for (ApnContext apnContext : dcac.getApnListSync()) {
+                apnContext.setReason(reason);
+                if (apnContext.getState() == State.FAILED) {
+                    apnContext.setState(State.IDLE);
+                }
+                sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext));
             }
-            sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext));
+            // Alram had expired. Clear pending intent recorded on the DataConnection.
+            dcac.setReconnectIntentSync(null);
         }
     }
 
@@ -550,6 +556,9 @@
             if (DBG) log("onDataConnectionAttached: start polling notify attached");
             startNetStatPoll();
             notifyDataConnection(Phone.REASON_DATA_ATTACHED);
+        } else {
+            // update APN availability so that APN can be enabled.
+            notifyDataAvailability(Phone.REASON_DATA_ATTACHED);
         }
 
         setupDataOnReadyApns(Phone.REASON_DATA_ATTACHED);
@@ -591,17 +600,27 @@
     }
 
     private void setupDataOnReadyApns(String reason) {
+        // Stop reconnect alarms on all data connections pending
+        // retry. Reset ApnContext state to IDLE.
+        for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+            if (dcac.getReconnectIntentSync() != null) {
+                cancelReconnectAlarm(dcac);
+                if (dcac.dataConnection != null) {
+                    dcac.dataConnection.resetRetryCount();
+                }
+            }
+        }
+
         // Only check for default APN state
         for (ApnContext apnContext : mApnContexts.values()) {
+            if (apnContext.getState() == State.FAILED) {
+                // By this time, alarms for all failed Apns
+                // should be stopped if any.
+                // Make sure to set the state back to IDLE
+                // so that setup data can happen.
+                apnContext.setState(State.IDLE);
+            }
             if (apnContext.isReady()) {
-                if (apnContext.getState() == State.FAILED) {
-                    cleanApnContextBeforeRestart(apnContext);
-                    if (apnContext.getDataConnection() != null) {
-                        apnContext.getDataConnection().resetRetryCount();
-                    }
-                }
-                // Do not start ApnContext in SCANNING state
-                // FAILED state must be reset to IDLE by now
                 if (apnContext.getState() == State.IDLE) {
                     apnContext.setReason(reason);
                     trySetupData(apnContext);
@@ -751,53 +770,70 @@
         if (DBG) {
             log("cleanUpConnection: tearDown=" + tearDown + " reason=" + apnContext.getReason());
         }
-        if (tearDown && cleanApnContextBeforeRestart(apnContext)) {
-            // if the request is tearDown and ApnContext does not hold an active connection,
-            // we're ok to return here.
-            return;
-        }
-
         DataConnectionAc dcac = apnContext.getDataConnectionAc();
-        if (tearDown && (dcac != null)) {
-            if (DBG) log("cleanUpConnection: tearing down");
-            Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
-            apnContext.getDataConnection().tearDown(apnContext.getReason(), msg);
-            apnContext.setState(State.DISCONNECTING);
+        if (tearDown) {
+            boolean isConnected = (apnContext.getState() != State.IDLE
+                                   && apnContext.getState() != State.FAILED);
+            if (!isConnected) {
+                // The request is tearDown and but ApnContext is not connected.
+                // If apnContext is not enabled anymore, break the linkage to the DCAC/DC.
+                apnContext.setState(State.IDLE);
+                if (!apnContext.isReady()) {
+                    apnContext.setDataConnection(null);
+                    apnContext.setDataConnectionAc(null);
+                }
+            } else {
+                // Connection is still there. Try to clean up.
+                if (dcac != null) {
+                    if (apnContext.getState() != State.DISCONNECTING) {
+                        if (DBG) log("cleanUpConnection: tearing down");
+                        Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
+                        apnContext.getDataConnection().tearDown(apnContext.getReason(), msg);
+                        apnContext.setState(State.DISCONNECTING);
+                    }
+                } else {
+                    // apn is connected but no reference to dcac.
+                    // Should not be happen, but reset the state in case.
+                    apnContext.setState(State.IDLE);
+                    mPhone.notifyDataConnection(apnContext.getReason(),
+                                                apnContext.getApnType());
+                }
+            }
         } else {
+            // force clean up the data connection.
             if (dcac != null) dcac.resetSync();
             apnContext.setState(State.IDLE);
             mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
             apnContext.setDataConnection(null);
             apnContext.setDataConnectionAc(null);
         }
+
+        // make sure reconnection alarm is cleaned up if there is no ApnContext
+        // associated to the connection.
+        if (dcac != null) {
+            Collection<ApnContext> apnList = dcac.getApnListSync();
+            if (apnList.isEmpty()) {
+                cancelReconnectAlarm(dcac);
+            }
+        }
     }
 
     /**
-     * @param APNContext to clean
-     * @return true if ApnContext is not connected anymore.
-     *         false if ApnContext still holds a connection.
+     * Cancels the alarm associated with DCAC.
+     *
+     * @param DataConnectionAc on which the alarm should be stopped.
      */
-    private boolean cleanApnContextBeforeRestart(ApnContext apnContext) {
-        if (apnContext == null) return true;
+    private void cancelReconnectAlarm(DataConnectionAc dcac) {
+        if (dcac == null) return;
 
-        // Clear the reconnect alarm, if set.
-        if (apnContext.getReconnectIntent() != null) {
-            AlarmManager am =
-                (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
-            am.cancel(apnContext.getReconnectIntent());
-            apnContext.setReconnectIntent(null);
-        }
+        PendingIntent intent = dcac.getReconnectIntentSync();
 
-        if (apnContext.getState() == State.IDLE || apnContext.getState() == State.DISCONNECTING) {
-            if (DBG) log("cleanUpConnection: state= " + apnContext.getState());
-            return true;
+        if (intent != null) {
+                AlarmManager am =
+                    (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
+                am.cancel(intent);
+                dcac.setReconnectIntentSync(null);
         }
-
-        if (apnContext.getState() == State.FAILED) {
-            apnContext.setState(State.IDLE);
-            return true;
-        }
-        return false;
     }
 
     /**
@@ -936,17 +972,26 @@
                 configureRetry(dc, apnContext.getApnType());
             }
             apnContext.setDataConnectionAc(dcac);
-            apnContext.setApnSetting(apn);
             apnContext.setDataConnection(dc);
         }
 
+        apnContext.setApnSetting(apn);
+        apnContext.setState(State.INITING);
+        mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+        // If reconnect alarm is active on this DataConnection, wait for the alarm being
+        // fired so that we don't disruppt data retry pattern engaged.
+        if (apnContext.getDataConnectionAc().getReconnectIntentSync() != null) {
+            if (DBG) log("setupData: data reconnection pending");
+            apnContext.setState(State.FAILED);
+            mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+            return true;
+        }
+
         Message msg = obtainMessage();
         msg.what = EVENT_DATA_SETUP_COMPLETE;
         msg.obj = apnContext;
         dc.bringUp(msg, apn);
 
-        apnContext.setState(State.INITING);
-        mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
         if (DBG) log("setupData: initing!");
         return true;
     }
@@ -1010,10 +1055,16 @@
                     }
                 }
                 if (!found) {
-                    // ApnContext does not have dcan reorted in data call list.
+                    // ApnContext does not have dcac reported in data call list.
+                    // Fetch all the ApnContexts that map to this dcac which are in
+                    // INITING state too.
                     if (DBG) log("onDataStateChanged(ar): Connected apn not found in the list (" +
                                  apnContext.toString() + ")");
-                    list.add(apnContext);
+                    if (apnContext.getDataConnectionAc() != null) {
+                        list.addAll(apnContext.getDataConnectionAc().getApnListSync());
+                    } else {
+                        list.add(apnContext);
+                    }
                 }
             }
         }
@@ -1063,13 +1114,14 @@
             // no associated DataConnection found. Ignore.
             if (dcac == null) continue;
 
-            Collection<ApnContext> apns = dcac.getApnList();
+            Collection<ApnContext> apns = dcac.getApnListSync();
 
-            // filter out ApnContext with "Connected" state.
+            // filter out ApnContext with "Connected/Connecting" state.
             ArrayList<ApnContext> connectedApns = new ArrayList<ApnContext>();
             for (ApnContext apnContext : apns) {
-                if ((apnContext != null) &&
-                    (apnContext.getState() == State.CONNECTED)) {
+                if (apnContext.getState() == State.CONNECTED ||
+                       apnContext.getState() == State.CONNECTING ||
+                       apnContext.getState() == State.INITING) {
                     connectedApns.add(apnContext);
                 }
             }
@@ -1449,21 +1501,28 @@
                 + (delay / 1000) + "s");
         }
 
+        DataConnectionAc dcac = apnContext.getDataConnectionAc();
+
+        if ((dcac == null) || (dcac.dataConnection == null)) {
+            // should not happen, but just in case.
+            loge("null dcac or dc.");
+            return;
+        }
+
         AlarmManager am =
             (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
 
-        // TODO : Register the receiver only once maybe in baseclass.
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(INTENT_RECONNECT_ALARM + '.'+apnContext.getApnType());
-        mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
-
-        Intent intent = new Intent(INTENT_RECONNECT_ALARM + '.' + apnContext.getApnType());
+        Intent intent = new Intent(INTENT_RECONNECT_ALARM + '.' +
+                                   dcac.dataConnection.getDataConnectionId());
         intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, apnContext.getReason());
-        intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, apnContext.getApnType());
-        apnContext.setReconnectIntent(PendingIntent.getBroadcast (
-                mPhone.getContext(), 0, intent, 0));
+        intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE,
+                        dcac.dataConnection.getDataConnectionId());
+
+        PendingIntent alarmIntent = PendingIntent.getBroadcast (mPhone.getContext(), 0,
+                                                                intent, 0);
+        dcac.setReconnectIntentSync(alarmIntent);
         am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                SystemClock.elapsedRealtime() + delay, apnContext.getReconnectIntent());
+                SystemClock.elapsedRealtime() + delay, alarmIntent);
 
     }
 
@@ -1482,13 +1541,16 @@
         createAllApnList();
         if (mRadioAvailable) {
             if (DBG) log("onRecordsLoaded: notifying data availability");
-            notifyDataAvailability(null);
+            notifyDataAvailability(Phone.REASON_SIM_LOADED);
         }
         setupDataOnReadyApns(Phone.REASON_SIM_LOADED);
     }
 
     @Override
     protected void onSetDependencyMet(String apnType, boolean met) {
+        // don't allow users to tweak hipri to work around default dependency not met
+        if (Phone.APN_TYPE_HIPRI.equals(apnType)) return;
+
         ApnContext apnContext = mApnContexts.get(apnType);
         if (apnContext == null) {
             loge("onSetDependencyMet: ApnContext not found in onSetDependencyMet(" +
@@ -1496,6 +1558,11 @@
             return;
         }
         applyNewState(apnContext, apnContext.isEnabled(), met);
+        if (Phone.APN_TYPE_DEFAULT.equals(apnType)) {
+            // tie actions on default to similar actions on HIPRI regarding dependencyMet
+            apnContext = mApnContexts.get(Phone.APN_TYPE_HIPRI);
+            if (apnContext != null) applyNewState(apnContext, apnContext.isEnabled(), met);
+        }
     }
 
     private void applyNewState(ApnContext apnContext, boolean enabled, boolean met) {
@@ -1581,11 +1648,17 @@
     @Override
     protected void onRoamingOff() {
         if (DBG) log("onRoamingOff");
+        // Notify data availability so APN can be enabled.
+        notifyDataAvailability(Phone.REASON_ROAMING_OFF);
+
         setupDataOnReadyApns(Phone.REASON_ROAMING_OFF);
     }
 
     @Override
     protected void onRoamingOn() {
+        // Notify data availability so APN can be enabled.
+        notifyDataAvailability(Phone.REASON_ROAMING_ON);
+
         if (getDataOnRoamingEnabled()) {
             if (DBG) log("onRoamingOn: setup data on roaming");
             setupDataOnReadyApns(Phone.REASON_ROAMING_ON);
@@ -1768,9 +1841,6 @@
         }
 
         apnContext.setState(State.IDLE);
-        apnContext.setApnSetting(null);
-        apnContext.setDataConnection(null);
-        apnContext.setDataConnectionAc(null);
 
         mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
 
@@ -1779,6 +1849,9 @@
         if (!isConnected()) {
             if (mPhone.getServiceStateTracker().processPendingRadioPowerOffAfterDataOff()) {
                 // Radio will be turned off. No need to retry data setup
+                apnContext.setApnSetting(null);
+                apnContext.setDataConnection(null);
+                apnContext.setDataConnectionAc(null);
                 return;
             }
         }
@@ -1790,6 +1863,10 @@
             // we're not tying up the RIL command channel.
             // This also helps in any external dependency to turn off the context.
             startAlarmForReconnect(APN_DELAY_MILLIS, apnContext);
+        } else {
+            apnContext.setApnSetting(null);
+            apnContext.setDataConnection(null);
+            apnContext.setDataConnectionAc(null);
         }
     }
 
@@ -1915,6 +1992,11 @@
                     " status=" + status);
         }
 
+        // install reconnect intent filter for this data connection.
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(INTENT_RECONNECT_ALARM + '.' + id);
+        mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
+
         if (DBG) log("createDataConnection() X id=" + id);
         return conn;
     }
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
index c4a6f53..6e9d0f9d 100644
--- a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -502,16 +502,17 @@
 
     @SmallTest
     public void testFormatNumberToE164() {
-        assertEquals("+16502910000", PhoneNumberUtils.formatNumberToE164("650 2910000", "us"));
-        assertNull(PhoneNumberUtils.formatNumberToE164("1234567", "us"));
-        assertEquals("+18004664114", PhoneNumberUtils.formatNumberToE164("800-GOOG-114", "us"));
+        // Note: ISO 3166-1 only allows upper case country codes.
+        assertEquals("+16502910000", PhoneNumberUtils.formatNumberToE164("650 2910000", "US"));
+        assertNull(PhoneNumberUtils.formatNumberToE164("1234567", "US"));
+        assertEquals("+18004664114", PhoneNumberUtils.formatNumberToE164("800-GOOG-114", "US"));
     }
 
     @SmallTest
     public void testFormatNumber() {
-        assertEquals("(650) 291-0000", PhoneNumberUtils.formatNumber("650 2910000", "us"));
-        assertEquals("123-4567", PhoneNumberUtils.formatNumber("1234567", "us"));
-        assertEquals("(800) 466-4114", PhoneNumberUtils.formatNumber("800-GOOG-114", "us"));
+        assertEquals("(650) 291-0000", PhoneNumberUtils.formatNumber("650 2910000", "US"));
+        assertEquals("123-4567", PhoneNumberUtils.formatNumber("1234567", "US"));
+        assertEquals("(800) 466-4114", PhoneNumberUtils.formatNumber("800-GOOG-114", "US"));
 
     }
 
diff --git a/tests/BiDiTests/res/layout/textview_direction_ltr.xml b/tests/BiDiTests/res/layout/textview_direction_ltr.xml
new file mode 100644
index 0000000..f7b7b8e
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_direction_ltr.xml
@@ -0,0 +1,112 @@
+<?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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/textview_direction_ltr"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layoutDirection="ltr">
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:textDirection="ltr">
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content">
+
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="inherit"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="firstStrong"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="anyRtl"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="ltr"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="rtl"
+                    />
+        </LinearLayout>
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content">
+
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="inherit"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="firstStrong"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="anyRtl"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="ltr"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="rtl"
+                    />
+        </LinearLayout>
+
+    </LinearLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/layout/textview_direction_rtl.xml b/tests/BiDiTests/res/layout/textview_direction_rtl.xml
new file mode 100644
index 0000000..81c5411
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_direction_rtl.xml
@@ -0,0 +1,112 @@
+<?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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/textview_direction_rtl"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layoutDirection="rtl">
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:textDirection="rtl">
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content">
+
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="inherit"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="firstStrong"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="anyRtl"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="ltr"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textDirection="rtl"
+                    />
+        </LinearLayout>
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content">
+
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="inherit"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="firstStrong"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="anyRtl"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="ltr"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="24dip"
+                      android:text="@string/textview_hebrew_text"
+                      android:textDirection="rtl"
+                    />
+        </LinearLayout>
+
+    </LinearLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/layout/view_group_margin_mixed.xml b/tests/BiDiTests/res/layout/view_group_margin_mixed.xml
new file mode 100644
index 0000000..5845b38
--- /dev/null
+++ b/tests/BiDiTests/res/layout/view_group_margin_mixed.xml
@@ -0,0 +1,241 @@
+<?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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:id="@+id/view_group_margin_mixed"
+             android:layout_width="fill_parent"
+             android:layout_height="fill_parent"
+             android:background="#FFFFFFFF">
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content">
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="ltr">
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF0000FF">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="0dip"
+                        android:layout_marginRight="0dip"
+                        android:layout_marginTop="0dip"
+                        android:layout_marginBottom="0dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF000000">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="10dip"
+                        android:layout_marginStart="5dip"
+                        android:layout_marginRight="20dip"
+                        android:layout_marginEnd="5dip"
+                        android:layout_marginTop="5dip"
+                        android:layout_marginBottom="5dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+        </LinearLayout>
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="rtl">
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF0000FF">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="0dip"
+                        android:layout_marginRight="0dip"
+                        android:layout_marginTop="0dip"
+                        android:layout_marginBottom="0dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF000000">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="10dip"
+                        android:layout_marginStart="5dip"
+                        android:layout_marginRight="20dip"
+                        android:layout_marginEnd="5dip"
+                        android:layout_marginTop="5dip"
+                        android:layout_marginBottom="5dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+        </LinearLayout>
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="inherit">
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF0000FF">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="0dip"
+                        android:layout_marginRight="0dip"
+                        android:layout_marginTop="0dip"
+                        android:layout_marginBottom="0dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF000000">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="10dip"
+                        android:layout_marginStart="5dip"
+                        android:layout_marginRight="20dip"
+                        android:layout_marginEnd="5dip"
+                        android:layout_marginTop="5dip"
+                        android:layout_marginBottom="5dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+        </LinearLayout>
+
+        <LinearLayout android:orientation="vertical"
+                      android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="locale">
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF0000FF">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="0dip"
+                        android:layout_marginRight="0dip"
+                        android:layout_marginTop="0dip"
+                        android:layout_marginBottom="0dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+            <LinearLayout android:orientation="horizontal"
+                          android:layout_width="match_parent"
+                          android:layout_height="wrap_content"
+                          android:background="#FF000000">
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:layout_marginLeft="10dip"
+                        android:layout_marginStart="5dip"
+                        android:layout_marginRight="20dip"
+                        android:layout_marginEnd="5dip"
+                        android:layout_marginTop="5dip"
+                        android:layout_marginBottom="5dip"
+                        android:background="#FFFF0000">
+                </FrameLayout>
+
+                <FrameLayout
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:background="#FF00FF00">
+                </FrameLayout>
+            </LinearLayout>
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
index c2683c2..c033879 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
@@ -106,28 +106,33 @@
         addItem(result, "Linear LTR", BiDiTestLinearLayoutLtr.class, R.id.linear_layout_ltr);
         addItem(result, "Linear RTL", BiDiTestLinearLayoutRtl.class, R.id.linear_layout_rtl);
         addItem(result, "Linear LOC", BiDiTestLinearLayoutLocale.class, R.id.linear_layout_locale);
-        
+
         addItem(result, "Frame LTR", BiDiTestFrameLayoutLtr.class, R.id.frame_layout_ltr);
         addItem(result, "Frame RTL", BiDiTestFrameLayoutRtl.class, R.id.frame_layout_rtl);
         addItem(result, "Frame LOC", BiDiTestFrameLayoutLocale.class, R.id.frame_layout_locale);
-        
+
         addItem(result, "Relative LTR", BiDiTestRelativeLayoutLtr.class, R.id.relative_layout_ltr);
         addItem(result, "Relative RTL", BiDiTestRelativeLayoutRtl.class, R.id.relative_layout_rtl);
-        
+
         addItem(result, "Relative2 LTR", BiDiTestRelativeLayout2Ltr.class, R.id.relative_layout_2_ltr);
         addItem(result, "Relative2 RTL", BiDiTestRelativeLayout2Rtl.class, R.id.relative_layout_2_rtl);
         addItem(result, "Relative2 LOC", BiDiTestRelativeLayout2Locale.class, R.id.relative_layout_2_locale);
-        
+
         addItem(result, "Table LTR", BiDiTestTableLayoutLtr.class, R.id.table_layout_ltr);
         addItem(result, "Table RTL", BiDiTestTableLayoutRtl.class, R.id.table_layout_rtl);
         addItem(result, "Table LOC", BiDiTestTableLayoutLocale.class, R.id.table_layout_locale);
 
+        addItem(result, "Padding", BiDiTestViewPadding.class, R.id.view_padding);
+        addItem(result, "Padding MIXED", BiDiTestViewPaddingMixed.class, R.id.view_padding_mixed);
+
+        addItem(result, "Margin MIXED", BiDiTestViewGroupMarginMixed.class, R.id.view_group_margin_mixed);
+
         addItem(result, "TextView LTR", BiDiTestTextViewLtr.class, R.id.textview_ltr);
         addItem(result, "TextView RTL", BiDiTestTextViewRtl.class, R.id.textview_rtl);
         addItem(result, "TextView LOC", BiDiTestTextViewLocale.class, R.id.textview_locale);
 
-        addItem(result, "ViewPadding", BiDiTestViewPadding.class, R.id.view_padding);
-        addItem(result, "ViewPadding MIXED", BiDiTestViewPaddingMixed.class, R.id.view_padding_mixed);
+        addItem(result, "TextDirection LTR", BiDiTestTextViewDirectionLtr.class, R.id.textview_direction_ltr);
+        addItem(result, "TextDirection RTL", BiDiTestTextViewDirectionRtl.class, R.id.textview_direction_rtl);
 
         return result;
     }
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionLtr.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionLtr.java
new file mode 100644
index 0000000..882ed1f
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionLtr.java
@@ -0,0 +1,31 @@
+/*
+ * 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.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestTextViewDirectionLtr extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.textview_direction_ltr, container, false);
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionRtl.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionRtl.java
new file mode 100644
index 0000000..e63ee35
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionRtl.java
@@ -0,0 +1,31 @@
+/*
+ * 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.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestTextViewDirectionRtl extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.textview_direction_rtl, container, false);
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestViewGroupMarginMixed.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestViewGroupMarginMixed.java
new file mode 100644
index 0000000..ce8c380
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestViewGroupMarginMixed.java
@@ -0,0 +1,17 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestViewGroupMarginMixed extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.view_group_margin_mixed, container, false);
+    }
+}
diff --git a/tests/CoreTests/MODULE_LICENSE_APACHE2 b/tests/CoreTests/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/tests/CoreTests/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/tests/GridLayoutTest/res/layout/grid3.xml b/tests/GridLayoutTest/res/layout/grid3.xml
index ba911c2..3c2db54 100644
--- a/tests/GridLayoutTest/res/layout/grid3.xml
+++ b/tests/GridLayoutTest/res/layout/grid3.xml
@@ -66,8 +66,8 @@
     <Space
             android:layout_row="4"
             android:layout_column="2"
-            android:layout_rowWeight="1"
-            android:layout_columnWeight="1"
+            android:layout_rowFlexibility="canStretch"
+            android:layout_columnFlexibility="canStretch"
             />
 
     <Button
diff --git a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
index e010a00..b9bf526 100644
--- a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
+++ b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
@@ -97,8 +97,8 @@
             Space v = new Space(context);
             {
                 LayoutParams lp = new LayoutParams(row5, col3);
-                lp.rowWeight = 1;
-                lp.columnWeight = 1;
+                lp.columnGroup.flexibility = CAN_STRETCH;
+                lp.rowGroup.flexibility = CAN_STRETCH;
                 vg.addView(v, lp);
             }
         }
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 7aa0617..cb8084d 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -31,6 +31,24 @@
         android:hardwareAccelerated="true">
 
         <activity
+                android:name="MaxBitmapSizeActivity"
+                android:label="_MaxBitmapSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
+                android:name="TimeDialogActivity"
+                android:label="_TimeDialog">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+        <activity
                 android:name="OpaqueActivity"
                 android:label="_Opaque">
             <intent-filter>
@@ -494,8 +512,7 @@
 
         <activity
                 android:name="Animated3dActivity"
-                android:label="_Animated 3d"
-                android:theme="@android:style/Theme.Translucent.NoTitleBar">
+                android:label="_Animated 3d">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
index 723f3e8..949589f 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
@@ -19,13 +19,17 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.app.Activity;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.SurfaceTexture;
-import android.opengl.GLES20;
+import android.opengl.GLUtils;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.TextureView;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
 import javax.microedition.khronos.egl.EGL10;
@@ -35,6 +39,15 @@
 import javax.microedition.khronos.egl.EGLDisplay;
 import javax.microedition.khronos.egl.EGLSurface;
 import javax.microedition.khronos.opengles.GL;
+import java.io.BufferedOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import static android.opengl.GLES20.*;
 
 @SuppressWarnings({"UnusedDeclaration"})
 public class GLTextureViewActivity extends Activity implements TextureView.SurfaceTextureListener {
@@ -47,13 +60,34 @@
 
         mTextureView = new TextureView(this);
         mTextureView.setSurfaceTextureListener(this);
+        mTextureView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Bitmap b = mTextureView.getBitmap(800, 800);
+                BufferedOutputStream out = null;
+                try {
+                    out = new BufferedOutputStream(new FileOutputStream("/sdcard/out.png"));
+                    b.compress(Bitmap.CompressFormat.PNG, 100, out);
+                } catch (FileNotFoundException e) {
+                    e.printStackTrace();
+                } finally {
+                    if (out != null) try {
+                        out.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        });
 
-        setContentView(mTextureView, new FrameLayout.LayoutParams(500, 400, Gravity.CENTER));
+        setContentView(mTextureView, new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
+                Gravity.CENTER));
     }
 
     @Override
     public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
-        mRenderThread = new RenderThread(surface);
+        mRenderThread = new RenderThread(getResources(), surface);
         mRenderThread.start();
 
         mTextureView.setCameraDistance(5000);
@@ -65,7 +99,7 @@
         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator animation) {
-                ((View) mTextureView.getParent()).invalidate();
+                mTextureView.invalidate();
             }
         });
         animator.start();
@@ -93,13 +127,12 @@
         private static final String LOG_TAG = "GLTextureView";
 
         static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
-        static final int EGL_SURFACE_TYPE = 0x3033;
-        static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
         static final int EGL_OPENGL_ES2_BIT = 4;
 
         private volatile boolean mFinished;
 
-        private SurfaceTexture mSurface;
+        private final Resources mResources;
+        private final SurfaceTexture mSurface;
         
         private EGL10 mEgl;
         private EGLDisplay mEglDisplay;
@@ -108,26 +141,96 @@
         private EGLSurface mEglSurface;
         private GL mGL;
 
-        RenderThread(SurfaceTexture surface) {
+        RenderThread(Resources resources, SurfaceTexture surface) {
+            mResources = resources;
             mSurface = surface;
         }
 
+        private static final String sSimpleVS =
+                "attribute vec4 position;\n" +
+                "attribute vec2 texCoords;\n" +
+                "varying vec2 outTexCoords;\n" +
+                "\nvoid main(void) {\n" +
+                "    outTexCoords = texCoords;\n" +
+                "    gl_Position = position;\n" +
+                "}\n\n";
+        private static final String sSimpleFS =
+                "precision mediump float;\n\n" +
+                "varying vec2 outTexCoords;\n" +
+                "uniform sampler2D texture;\n" +
+                "\nvoid main(void) {\n" +
+                "    gl_FragColor = texture2D(texture, outTexCoords);\n" +
+                "}\n\n";
+
+        private static final int FLOAT_SIZE_BYTES = 4;
+        private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
+        private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
+        private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
+        private final float[] mTriangleVerticesData = {
+                // X, Y, Z, U, V
+                -1.0f, -1.0f, 0, 0.f, 0.f,
+                1.0f, -1.0f, 0, 1.f, 0.f,
+                -1.0f,  1.0f, 0, 0.f, 1.f,
+                1.0f,   1.0f, 0, 1.f, 1.f,
+        };
+
         @Override
         public void run() {
             initGL();
+            
+            FloatBuffer triangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length
+                    * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
+            triangleVertices.put(mTriangleVerticesData).position(0);
 
-            float red = 1.0f;
+            int texture = loadTexture(R.drawable.large_photo);
+            int program = buildProgram(sSimpleVS, sSimpleFS);
+
+            int attribPosition = glGetAttribLocation(program, "position");
+            checkGlError();
+
+            int attribTexCoords = glGetAttribLocation(program, "texCoords");
+            checkGlError();
+
+            int uniformTexture = glGetUniformLocation(program, "texture");
+            checkGlError();
+
+            glBindTexture(GL_TEXTURE_2D, texture);
+            checkGlError();
+
+            glUseProgram(program);
+            checkGlError();
+
+            glEnableVertexAttribArray(attribPosition);
+            checkGlError();
+
+            glEnableVertexAttribArray(attribTexCoords);
+            checkGlError();
+
+            glUniform1i(texture, 0);
+            checkGlError();
+            
             while (!mFinished) {
                 checkCurrent();
 
                 Log.d(LOG_TAG, "Rendering frame");
 
-                GLES20.glClearColor(red, 0.0f, 0.0f, 1.0f);
+                glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
                 checkGlError();
 
-                GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+                glClear(GL_COLOR_BUFFER_BIT);
                 checkGlError();
 
+                // drawQuad
+                triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
+                glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false,
+                        TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
+
+                triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
+                glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false,
+                        TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
+
+                glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
                 if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
                     throw new RuntimeException("Cannot swap buffers");
                 }
@@ -138,14 +241,90 @@
                 } catch (InterruptedException e) {
                     // Ignore
                 }
-
-                red += 0.021f;
-                if (red > 1.0f) red = 0.0f;
             }
 
             finishGL();
         }
 
+        private int loadTexture(int resource) {
+            int[] textures = new int[1];
+
+            glActiveTexture(GL_TEXTURE0);
+            glGenTextures(1, textures, 0);
+            checkGlError();
+
+            int texture = textures[0];
+            glBindTexture(GL_TEXTURE_2D, texture);
+            checkGlError();
+            
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+            Bitmap bitmap = BitmapFactory.decodeResource(mResources, resource);
+
+            GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0);
+            checkGlError();
+
+            bitmap.recycle();
+
+            return texture;
+        }
+        
+        private int buildProgram(String vertex, String fragment) {
+            int vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
+            if (vertexShader == 0) return 0;
+
+            int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
+            if (fragmentShader == 0) return 0;
+
+            int program = glCreateProgram();
+            glAttachShader(program, vertexShader);
+            checkGlError();
+
+            glAttachShader(program, fragmentShader);
+            checkGlError();
+
+            glLinkProgram(program);
+            checkGlError();
+
+            int[] status = new int[1];
+            glGetProgramiv(program, GL_LINK_STATUS, status, 0);
+            if (status[0] != GL_TRUE) {
+                String error = glGetProgramInfoLog(program);
+                Log.d(LOG_TAG, "Error while linking program:\n" + error);
+                glDeleteShader(vertexShader);
+                glDeleteShader(fragmentShader);
+                glDeleteProgram(program);
+                return 0;
+            }
+
+            return program;
+        }
+        
+        private int buildShader(String source, int type) {
+            int shader = glCreateShader(type);
+
+            glShaderSource(shader, source);
+            checkGlError();
+
+            glCompileShader(shader);
+            checkGlError();
+
+            int[] status = new int[1];
+            glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0);
+            if (status[0] != GL_TRUE) {
+                String error = glGetShaderInfoLog(shader);
+                Log.d(LOG_TAG, "Error while compiling shader:\n" + error);
+                glDeleteShader(shader);
+                return 0;
+            }
+            
+            return shader;
+        }
+
         private void checkEglError() {
             int error = mEgl.eglGetError();
             if (error != EGL10.EGL_SUCCESS) {
@@ -154,8 +333,8 @@
         }
 
         private void checkGlError() {
-            int error = GLES20.glGetError();
-            if (error != GLES20.GL_NO_ERROR) {
+            int error = glGetError();
+            if (error != GL_NO_ERROR) {
                 Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error));
             }
         }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MaxBitmapSizeActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MaxBitmapSizeActivity.java
new file mode 100644
index 0000000..b3b42dc
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MaxBitmapSizeActivity.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 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.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.LinearLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class MaxBitmapSizeActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        final LinearLayout layout = new LinearLayout(this);
+
+        CanvasView view = new CanvasView(this);
+        layout.addView(view, new LinearLayout.LayoutParams(200, 200));
+
+        view = new CanvasView(this);
+        view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+        layout.addView(view, new LinearLayout.LayoutParams(200, 200));
+
+        setContentView(layout);
+    }
+
+    private static class CanvasView extends View {
+        public CanvasView(Context c) {
+            super(c);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+            Log.d("Bitmap", "Hw         = " + canvas.isHardwareAccelerated());
+            Log.d("Bitmap", "Max width  = " + canvas.getMaximumBitmapWidth());
+            Log.d("Bitmap", "Max height = " + canvas.getMaximumBitmapHeight());
+        }
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
index 01ee90a..634e7e3 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
@@ -16,8 +16,6 @@
 
 package com.android.test.hwui;
 
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
 import android.app.Activity;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
@@ -35,7 +33,6 @@
     private Camera mCamera;
     private TextureView mTextureView;
     private FrameLayout mContent;
-    private AnimatorSet mAnimatorSet;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -54,7 +51,6 @@
             @Override
             public void onClick(View v) {
                 if (mAdded) {
-                    if (mAnimatorSet != null) mAnimatorSet.cancel();
                     mContent.removeView(mTextureView);
                 } else {
                     mContent.addView(mTextureView);
@@ -63,7 +59,9 @@
             }
         });
 
-        mContent.addView(mTextureView, new FrameLayout.LayoutParams(500, 400, Gravity.CENTER));
+        mContent.addView(mTextureView, new FrameLayout.LayoutParams(
+                FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT,
+                Gravity.CENTER));
         mContent.addView(button, new FrameLayout.LayoutParams(
                 FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT,
                 Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM));
@@ -73,6 +71,9 @@
     @Override
     public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
         mCamera = Camera.open();
+        Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
+        mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
+                previewSize.width, previewSize.height, Gravity.CENTER));
 
         try {
             mCamera.setPreviewTexture(surface);
@@ -83,20 +84,6 @@
         mCamera.startPreview();
 
         mTextureView.setCameraDistance(5000);
-
-//        ObjectAnimator rotationY = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f);
-//        rotationY.setRepeatMode(ObjectAnimator.REVERSE);
-//        rotationY.setRepeatCount(ObjectAnimator.INFINITE);
-//        rotationY.setDuration(4000);
-
-//        ObjectAnimator alpha = ObjectAnimator.ofFloat(mTextureView, "alpha", 1.0f, 0.0f);
-//        alpha.setRepeatMode(ObjectAnimator.REVERSE);
-//        alpha.setRepeatCount(ObjectAnimator.INFINITE);
-//        alpha.setDuration(4000);
-
-//        mAnimatorSet = new AnimatorSet();
-//        mAnimatorSet.play(alpha).with(rotationY);
-//        mAnimatorSet.start();
     }
 
     @Override
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TimeDialogActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TimeDialogActivity.java
new file mode 100644
index 0000000..9e3e950
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TimeDialogActivity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 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.test.hwui;
+
+import android.app.Activity;
+import android.app.TimePickerDialog;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.Button;
+import android.widget.FrameLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class TimeDialogActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        FrameLayout layout = new FrameLayout(this);
+        Button b = new Button(this);
+        b.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
+                FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER));
+        b.setText("Show dialog");
+        b.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                new TimePickerDialog(TimeDialogActivity.this, null, 12, 12, true).show();
+            }
+        });
+        layout.addView(b);
+        
+        setContentView(layout);
+    }
+}
diff --git a/tests/RenderScriptTests/PerfTest/AndroidManifest.xml b/tests/RenderScriptTests/PerfTest/AndroidManifest.xml
index aafd176..cc60396 100644
--- a/tests/RenderScriptTests/PerfTest/AndroidManifest.xml
+++ b/tests/RenderScriptTests/PerfTest/AndroidManifest.xml
@@ -9,8 +9,7 @@
       android:icon="@drawable/test_pattern">
         <uses-library android:name="android.test.runner" />
         <activity android:name="RsBench"
-                  android:label="RsBenchmark"
-                  android:theme="@android:style/Theme.Black.NoTitleBar">
+                  android:label="RsBenchmark">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
diff --git a/tests/RenderScriptTests/PerfTest/res/menu/loader_menu.xml b/tests/RenderScriptTests/PerfTest/res/menu/loader_menu.xml
new file mode 100644
index 0000000..8234677
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/res/menu/loader_menu.xml
@@ -0,0 +1,25 @@
+<?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.
+*/
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/benchmark_mode"
+          android:title="@string/benchmark_mode" />
+    <item android:id="@+id/debug_mode"
+          android:title="@string/debug_mode" />
+</menu>
diff --git a/tests/RenderScriptTests/PerfTest/res/values/strings.xml b/tests/RenderScriptTests/PerfTest/res/values/strings.xml
new file mode 100644
index 0000000..627ac21
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <skip />
+    <string name="benchmark_mode">Benchmark Mode</string>
+    <string name="debug_mode">Debug Mode</string>
+</resources>
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBench.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBench.java
index d7393f8..b336a4d 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBench.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBench.java
@@ -31,10 +31,14 @@
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
+import android.view.MenuInflater;
 import android.view.View;
 import android.view.Window;
 import android.widget.Button;
 import android.widget.ListView;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.widget.Toast;
 
 import java.lang.Runtime;
 
@@ -77,4 +81,37 @@
         super.onPause();
         mView.pause();
     }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.loader_menu, menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        // Handle item selection
+        switch (item.getItemId()) {
+            case R.id.benchmark_mode:
+                mView.setBenchmarkMode();
+                return true;
+            case R.id.debug_mode:
+                AlertDialog.Builder builder = new AlertDialog.Builder(this);
+                builder.setTitle("Pick a Test");
+                builder.setItems(mView.getTestNames(),
+                                 new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int item) {
+                        Toast.makeText(getApplicationContext(),
+                                       "Switching to: " + mView.getTestNames()[item],
+                                       Toast.LENGTH_SHORT).show();
+                        mView.setDebugMode(item);
+                    }
+                });
+                builder.show();
+                return true;
+            default:
+                return super.onOptionsItemSelected(item);
+        }
+    }
 }
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
index c706286..c375be5 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
@@ -84,12 +84,6 @@
     private Resources mRes;
     private RenderScriptGL mRS;
 
-    private Sampler mLinearClamp;
-    private Sampler mLinearWrap;
-    private Sampler mMipLinearWrap;
-    private Sampler mNearestClamp;
-    private Sampler mNearesWrap;
-
     private ProgramStore mProgStoreBlendNoneDepth;
     private ProgramStore mProgStoreBlendNone;
     private ProgramStore mProgStoreBlendAlpha;
@@ -115,10 +109,6 @@
     private ScriptField_FragentShaderConstants3_s mFSConstPixel;
 
 
-    private ProgramRaster mCullBack;
-    private ProgramRaster mCullFront;
-    private ProgramRaster mCullNone;
-
     private Allocation mTexTorus;
     private Allocation mTexOpaque;
     private Allocation mTexTransparent;
@@ -143,6 +133,8 @@
 
 
     private ScriptC_rsbench mScript;
+    private ScriptC_text_test mTextScript;
+    private ScriptC_torus_test mTorusScript;
 
     private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
 
@@ -310,6 +302,7 @@
         mProgStoreBlendAdd = BLEND_ADD_DEPTH_NONE(mRS);
 
         mScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth);
+
         mScript.set_gProgStoreBlendNone(mProgStoreBlendNone);
         mScript.set_gProgStoreBlendAlpha(mProgStoreBlendAlpha);
         mScript.set_gProgStoreBlendAdd(mProgStoreBlendAdd);
@@ -330,22 +323,24 @@
         texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
                               ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
         mProgFragmentTexture = texBuilder.create();
-        mProgFragmentTexture.bindSampler(mLinearClamp, 0);
+        mProgFragmentTexture.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
 
         ProgramFragmentFixedFunction.Builder colBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
         colBuilder.setVaryingColor(false);
         mProgFragmentColor = colBuilder.create();
 
         mScript.set_gProgFragmentColor(mProgFragmentColor);
+
         mScript.set_gProgFragmentTexture(mProgFragmentTexture);
 
 
+
         // For Galaxy live wallpaper drawing
         ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS);
         builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
                            ProgramFragmentFixedFunction.Builder.Format.RGB, 0);
         ProgramFragment pfb = builder.create();
-        pfb.bindSampler(mNearesWrap, 0);
+        pfb.bindSampler(Sampler.WRAP_NEAREST(mRS), 0);
         mScript.set_gPFBackground(pfb);
 
         builder = new ProgramFragmentFixedFunction.Builder(mRS);
@@ -354,7 +349,7 @@
                            ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
         builder.setVaryingColor(true);
         ProgramFragment pfs = builder.create();
-        pfs.bindSampler(mMipLinearWrap, 0);
+        pfs.bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS), 0);
         mScript.set_gPFStars(pfs);
 
     }
@@ -404,6 +399,7 @@
 
         mScript.set_gProgVertex(mProgVertex);
 
+
         // For galaxy live wallpaper
         mPvStarAlloc = new ScriptField_VpConsts(mRS, 1);
         mScript.bind_vpConstants(mPvStarAlloc);
@@ -447,13 +443,11 @@
     private void initCustomShaders() {
         mVSConst = new ScriptField_VertexShaderConstants_s(mRS, 1);
         mFSConst = new ScriptField_FragentShaderConstants_s(mRS, 1);
-        mScript.bind_gVSConstants(mVSConst);
-        mScript.bind_gFSConstants(mFSConst);
+
 
         mVSConstPixel = new ScriptField_VertexShaderConstants3_s(mRS, 1);
         mFSConstPixel = new ScriptField_FragentShaderConstants3_s(mRS, 1);
-        mScript.bind_gVSConstPixel(mVSConstPixel);
-        mScript.bind_gFSConstPixel(mFSConstPixel);
+
 
         // Initialize the shader builder
         ProgramVertex.Builder pvbCustom = new ProgramVertex.Builder(mRS);
@@ -506,11 +500,7 @@
         }
         mProgFragmentMultitex = pfbCustom.create();
 
-        mScript.set_gProgVertexCustom(mProgVertexCustom);
-        mScript.set_gProgFragmentCustom(mProgFragmentCustom);
-        mScript.set_gProgVertexPixelLight(mProgVertexPixelLight);
-        mScript.set_gProgVertexPixelLightMove(mProgVertexPixelLightMove);
-        mScript.set_gProgFragmentPixelLight(mProgFragmentPixelLight);
+
         mScript.set_gProgFragmentMultitex(mProgFragmentMultitex);
     }
 
@@ -587,39 +577,22 @@
             Log.e("rs", "could not load model");
         } else {
             mTorus = (Mesh)entry.getObject();
-            mScript.set_gTorusMesh(mTorus);
         }
 
         createParticlesMesh();
     }
 
     private void initSamplers() {
-        Sampler.Builder bs = new Sampler.Builder(mRS);
-        bs.setMinification(Sampler.Value.LINEAR);
-        bs.setMagnification(Sampler.Value.LINEAR);
-        bs.setWrapS(Sampler.Value.WRAP);
-        bs.setWrapT(Sampler.Value.WRAP);
-        mLinearWrap = bs.create();
-
-        mLinearClamp = Sampler.CLAMP_LINEAR(mRS);
-        mNearestClamp = Sampler.CLAMP_NEAREST(mRS);
-        mMipLinearWrap = Sampler.WRAP_LINEAR_MIP_LINEAR(mRS);
-        mNearesWrap = Sampler.WRAP_NEAREST(mRS);
-
-        mScript.set_gLinearClamp(mLinearClamp);
-        mScript.set_gLinearWrap(mLinearWrap);
-        mScript.set_gMipLinearWrap(mMipLinearWrap);
-        mScript.set_gNearestClamp(mNearestClamp);
+        mScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
+        mScript.set_gLinearWrap(Sampler.WRAP_LINEAR(mRS));
+        mScript.set_gMipLinearWrap(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS));
+        mScript.set_gNearestClamp(Sampler.CLAMP_NEAREST(mRS));
     }
 
     private void initProgramRaster() {
-        mCullBack = ProgramRaster.CULL_BACK(mRS);
-        mCullFront = ProgramRaster.CULL_FRONT(mRS);
-        mCullNone = ProgramRaster.CULL_NONE(mRS);
-
-        mScript.set_gCullBack(mCullBack);
-        mScript.set_gCullFront(mCullFront);
-        mScript.set_gCullNone(mCullNone);
+        mScript.set_gCullBack(ProgramRaster.CULL_BACK(mRS));
+        mScript.set_gCullFront(ProgramRaster.CULL_FRONT(mRS));
+        mScript.set_gCullNone(ProgramRaster.CULL_NONE(mRS));
     }
 
     private int strlen(byte[] array) {
@@ -645,9 +618,47 @@
         }
     }
 
+    public void setDebugMode(int num) {
+        mScript.invoke_setDebugMode(num);
+    }
+
+    public void setBenchmarkMode() {
+        mScript.invoke_setBenchmarkMode();
+    }
+
+    void initTextScript() {
+        mTextScript = new ScriptC_text_test(mRS, mRes, R.raw.text_test);
+        mTextScript.set_gFontSans(mFontSans);
+        mTextScript.set_gFontSerif(mFontSerif);
+    }
+
+    void initTorusScript() {
+        mTorusScript = new ScriptC_torus_test(mRS, mRes, R.raw.torus_test);
+        mTorusScript.set_gCullFront(ProgramRaster.CULL_FRONT(mRS));
+        mTorusScript.set_gCullBack(ProgramRaster.CULL_BACK(mRS));
+        mTorusScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
+        mTorusScript.set_gTorusMesh(mTorus);
+        mTorusScript.set_gTexTorus(mTexTorus);
+        mTorusScript.set_gProgVertexCustom(mProgVertexCustom);
+        mTorusScript.set_gProgFragmentCustom(mProgFragmentCustom);
+        mTorusScript.set_gProgVertexPixelLight(mProgVertexPixelLight);
+        mTorusScript.set_gProgVertexPixelLightMove(mProgVertexPixelLightMove);
+        mTorusScript.set_gProgFragmentPixelLight(mProgFragmentPixelLight);
+        mTorusScript.bind_gVSConstPixel(mVSConstPixel);
+        mTorusScript.bind_gFSConstPixel(mFSConstPixel);
+        mTorusScript.bind_gVSConstants(mVSConst);
+        mTorusScript.bind_gFSConstants(mFSConst);
+        mTorusScript.set_gProgVertex(mProgVertex);
+        mTorusScript.set_gProgFragmentTexture(mProgFragmentTexture);
+        mTorusScript.set_gProgFragmentColor(mProgFragmentColor);
+        mTorusScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth);
+    }
+
     private void initRS() {
 
         mScript = new ScriptC_rsbench(mRS, mRes, R.raw.rsbench);
+
+
         mRS.setMessageHandler(mRsMessage);
 
         mMaxModes = mScript.get_gMaxModes();
@@ -709,6 +720,13 @@
         mSampleListViewAllocs.copyAll();
         mScript.bind_gListViewText(mSampleListViewAllocs);
 
+        initTextScript();
+        initTorusScript();
+
+        mScript.set_gFontScript(mTextScript);
+        mScript.set_gTorusScript(mTorusScript);
+        mScript.set_gDummyAlloc(Allocation.createSized(mRS, Element.I32(mRS), 1));
+
         mRS.bindRootScript(mScript);
     }
 }
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java
index 2882b93..61aa3e1 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java
@@ -105,4 +105,16 @@
     public boolean testIsFinished() {
         return mRender.testIsFinished();
     }
+
+    void setBenchmarkMode() {
+        mRender.setBenchmarkMode();
+    }
+
+    void setDebugMode(int num) {
+        mRender.setDebugMode(num);
+    }
+
+    String[] getTestNames() {
+        return mRender.mTestNames;
+    }
 }
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
index bb81862..eaafe1d 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
@@ -18,6 +18,7 @@
 
 #include "rs_graphics.rsh"
 #include "shader_def.rsh"
+#include "subtest_def.rsh"
 
 /* Message sent from script to renderscript */
 const int RS_MSG_TEST_DONE = 100;
@@ -98,7 +99,6 @@
 rs_mesh g10by10Mesh;
 rs_mesh g100by100Mesh;
 rs_mesh gWbyHMesh;
-rs_mesh gTorusMesh;
 rs_mesh gSingleMesh;
 
 rs_font gFontSans;
@@ -115,25 +115,15 @@
 rs_program_raster gCullFront;
 rs_program_raster gCullNone;
 
-// Custom vertex shader compunents
-VertexShaderConstants *gVSConstants;
-FragentShaderConstants *gFSConstants;
-VertexShaderConstants3 *gVSConstPixel;
-FragentShaderConstants3 *gFSConstPixel;
 // Export these out to easily set the inputs to shader
 VertexShaderInputs *gVSInputs;
-// Custom shaders we use for lighting
-rs_program_vertex gProgVertexCustom;
-rs_program_fragment gProgFragmentCustom;
-rs_program_vertex gProgVertexPixelLight;
-rs_program_vertex gProgVertexPixelLightMove;
-rs_program_fragment gProgFragmentPixelLight;
+
 rs_program_fragment gProgFragmentMultitex;
 
 rs_allocation gRenderBufferColor;
 rs_allocation gRenderBufferDepth;
 
-float gDt = 0;
+static float gDt = 0;
 
 void init() {
 }
@@ -141,16 +131,6 @@
 static int gRenderSurfaceW;
 static int gRenderSurfaceH;
 
-static const char *sampleText = "This is a sample of small text for performace";
-// Offsets for multiple layer of text
-static int textOffsets[] = { 0,  0, -5, -5, 5,  5, -8, -8, 8,  8};
-static float textColors[] = {1.0f, 1.0f, 1.0f, 1.0f,
-                             0.5f, 0.7f, 0.5f, 1.0f,
-                             0.7f, 0.5f, 0.5f, 1.0f,
-                             0.5f, 0.5f, 0.7f, 1.0f,
-                             0.5f, 0.6f, 0.7f, 1.0f,
-};
-
 /**
   * Methods to draw the galaxy live wall paper
   */
@@ -291,40 +271,16 @@
     rsgBindDepthTarget(gRenderBufferDepth);
 }
 
+rs_script gFontScript;
+rs_script gTorusScript;
+rs_allocation gDummyAlloc;
+
 static void displayFontSamples(int fillNum) {
-
-    rs_font fonts[5];
-    fonts[0] = gFontSans;
-    fonts[1] = gFontSerif;
-    fonts[2] = gFontSans;
-    fonts[3] = gFontSerif;
-    fonts[4] = gFontSans;
-
-    uint width = gRenderSurfaceW;
-    uint height = gRenderSurfaceH;
-    int left = 0, right = 0, top = 0, bottom = 0;
-    rsgMeasureText(sampleText, &left, &right, &top, &bottom);
-
-    int textHeight = top - bottom;
-    int textWidth = right - left;
-    int numVerticalLines = height / textHeight;
-    int yPos = top;
-
-    int xOffset = 0, yOffset = 0;
-    for(int fillI = 0; fillI < fillNum; fillI ++) {
-        rsgBindFont(fonts[fillI]);
-        xOffset = textOffsets[fillI * 2];
-        yOffset = textOffsets[fillI * 2 + 1];
-        float *colPtr = textColors + fillI * 4;
-        rsgFontColor(colPtr[0], colPtr[1], colPtr[2], colPtr[3]);
-        for (int h = 0; h < 4; h ++) {
-            yPos = top + yOffset;
-            for (int v = 0; v < numVerticalLines; v ++) {
-                rsgDrawText(sampleText, xOffset + textWidth * h, yPos);
-                yPos += textHeight;
-            }
-        }
-    }
+    TestData testData;
+    testData.renderSurfaceW = gRenderSurfaceW;
+    testData.renderSurfaceH = gRenderSurfaceH;
+    testData.user = fillNum;
+    rsForEach(gFontScript, gDummyAlloc, gDummyAlloc, &testData);
 }
 
 static void bindProgramVertexOrtho() {
@@ -555,212 +511,37 @@
     drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
 }
 
-static float gTorusRotation = 0;
-static void updateModelMatrix(rs_matrix4x4 *matrix, void *buffer) {
-    if (buffer == 0) {
-        rsgProgramVertexLoadModelMatrix(matrix);
-    } else {
-        rsgAllocationSyncAll(rsGetAllocation(buffer));
-    }
-}
-
-static void drawToruses(int numMeshes, rs_matrix4x4 *matrix, void *buffer) {
-
-    if (numMeshes == 1) {
-        rsMatrixLoadTranslate(matrix, 0.0f, 0.0f, -7.5f);
-        rsMatrixRotate(matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
-        updateModelMatrix(matrix, buffer);
-        rsgDrawMesh(gTorusMesh);
-        return;
-    }
-
-    if (numMeshes == 2) {
-        rsMatrixLoadTranslate(matrix, -1.6f, 0.0f, -7.5f);
-        rsMatrixRotate(matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
-        updateModelMatrix(matrix, buffer);
-        rsgDrawMesh(gTorusMesh);
-
-        rsMatrixLoadTranslate(matrix, 1.6f, 0.0f, -7.5f);
-        rsMatrixRotate(matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
-        updateModelMatrix(matrix, buffer);
-        rsgDrawMesh(gTorusMesh);
-        return;
-    }
-
-    float startX = -5.0f;
-    float startY = -1.5f;
-    float startZ = -15.0f;
-    float dist = 3.2f;
-
-    for (int h = 0; h < 4; h ++) {
-        for (int v = 0; v < 2; v ++) {
-            // Position our model on the screen
-            rsMatrixLoadTranslate(matrix, startX + dist * h, startY + dist * v, startZ);
-            rsMatrixRotate(matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
-            updateModelMatrix(matrix, buffer);
-            rsgDrawMesh(gTorusMesh);
-        }
-    }
-}
-
 // Quick hack to get some geometry numbers
 static void displaySimpleGeoSamples(bool useTexture, int numMeshes) {
-    rsgBindProgramVertex(gProgVertex);
-    rsgBindProgramRaster(gCullBack);
-    // Setup the projection matrix with 30 degree field of view
-    rs_matrix4x4 proj;
-    float aspect = (float)gRenderSurfaceW / (float)gRenderSurfaceH;
-    rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f);
-    rsgProgramVertexLoadProjectionMatrix(&proj);
-
-    // Fragment shader with texture
-    rsgBindProgramStore(gProgStoreBlendNoneDepth);
-    if (useTexture) {
-        rsgBindProgramFragment(gProgFragmentTexture);
-    } else {
-        rsgBindProgramFragment(gProgFragmentColor);
-        rsgProgramFragmentConstantColor(gProgFragmentColor, 0.1, 0.7, 0.1, 1);
-    }
-    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
-    rsgBindTexture(gProgFragmentTexture, 0, gTexTorus);
-
-    // Apply a rotation to our mesh
-    gTorusRotation += 50.0f * gDt;
-    if (gTorusRotation > 360.0f) {
-        gTorusRotation -= 360.0f;
-    }
-
-    rs_matrix4x4 matrix;
-    drawToruses(numMeshes, &matrix, 0);
-}
-
-float gLight0Rotation = 0;
-float gLight1Rotation = 0;
-
-static void setupCustomShaderLights() {
-    float4 light0Pos = {-5.0f, 5.0f, -10.0f, 1.0f};
-    float4 light1Pos = {2.0f, 5.0f, 15.0f, 1.0f};
-    float4 light0DiffCol = {0.9f, 0.7f, 0.7f, 1.0f};
-    float4 light0SpecCol = {0.9f, 0.6f, 0.6f, 1.0f};
-    float4 light1DiffCol = {0.5f, 0.5f, 0.9f, 1.0f};
-    float4 light1SpecCol = {0.5f, 0.5f, 0.9f, 1.0f};
-
-    gLight0Rotation += 50.0f * gDt;
-    if (gLight0Rotation > 360.0f) {
-        gLight0Rotation -= 360.0f;
-    }
-    gLight1Rotation -= 50.0f * gDt;
-    if (gLight1Rotation > 360.0f) {
-        gLight1Rotation -= 360.0f;
-    }
-
-    rs_matrix4x4 l0Mat;
-    rsMatrixLoadRotate(&l0Mat, gLight0Rotation, 1.0f, 0.0f, 0.0f);
-    light0Pos = rsMatrixMultiply(&l0Mat, light0Pos);
-    rs_matrix4x4 l1Mat;
-    rsMatrixLoadRotate(&l1Mat, gLight1Rotation, 0.0f, 0.0f, 1.0f);
-    light1Pos = rsMatrixMultiply(&l1Mat, light1Pos);
-
-    // Set light 0 properties
-    gVSConstants->light0_Posision = light0Pos;
-    gVSConstants->light0_Diffuse = 1.0f;
-    gVSConstants->light0_Specular = 0.5f;
-    gVSConstants->light0_CosinePower = 10.0f;
-    // Set light 1 properties
-    gVSConstants->light1_Posision = light1Pos;
-    gVSConstants->light1_Diffuse = 1.0f;
-    gVSConstants->light1_Specular = 0.7f;
-    gVSConstants->light1_CosinePower = 25.0f;
-    rsgAllocationSyncAll(rsGetAllocation(gVSConstants));
-
-    // Update fragment shader constants
-    // Set light 0 colors
-    gFSConstants->light0_DiffuseColor = light0DiffCol;
-    gFSConstants->light0_SpecularColor = light0SpecCol;
-    // Set light 1 colors
-    gFSConstants->light1_DiffuseColor = light1DiffCol;
-    gFSConstants->light1_SpecularColor = light1SpecCol;
-    rsgAllocationSyncAll(rsGetAllocation(gFSConstants));
-
-    // Set light 0 properties for per pixel lighting
-    gFSConstPixel->light0_Posision = light0Pos;
-    gFSConstPixel->light0_Diffuse = 1.0f;
-    gFSConstPixel->light0_Specular = 0.5f;
-    gFSConstPixel->light0_CosinePower = 10.0f;
-    gFSConstPixel->light0_DiffuseColor = light0DiffCol;
-    gFSConstPixel->light0_SpecularColor = light0SpecCol;
-    // Set light 1 properties
-    gFSConstPixel->light1_Posision = light1Pos;
-    gFSConstPixel->light1_Diffuse = 1.0f;
-    gFSConstPixel->light1_Specular = 0.7f;
-    gFSConstPixel->light1_CosinePower = 25.0f;
-    gFSConstPixel->light1_DiffuseColor = light1DiffCol;
-    gFSConstPixel->light1_SpecularColor = light1SpecCol;
-    rsgAllocationSyncAll(rsGetAllocation(gFSConstPixel));
+    TestData testData;
+    testData.renderSurfaceW = gRenderSurfaceW;
+    testData.renderSurfaceH = gRenderSurfaceH;
+    testData.dt = gDt;
+    testData.user = 0;
+    testData.user1 = useTexture ? 1 : 0;
+    testData.user2 = numMeshes;
+    rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData);
 }
 
 static void displayCustomShaderSamples(int numMeshes) {
-
-    // Update vertex shader constants
-    // Load model matrix
-    // Apply a rotation to our mesh
-    gTorusRotation += 50.0f * gDt;
-    if (gTorusRotation > 360.0f) {
-        gTorusRotation -= 360.0f;
-    }
-
-    // Setup the projection matrix
-    float aspect = (float)gRenderSurfaceW / (float)gRenderSurfaceH;
-    rsMatrixLoadPerspective(&gVSConstants->proj, 30.0f, aspect, 0.1f, 100.0f);
-    setupCustomShaderLights();
-
-    rsgBindProgramVertex(gProgVertexCustom);
-
-    // Fragment shader with texture
-    rsgBindProgramStore(gProgStoreBlendNoneDepth);
-    rsgBindProgramFragment(gProgFragmentCustom);
-    rsgBindSampler(gProgFragmentCustom, 0, gLinearClamp);
-    rsgBindTexture(gProgFragmentCustom, 0, gTexTorus);
-
-    // Use back face culling
-    rsgBindProgramRaster(gCullBack);
-
-    drawToruses(numMeshes, &gVSConstants->model, gVSConstants);
+    TestData testData;
+    testData.renderSurfaceW = gRenderSurfaceW;
+    testData.renderSurfaceH = gRenderSurfaceH;
+    testData.dt = gDt;
+    testData.user = 1;
+    testData.user1 = numMeshes;
+    rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData);
 }
 
 static void displayPixelLightSamples(int numMeshes, bool heavyVertex) {
-
-    // Update vertex shader constants
-    // Load model matrix
-    // Apply a rotation to our mesh
-    gTorusRotation += 30.0f * gDt;
-    if (gTorusRotation > 360.0f) {
-        gTorusRotation -= 360.0f;
-    }
-
-    gVSConstPixel->time = rsUptimeMillis()*0.005;
-
-    // Setup the projection matrix
-    float aspect = (float)gRenderSurfaceW / (float)gRenderSurfaceH;
-    rsMatrixLoadPerspective(&gVSConstPixel->proj, 30.0f, aspect, 0.1f, 100.0f);
-    setupCustomShaderLights();
-
-    if (heavyVertex) {
-        rsgBindProgramVertex(gProgVertexPixelLightMove);
-    } else {
-        rsgBindProgramVertex(gProgVertexPixelLight);
-    }
-
-    // Fragment shader with texture
-    rsgBindProgramStore(gProgStoreBlendNoneDepth);
-    rsgBindProgramFragment(gProgFragmentPixelLight);
-    rsgBindSampler(gProgFragmentPixelLight, 0, gLinearClamp);
-    rsgBindTexture(gProgFragmentPixelLight, 0, gTexTorus);
-
-    // Use back face culling
-    rsgBindProgramRaster(gCullBack);
-
-    drawToruses(numMeshes, &gVSConstPixel->model, gVSConstPixel);
+    TestData testData;
+    testData.renderSurfaceW = gRenderSurfaceW;
+    testData.renderSurfaceH = gRenderSurfaceH;
+    testData.dt = gDt;
+    testData.user = 2;
+    testData.user1 = numMeshes;
+    testData.user2 = heavyVertex ? 1 : 0;
+    rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData);
 }
 
 static void displayMultitextureSample(bool blend, int quadCount) {
@@ -862,6 +643,20 @@
     "UI test with live wallpaper",
 };
 
+static bool gIsDebugMode = false;
+void setDebugMode(int testNumber) {
+    gIsDebugMode = true;
+    benchMode = testNumber;
+    rsgClearAllRenderTargets();
+}
+
+void setBenchmarkMode() {
+    gIsDebugMode = false;
+    benchMode = 0;
+    runningLoops = 0;
+}
+
+
 void getTestName(int testIndex) {
     int bufferLen = rsAllocationGetDimX(rsGetAllocation(gStringBuffer));
     if (testIndex >= gMaxModes) {
@@ -932,7 +727,7 @@
         displaySingletexFill(true, 10);
         break;
     case 18:
-        displayMultitextureSample(true, 8);
+        displayMultitextureSample(true, 10);
         break;
     case 19:
         displayPixelLightSamples(1, false);
@@ -992,14 +787,7 @@
                          startX + width, startY, 0, 1, 1);
 }
 
-int root(void) {
-    gRenderSurfaceW = rsgGetWidth();
-    gRenderSurfaceH = rsgGetHeight();
-    rsgClearColor(0.2f, 0.2f, 0.2f, 1.0f);
-    rsgClearDepth(1.0f);
-    if(!checkInit()) {
-        return 1;
-    }
+static void benchmark() {
 
     gDt = 1.0f / 60.0f;
 
@@ -1045,8 +833,6 @@
 
     benchMode ++;
 
-    gTorusRotation = 0;
-
     if (benchMode == gMaxModes) {
         rsSendToClientBlocking(RS_MSG_RESULTS_READY, gResultBuffer, gMaxModes*sizeof(float));
         benchMode = 0;
@@ -1058,5 +844,30 @@
             sendMsgFlag = true;
         }
     }
+
+}
+
+static void debug() {
+    gDt = rsGetDt();
+
+    rsgFinish();
+    runTest(benchMode);
+}
+
+int root(void) {
+    gRenderSurfaceW = rsgGetWidth();
+    gRenderSurfaceH = rsgGetHeight();
+    rsgClearColor(0.2f, 0.2f, 0.2f, 1.0f);
+    rsgClearDepth(1.0f);
+    if(!checkInit()) {
+        return 1;
+    }
+
+    if (gIsDebugMode) {
+        debug();
+    } else {
+        benchmark();
+    }
+
     return 1;
 }
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/subtest_def.rsh b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/subtest_def.rsh
new file mode 100644
index 0000000..b635373
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/subtest_def.rsh
@@ -0,0 +1,28 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.perftest)
+
+typedef struct TestData_s {
+    int renderSurfaceW;
+    int renderSurfaceH;
+    float dt;
+    int user;
+    int user1;
+    int user2;
+    int user3;
+} TestData;
+
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs
new file mode 100644
index 0000000..0df6b35
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs
@@ -0,0 +1,82 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.perftest)
+
+#include "rs_graphics.rsh"
+#include "subtest_def.rsh"
+
+rs_font gFontSans;
+rs_font gFontSerif;
+
+void init() {
+}
+
+static int gRenderSurfaceW = 1280;
+static int gRenderSurfaceH = 720;
+
+static const char *sampleText = "This is a sample of small text for performace";
+// Offsets for multiple layer of text
+static int textOffsets[] = { 0,  0, -5, -5, 5,  5, -8, -8, 8,  8};
+static float textColors[] = {1.0f, 1.0f, 1.0f, 1.0f,
+                             0.5f, 0.7f, 0.5f, 1.0f,
+                             0.7f, 0.5f, 0.5f, 1.0f,
+                             0.5f, 0.5f, 0.7f, 1.0f,
+                             0.5f, 0.6f, 0.7f, 1.0f,
+};
+
+static void displayFontSamples(int fillNum) {
+
+    rs_font fonts[5];
+    fonts[0] = gFontSans;
+    fonts[1] = gFontSerif;
+    fonts[2] = gFontSans;
+    fonts[3] = gFontSerif;
+    fonts[4] = gFontSans;
+
+    uint width = gRenderSurfaceW;
+    uint height = gRenderSurfaceH;
+    int left = 0, right = 0, top = 0, bottom = 0;
+    rsgMeasureText(sampleText, &left, &right, &top, &bottom);
+
+    int textHeight = top - bottom;
+    int textWidth = right - left;
+    int numVerticalLines = height / textHeight;
+    int yPos = top;
+
+    int xOffset = 0, yOffset = 0;
+    for(int fillI = 0; fillI < fillNum; fillI ++) {
+        rsgBindFont(fonts[fillI]);
+        xOffset = textOffsets[fillI * 2];
+        yOffset = textOffsets[fillI * 2 + 1];
+        float *colPtr = textColors + fillI * 4;
+        rsgFontColor(colPtr[0], colPtr[1], colPtr[2], colPtr[3]);
+        for (int h = 0; h < 4; h ++) {
+            yPos = top + yOffset;
+            for (int v = 0; v < numVerticalLines; v ++) {
+                rsgDrawText(sampleText, xOffset + textWidth * h, yPos);
+                yPos += textHeight;
+            }
+        }
+    }
+}
+
+void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
+    TestData *testData = (TestData*)usrData;
+    gRenderSurfaceW = testData->renderSurfaceW;
+    gRenderSurfaceH = testData->renderSurfaceH;
+    displayFontSamples(testData->user);
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/torus_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/torus_test.rs
new file mode 100644
index 0000000..26d5680
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/torus_test.rs
@@ -0,0 +1,283 @@
+// 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.perftest)
+
+#include "rs_graphics.rsh"
+#include "subtest_def.rsh"
+#include "shader_def.rsh"
+
+rs_program_vertex gProgVertex;
+rs_program_fragment gProgFragmentColor;
+rs_program_fragment gProgFragmentTexture;
+
+rs_program_store gProgStoreBlendNoneDepth;
+rs_mesh gTorusMesh;
+
+rs_program_raster gCullBack;
+rs_program_raster gCullFront;
+
+// Custom vertex shader compunents
+VertexShaderConstants *gVSConstants;
+FragentShaderConstants *gFSConstants;
+VertexShaderConstants3 *gVSConstPixel;
+FragentShaderConstants3 *gFSConstPixel;
+
+// Custom shaders we use for lighting
+rs_program_vertex gProgVertexCustom;
+rs_program_fragment gProgFragmentCustom;
+
+rs_sampler gLinearClamp;
+rs_allocation gTexTorus;
+
+rs_program_vertex gProgVertexPixelLight;
+rs_program_vertex gProgVertexPixelLightMove;
+rs_program_fragment gProgFragmentPixelLight;
+
+static float gDt = 0.0f;
+
+static int gRenderSurfaceW;
+static int gRenderSurfaceH;
+
+
+static float gTorusRotation = 0;
+static void updateModelMatrix(rs_matrix4x4 *matrix, void *buffer) {
+    if (buffer == 0) {
+        rsgProgramVertexLoadModelMatrix(matrix);
+    } else {
+        rsgAllocationSyncAll(rsGetAllocation(buffer));
+    }
+}
+
+static void drawToruses(int numMeshes, rs_matrix4x4 *matrix, void *buffer) {
+
+    if (numMeshes == 1) {
+        rsMatrixLoadTranslate(matrix, 0.0f, 0.0f, -7.5f);
+        rsMatrixRotate(matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
+        updateModelMatrix(matrix, buffer);
+        rsgDrawMesh(gTorusMesh);
+        return;
+    }
+
+    if (numMeshes == 2) {
+        rsMatrixLoadTranslate(matrix, -1.6f, 0.0f, -7.5f);
+        rsMatrixRotate(matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
+        updateModelMatrix(matrix, buffer);
+        rsgDrawMesh(gTorusMesh);
+
+        rsMatrixLoadTranslate(matrix, 1.6f, 0.0f, -7.5f);
+        rsMatrixRotate(matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
+        updateModelMatrix(matrix, buffer);
+        rsgDrawMesh(gTorusMesh);
+        return;
+    }
+
+    float startX = -5.0f;
+    float startY = -1.5f;
+    float startZ = -15.0f;
+    float dist = 3.2f;
+
+    for (int h = 0; h < 4; h ++) {
+        for (int v = 0; v < 2; v ++) {
+            // Position our model on the screen
+            rsMatrixLoadTranslate(matrix, startX + dist * h, startY + dist * v, startZ);
+            rsMatrixRotate(matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
+            updateModelMatrix(matrix, buffer);
+            rsgDrawMesh(gTorusMesh);
+        }
+    }
+}
+
+
+// Quick hack to get some geometry numbers
+static void displaySimpleGeoSamples(bool useTexture, int numMeshes) {
+    rsgBindProgramVertex(gProgVertex);
+    rsgBindProgramRaster(gCullBack);
+    // Setup the projection matrix with 30 degree field of view
+    rs_matrix4x4 proj;
+    float aspect = (float)gRenderSurfaceW / (float)gRenderSurfaceH;
+    rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f);
+    rsgProgramVertexLoadProjectionMatrix(&proj);
+
+    // Fragment shader with texture
+    rsgBindProgramStore(gProgStoreBlendNoneDepth);
+    if (useTexture) {
+        rsgBindProgramFragment(gProgFragmentTexture);
+    } else {
+        rsgBindProgramFragment(gProgFragmentColor);
+        rsgProgramFragmentConstantColor(gProgFragmentColor, 0.1, 0.7, 0.1, 1);
+    }
+    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+    rsgBindTexture(gProgFragmentTexture, 0, gTexTorus);
+
+    // Apply a rotation to our mesh
+    gTorusRotation += 50.0f * gDt;
+    if (gTorusRotation > 360.0f) {
+        gTorusRotation -= 360.0f;
+    }
+
+    rs_matrix4x4 matrix;
+    drawToruses(numMeshes, &matrix, 0);
+}
+
+float gLight0Rotation = 0;
+float gLight1Rotation = 0;
+
+static void setupCustomShaderLights() {
+    float4 light0Pos = {-5.0f, 5.0f, -10.0f, 1.0f};
+    float4 light1Pos = {2.0f, 5.0f, 15.0f, 1.0f};
+    float4 light0DiffCol = {0.9f, 0.7f, 0.7f, 1.0f};
+    float4 light0SpecCol = {0.9f, 0.6f, 0.6f, 1.0f};
+    float4 light1DiffCol = {0.5f, 0.5f, 0.9f, 1.0f};
+    float4 light1SpecCol = {0.5f, 0.5f, 0.9f, 1.0f};
+
+    gLight0Rotation += 50.0f * gDt;
+    if (gLight0Rotation > 360.0f) {
+        gLight0Rotation -= 360.0f;
+    }
+    gLight1Rotation -= 50.0f * gDt;
+    if (gLight1Rotation > 360.0f) {
+        gLight1Rotation -= 360.0f;
+    }
+
+    rs_matrix4x4 l0Mat;
+    rsMatrixLoadRotate(&l0Mat, gLight0Rotation, 1.0f, 0.0f, 0.0f);
+    light0Pos = rsMatrixMultiply(&l0Mat, light0Pos);
+    rs_matrix4x4 l1Mat;
+    rsMatrixLoadRotate(&l1Mat, gLight1Rotation, 0.0f, 0.0f, 1.0f);
+    light1Pos = rsMatrixMultiply(&l1Mat, light1Pos);
+
+    // Set light 0 properties
+    gVSConstants->light0_Posision = light0Pos;
+    gVSConstants->light0_Diffuse = 1.0f;
+    gVSConstants->light0_Specular = 0.5f;
+    gVSConstants->light0_CosinePower = 10.0f;
+    // Set light 1 properties
+    gVSConstants->light1_Posision = light1Pos;
+    gVSConstants->light1_Diffuse = 1.0f;
+    gVSConstants->light1_Specular = 0.7f;
+    gVSConstants->light1_CosinePower = 25.0f;
+    rsgAllocationSyncAll(rsGetAllocation(gVSConstants));
+
+    // Update fragment shader constants
+    // Set light 0 colors
+    gFSConstants->light0_DiffuseColor = light0DiffCol;
+    gFSConstants->light0_SpecularColor = light0SpecCol;
+    // Set light 1 colors
+    gFSConstants->light1_DiffuseColor = light1DiffCol;
+    gFSConstants->light1_SpecularColor = light1SpecCol;
+    rsgAllocationSyncAll(rsGetAllocation(gFSConstants));
+
+    // Set light 0 properties for per pixel lighting
+    gFSConstPixel->light0_Posision = light0Pos;
+    gFSConstPixel->light0_Diffuse = 1.0f;
+    gFSConstPixel->light0_Specular = 0.5f;
+    gFSConstPixel->light0_CosinePower = 10.0f;
+    gFSConstPixel->light0_DiffuseColor = light0DiffCol;
+    gFSConstPixel->light0_SpecularColor = light0SpecCol;
+    // Set light 1 properties
+    gFSConstPixel->light1_Posision = light1Pos;
+    gFSConstPixel->light1_Diffuse = 1.0f;
+    gFSConstPixel->light1_Specular = 0.7f;
+    gFSConstPixel->light1_CosinePower = 25.0f;
+    gFSConstPixel->light1_DiffuseColor = light1DiffCol;
+    gFSConstPixel->light1_SpecularColor = light1SpecCol;
+    rsgAllocationSyncAll(rsGetAllocation(gFSConstPixel));
+}
+
+static void displayCustomShaderSamples(int numMeshes) {
+
+    // Update vertex shader constants
+    // Load model matrix
+    // Apply a rotation to our mesh
+    gTorusRotation += 50.0f * gDt;
+    if (gTorusRotation > 360.0f) {
+        gTorusRotation -= 360.0f;
+    }
+
+    // Setup the projection matrix
+    float aspect = (float)gRenderSurfaceW / (float)gRenderSurfaceH;
+    rsMatrixLoadPerspective(&gVSConstants->proj, 30.0f, aspect, 0.1f, 100.0f);
+    setupCustomShaderLights();
+
+    rsgBindProgramVertex(gProgVertexCustom);
+
+    // Fragment shader with texture
+    rsgBindProgramStore(gProgStoreBlendNoneDepth);
+    rsgBindProgramFragment(gProgFragmentCustom);
+    rsgBindSampler(gProgFragmentCustom, 0, gLinearClamp);
+    rsgBindTexture(gProgFragmentCustom, 0, gTexTorus);
+
+    // Use back face culling
+    rsgBindProgramRaster(gCullBack);
+
+    drawToruses(numMeshes, &gVSConstants->model, gVSConstants);
+}
+
+static void displayPixelLightSamples(int numMeshes, bool heavyVertex) {
+
+    // Update vertex shader constants
+    // Load model matrix
+    // Apply a rotation to our mesh
+    gTorusRotation += 30.0f * gDt;
+    if (gTorusRotation > 360.0f) {
+        gTorusRotation -= 360.0f;
+    }
+
+    gVSConstPixel->time = rsUptimeMillis()*0.005;
+
+    // Setup the projection matrix
+    float aspect = (float)gRenderSurfaceW / (float)gRenderSurfaceH;
+    rsMatrixLoadPerspective(&gVSConstPixel->proj, 30.0f, aspect, 0.1f, 100.0f);
+    setupCustomShaderLights();
+
+    if (heavyVertex) {
+        rsgBindProgramVertex(gProgVertexPixelLightMove);
+    } else {
+        rsgBindProgramVertex(gProgVertexPixelLight);
+    }
+
+    // Fragment shader with texture
+    rsgBindProgramStore(gProgStoreBlendNoneDepth);
+    rsgBindProgramFragment(gProgFragmentPixelLight);
+    rsgBindSampler(gProgFragmentPixelLight, 0, gLinearClamp);
+    rsgBindTexture(gProgFragmentPixelLight, 0, gTexTorus);
+
+    // Use back face culling
+    rsgBindProgramRaster(gCullBack);
+
+    drawToruses(numMeshes, &gVSConstPixel->model, gVSConstPixel);
+}
+
+
+void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
+    TestData *testData = (TestData*)usrData;
+    gRenderSurfaceW = testData->renderSurfaceW;
+    gRenderSurfaceH = testData->renderSurfaceH;
+    gDt = testData->dt;
+
+    switch(testData->user) {
+        case 0:
+            displaySimpleGeoSamples(testData->user1 == 1 ? true : false, testData->user2);
+            break;
+        case 1:
+            displayCustomShaderSamples(testData->user1);
+            break;
+        case 2:
+            displayPixelLightSamples(testData->user1, testData->user2 == 1 ? true : false);
+            break;
+    }
+}
diff --git a/voip/java/android/net/sip/ISipSessionListener.aidl b/voip/java/android/net/sip/ISipSessionListener.aidl
index 5920bca..690700c 100644
--- a/voip/java/android/net/sip/ISipSessionListener.aidl
+++ b/voip/java/android/net/sip/ISipSessionListener.aidl
@@ -72,6 +72,14 @@
     void onCallBusy(in ISipSession session);
 
     /**
+     * Called when the call is being transferred to a new one.
+     *
+     * @param newSession the new session that the call will be transferred to
+     * @param sessionDescription the new peer's session description
+     */
+    void onCallTransferring(in ISipSession newSession, String sessionDescription);
+
+    /**
      * Called when an error occurs during session initialization and
      * termination.
      *
diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index b46f826..c1affa6 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -26,6 +26,7 @@
 import android.net.wifi.WifiManager;
 import android.os.Message;
 import android.os.RemoteException;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.io.IOException;
@@ -170,6 +171,7 @@
     private SipProfile mLocalProfile;
     private SipAudioCall.Listener mListener;
     private SipSession mSipSession;
+    private SipSession mTransferringSession;
 
     private long mSessionId = System.currentTimeMillis();
     private String mPeerSd;
@@ -347,6 +349,27 @@
         }
     }
 
+    private synchronized void transferToNewSession() {
+        if (mTransferringSession == null) return;
+        SipSession origin = mSipSession;
+        mSipSession = mTransferringSession;
+        mTransferringSession = null;
+
+        // stop the replaced call.
+        if (mAudioStream != null) {
+            mAudioStream.join(null);
+        } else {
+            try {
+                mAudioStream = new AudioStream(InetAddress.getByName(
+                        getLocalIp()));
+            } catch (Throwable t) {
+                Log.i(TAG, "transferToNewSession(): " + t);
+            }
+        }
+        if (origin != null) origin.endCall();
+        startAudio();
+    }
+
     private SipSession.Listener createListener() {
         return new SipSession.Listener() {
             @Override
@@ -378,6 +401,7 @@
             @Override
             public void onRinging(SipSession session,
                     SipProfile peerProfile, String sessionDescription) {
+                // this callback is triggered only for reinvite.
                 synchronized (SipAudioCall.this) {
                     if ((mSipSession == null) || !mInCall
                             || !session.getCallId().equals(
@@ -404,6 +428,13 @@
                 mPeerSd = sessionDescription;
                 Log.v(TAG, "onCallEstablished()" + mPeerSd);
 
+                // TODO: how to notify the UI that the remote party is changed
+                if ((mTransferringSession != null)
+                        && (session == mTransferringSession)) {
+                    transferToNewSession();
+                    return;
+                }
+
                 Listener listener = mListener;
                 if (listener != null) {
                     try {
@@ -420,7 +451,17 @@
 
             @Override
             public void onCallEnded(SipSession session) {
-                Log.d(TAG, "sip call ended: " + session);
+                Log.d(TAG, "sip call ended: " + session + " mSipSession:" + mSipSession);
+                // reset the trasnferring session if it is the one.
+                if (session == mTransferringSession) {
+                    mTransferringSession = null;
+                    return;
+                }
+                // or ignore the event if the original session is being
+                // transferred to the new one.
+                if ((mTransferringSession != null) ||
+                    (session != mSipSession)) return;
+
                 Listener listener = mListener;
                 if (listener != null) {
                     try {
@@ -489,6 +530,22 @@
             public void onRegistrationDone(SipSession session, int duration) {
                 // irrelevant
             }
+
+            @Override
+            public void onCallTransferring(SipSession newSession,
+                    String sessionDescription) {
+                Log.v(TAG, "onCallTransferring mSipSession:"
+                        + mSipSession + " newSession:" + newSession);
+                mTransferringSession = newSession;
+                // session changing request
+                try {
+                    String answer = createAnswer(sessionDescription).encode();
+                    newSession.answerCall(answer, SESSION_TIMEOUT);
+                } catch (Throwable e) {
+                    Log.e(TAG, "onCallTransferring()", e);
+                    newSession.endCall();
+                }
+            }
         };
     }
 
@@ -675,6 +732,7 @@
     }
 
     private SimpleSessionDescription createAnswer(String offerSd) {
+        if (TextUtils.isEmpty(offerSd)) return createOffer();
         SimpleSessionDescription offer =
                 new SimpleSessionDescription(offerSd);
         SimpleSessionDescription answer =
diff --git a/voip/java/android/net/sip/SipSession.java b/voip/java/android/net/sip/SipSession.java
index 5629b3c..5ba1626 100644
--- a/voip/java/android/net/sip/SipSession.java
+++ b/voip/java/android/net/sip/SipSession.java
@@ -160,6 +160,17 @@
         }
 
         /**
+         * Called when the call is being transferred to a new one.
+         *
+         * @hide
+         * @param newSession the new session that the call will be transferred to
+         * @param sessionDescription the new peer's session description
+         */
+        public void onCallTransferring(SipSession newSession,
+                String sessionDescription) {
+        }
+
+        /**
          * Called when an error occurs during session initialization and
          * termination.
          *
@@ -489,6 +500,16 @@
                 }
             }
 
+            public void onCallTransferring(ISipSession session,
+                    String sessionDescription) {
+                if (mListener != null) {
+                    mListener.onCallTransferring(
+                            new SipSession(session, SipSession.this.mListener),
+                            sessionDescription);
+
+                }
+            }
+
             public void onCallChangeFailed(ISipSession session, int errorCode,
                     String message) {
                 if (mListener != null) {
diff --git a/voip/java/android/net/sip/SipSessionAdapter.java b/voip/java/android/net/sip/SipSessionAdapter.java
index 86aca37..f538983 100644
--- a/voip/java/android/net/sip/SipSessionAdapter.java
+++ b/voip/java/android/net/sip/SipSessionAdapter.java
@@ -42,6 +42,10 @@
     public void onCallBusy(ISipSession session) {
     }
 
+    public void onCallTransferring(ISipSession session,
+            String sessionDescription) {
+    }
+
     public void onCallChangeFailed(ISipSession session, int errorCode,
             String message) {
     }
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index 018e6de..c031bc1 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -150,9 +150,17 @@
 
     private ContactHeader createContactHeader(SipProfile profile)
             throws ParseException, SipException {
-        ListeningPoint lp = getListeningPoint();
-        SipURI contactURI =
-                createSipUri(profile.getUserName(), profile.getProtocol(), lp);
+        return createContactHeader(profile, null, 0);
+    }
+
+    private ContactHeader createContactHeader(SipProfile profile,
+            String ip, int port) throws ParseException,
+            SipException {
+        SipURI contactURI = (ip == null)
+                ? createSipUri(profile.getUserName(), profile.getProtocol(),
+                        getListeningPoint())
+                : createSipUri(profile.getUserName(), profile.getProtocol(),
+                        ip, port);
 
         Address contactAddress = mAddressFactory.createAddress(contactURI);
         contactAddress.setDisplayName(profile.getDisplayName());
@@ -168,9 +176,14 @@
 
     private SipURI createSipUri(String username, String transport,
             ListeningPoint lp) throws ParseException {
-        SipURI uri = mAddressFactory.createSipURI(username, lp.getIPAddress());
+        return createSipUri(username, transport, lp.getIPAddress(), lp.getPort());
+    }
+
+    private SipURI createSipUri(String username, String transport,
+            String ip, int port) throws ParseException {
+        SipURI uri = mAddressFactory.createSipURI(username, ip);
         try {
-            uri.setPort(lp.getPort());
+            uri.setPort(port);
             uri.setTransportParam(transport);
         } catch (InvalidArgumentException e) {
             throw new RuntimeException(e);
@@ -314,7 +327,7 @@
         }
     }
 
-    private ServerTransaction getServerTransaction(RequestEvent event)
+    public ServerTransaction getServerTransaction(RequestEvent event)
             throws SipException {
         ServerTransaction transaction = event.getServerTransaction();
         if (transaction == null) {
@@ -353,13 +366,14 @@
      */
     public ServerTransaction sendInviteOk(RequestEvent event,
             SipProfile localProfile, String sessionDescription,
-            ServerTransaction inviteTransaction)
-            throws SipException {
+            ServerTransaction inviteTransaction, String externalIp,
+            int externalPort) throws SipException {
         try {
             Request request = event.getRequest();
             Response response = mMessageFactory.createResponse(Response.OK,
                     request);
-            response.addHeader(createContactHeader(localProfile));
+            response.addHeader(createContactHeader(localProfile, externalIp,
+                    externalPort));
             response.setContent(sessionDescription,
                     mHeaderFactory.createContentTypeHeader(
                             "application", "sdp"));
diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
index 3b0f546..c553947 100644
--- a/voip/java/com/android/server/sip/SipService.java
+++ b/voip/java/com/android/server/sip/SipService.java
@@ -74,6 +74,7 @@
     private static final int SHORT_EXPIRY_TIME = 10;
     private static final int MIN_EXPIRY_TIME = 60;
     private static final int DEFAULT_KEEPALIVE_INTERVAL = 10; // in seconds
+    private static final int DEFAULT_MAX_KEEPALIVE_INTERVAL = 120; // in seconds
 
     private Context mContext;
     private String mLocalIp;
@@ -83,6 +84,8 @@
     private WifiScanProcess mWifiScanProcess;
     private WifiManager.WifiLock mWifiLock;
     private boolean mWifiOnly;
+    private BroadcastReceiver mWifiStateReceiver = null;
+
     private IntervalMeasurementProcess mIntervalMeasurementProcess;
 
     private MyExecutor mExecutor = new MyExecutor();
@@ -99,6 +102,7 @@
     private boolean mWifiEnabled;
     private SipWakeLock mMyWakeLock;
     private int mKeepAliveInterval;
+    private int mLastGoodKeepAliveInterval = DEFAULT_KEEPALIVE_INTERVAL;
 
     /**
      * Starts the SIP service. Do nothing if the SIP API is not supported on the
@@ -123,40 +127,47 @@
         mWifiOnly = SipManager.isSipWifiOnly(context);
     }
 
-    private BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
-                int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
-                        WifiManager.WIFI_STATE_UNKNOWN);
-                synchronized (SipService.this) {
-                    switch (state) {
-                        case WifiManager.WIFI_STATE_ENABLED:
-                            mWifiEnabled = true;
-                            if (anyOpenedToReceiveCalls()) grabWifiLock();
-                            break;
-                        case WifiManager.WIFI_STATE_DISABLED:
-                            mWifiEnabled = false;
-                            releaseWifiLock();
-                            break;
+    private BroadcastReceiver createWifiBroadcastReceiver() {
+        return new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                String action = intent.getAction();
+                if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
+                    int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+                            WifiManager.WIFI_STATE_UNKNOWN);
+                    synchronized (SipService.this) {
+                        switch (state) {
+                            case WifiManager.WIFI_STATE_ENABLED:
+                                mWifiEnabled = true;
+                                if (anyOpenedToReceiveCalls()) grabWifiLock();
+                                break;
+                            case WifiManager.WIFI_STATE_DISABLED:
+                                mWifiEnabled = false;
+                                releaseWifiLock();
+                                break;
+                        }
                     }
                 }
             }
-        }
+        };
     };
 
     private void registerReceivers() {
         mContext.registerReceiver(mConnectivityReceiver,
                 new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
-        mContext.registerReceiver(mWifiStateReceiver,
-                new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
+        if (SipManager.isSipWifiOnly(mContext)) {
+            mWifiStateReceiver = createWifiBroadcastReceiver();
+            mContext.registerReceiver(mWifiStateReceiver,
+                    new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
+        }
         if (DEBUG) Log.d(TAG, " +++ register receivers");
     }
 
     private void unregisterReceivers() {
         mContext.unregisterReceiver(mConnectivityReceiver);
-        mContext.unregisterReceiver(mWifiStateReceiver);
+        if (SipManager.isSipWifiOnly(mContext)) {
+            mContext.unregisterReceiver(mWifiStateReceiver);
+        }
         if (DEBUG) Log.d(TAG, " --- unregister receivers");
     }
 
@@ -439,6 +450,7 @@
             if (connected) {
                 mLocalIp = determineLocalIp();
                 mKeepAliveInterval = -1;
+                mLastGoodKeepAliveInterval = DEFAULT_KEEPALIVE_INTERVAL;
                 for (SipSessionGroupExt group : mSipGroups.values()) {
                     group.onConnectivityChanged(true);
                 }
@@ -462,7 +474,8 @@
 
     private void startPortMappingLifetimeMeasurement(
             SipProfile localProfile) {
-        startPortMappingLifetimeMeasurement(localProfile, -1);
+        startPortMappingLifetimeMeasurement(localProfile,
+                DEFAULT_MAX_KEEPALIVE_INTERVAL);
     }
 
     private void startPortMappingLifetimeMeasurement(
@@ -473,8 +486,16 @@
             Log.d(TAG, "start NAT port mapping timeout measurement on "
                     + localProfile.getUriString());
 
-            mIntervalMeasurementProcess =
-                    new IntervalMeasurementProcess(localProfile, maxInterval);
+            int minInterval = mLastGoodKeepAliveInterval;
+            if (minInterval >= maxInterval) {
+                // If mLastGoodKeepAliveInterval also does not work, reset it
+                // to the default min
+                minInterval = mLastGoodKeepAliveInterval
+                        = DEFAULT_KEEPALIVE_INTERVAL;
+                Log.d(TAG, "  reset min interval to " + minInterval);
+            }
+            mIntervalMeasurementProcess = new IntervalMeasurementProcess(
+                    localProfile, minInterval, maxInterval);
             mIntervalMeasurementProcess.start();
         }
     }
@@ -530,7 +551,7 @@
 
     private int getKeepAliveInterval() {
         return (mKeepAliveInterval < 0)
-                ? DEFAULT_KEEPALIVE_INTERVAL
+                ? mLastGoodKeepAliveInterval
                 : mKeepAliveInterval;
     }
 
@@ -756,31 +777,36 @@
         }
     }
 
-    private class IntervalMeasurementProcess implements
+    private class IntervalMeasurementProcess implements Runnable,
             SipSessionGroup.KeepAliveProcessCallback {
         private static final String TAG = "SipKeepAliveInterval";
-        private static final int MAX_INTERVAL = 120; // in seconds
-        private static final int MIN_INTERVAL = 10; // in seconds
+        private static final int MIN_INTERVAL = 5; // in seconds
         private static final int PASS_THRESHOLD = 10;
         private static final int MAX_RETRY_COUNT = 5;
+        private static final int NAT_MEASUREMENT_RETRY_INTERVAL = 120; // in seconds
         private SipSessionGroupExt mGroup;
         private SipSessionGroup.SipSessionImpl mSession;
-        private boolean mRunning;
-        private int mMinInterval = 10; // in seconds
+        private int mMinInterval;
         private int mMaxInterval;
         private int mInterval;
         private int mPassCount = 0;
-        private int mErrorCount = 0;
 
-        public IntervalMeasurementProcess(SipProfile localProfile, int maxInterval) {
-            mMaxInterval = (maxInterval < 0) ? MAX_INTERVAL : maxInterval;
-            mInterval = (mMaxInterval + mMinInterval) / 2;
+        public IntervalMeasurementProcess(SipProfile localProfile,
+                int minInterval, int maxInterval) {
+            mMaxInterval = maxInterval;
+            mMinInterval = minInterval;
+            mInterval = (maxInterval + minInterval) / 2;
 
             // Don't start measurement if the interval is too small
-            if (mInterval < MIN_INTERVAL) {
+            if (mInterval < DEFAULT_KEEPALIVE_INTERVAL) {
                 Log.w(TAG, "interval is too small; measurement aborted; "
                         + "maxInterval=" + mMaxInterval);
                 return;
+            } else if (checkTermination()) {
+                Log.w(TAG, "interval is too small; measurement aborted; "
+                        + "interval=[" + mMinInterval + "," + mMaxInterval
+                        + "]");
+                return;
             }
 
             try {
@@ -788,8 +814,6 @@
                 // TODO: remove this line once SipWakeupTimer can better handle
                 // variety of timeout values
                 mGroup.setWakeupTimer(new SipWakeupTimer(mContext, mExecutor));
-                mSession = (SipSessionGroup.SipSessionImpl)
-                        mGroup.createSession(null);
             } catch (Exception e) {
                 Log.w(TAG, "start interval measurement error: " + e);
             }
@@ -797,6 +821,11 @@
 
         public void start() {
             synchronized (SipService.this) {
+                Log.d(TAG, "start measurement w interval=" + mInterval);
+                if (mSession == null) {
+                    mSession = (SipSessionGroup.SipSessionImpl)
+                            mGroup.createSession(null);
+                }
                 try {
                     mSession.startKeepAliveProcess(mInterval, this);
                 } catch (SipException e) {
@@ -807,14 +836,23 @@
 
         public void stop() {
             synchronized (SipService.this) {
-                mSession.stopKeepAliveProcess();
+                if (mSession != null) {
+                    mSession.stopKeepAliveProcess();
+                    mSession = null;
+                }
+                mTimer.cancel(this);
             }
         }
 
         private void restart() {
             synchronized (SipService.this) {
+                // Return immediately if the measurement process is stopped
+                if (mSession == null) return;
+
+                Log.d(TAG, "restart measurement w interval=" + mInterval);
                 try {
                     mSession.stopKeepAliveProcess();
+                    mPassCount = 0;
                     mSession.startKeepAliveProcess(mInterval, this);
                 } catch (SipException e) {
                     Log.e(TAG, "restart()", e);
@@ -822,16 +860,21 @@
             }
         }
 
+        private boolean checkTermination() {
+            return ((mMaxInterval - mMinInterval) < MIN_INTERVAL);
+        }
+
         // SipSessionGroup.KeepAliveProcessCallback
         @Override
         public void onResponse(boolean portChanged) {
             synchronized (SipService.this) {
-                mErrorCount = 0;
-
                 if (!portChanged) {
                     if (++mPassCount != PASS_THRESHOLD) return;
                     // update the interval, since the current interval is good to
                     // keep the port mapping.
+                    if (mKeepAliveInterval > 0) {
+                        mLastGoodKeepAliveInterval = mKeepAliveInterval;
+                    }
                     mKeepAliveInterval = mMinInterval = mInterval;
                     if (DEBUG) {
                         Log.d(TAG, "measured good keepalive interval: "
@@ -842,9 +885,13 @@
                     // Since the rport is changed, shorten the interval.
                     mMaxInterval = mInterval;
                 }
-                if ((mMaxInterval - mMinInterval) < MIN_INTERVAL) {
+                if (checkTermination()) {
                     // update mKeepAliveInterval and stop measurement.
                     stop();
+                    // If all the measurements failed, we still set it to
+                    // mMinInterval; If mMinInterval still doesn't work, a new
+                    // measurement with min interval=DEFAULT_KEEPALIVE_INTERVAL
+                    // will be conducted.
                     mKeepAliveInterval = mMinInterval;
                     if (DEBUG) {
                         Log.d(TAG, "measured keepalive interval: "
@@ -853,7 +900,6 @@
                 } else {
                     // calculate the new interval and continue.
                     mInterval = (mMaxInterval + mMinInterval) / 2;
-                    mPassCount = 0;
                     if (DEBUG) {
                         Log.d(TAG, "current interval: " + mKeepAliveInterval
                                 + ", test new interval: " + mInterval);
@@ -866,22 +912,32 @@
         // SipSessionGroup.KeepAliveProcessCallback
         @Override
         public void onError(int errorCode, String description) {
+            Log.w(TAG, "interval measurement error: " + description);
+            restartLater();
+        }
+
+        // timeout handler
+        @Override
+        public void run() {
+            mTimer.cancel(this);
+            restart();
+        }
+
+        private void restartLater() {
             synchronized (SipService.this) {
-                Log.w(TAG, "interval measurement error: " + description);
-                if (++mErrorCount < MAX_RETRY_COUNT) {
-                    Log.w(TAG, "  retry count = " + mErrorCount);
-                    mPassCount = 0;
-                    restart();
-                } else {
-                    Log.w(TAG, "  max retry count reached; measurement aborted");
-                }
+                int interval = NAT_MEASUREMENT_RETRY_INTERVAL;
+                Log.d(TAG, "Retry measurement " + interval + "s later.");
+                mTimer.cancel(this);
+                mTimer.set(interval * 1000, this);
             }
         }
     }
 
     private class AutoRegistrationProcess extends SipSessionAdapter
             implements Runnable, SipSessionGroup.KeepAliveProcessCallback {
+        private static final int MIN_KEEPALIVE_SUCCESS_COUNT = 10;
         private String TAG = "SipAudoReg";
+
         private SipSessionGroup.SipSessionImpl mSession;
         private SipSessionGroup.SipSessionImpl mKeepAliveSession;
         private SipSessionListenerProxy mProxy = new SipSessionListenerProxy();
@@ -892,6 +948,8 @@
         private String mErrorMessage;
         private boolean mRunning = false;
 
+        private int mKeepAliveSuccessCount = 0;
+
         private String getAction() {
             return toString();
         }
@@ -915,18 +973,56 @@
             }
         }
 
+        private void startKeepAliveProcess(int interval) {
+            Log.d(TAG, "start keepalive w interval=" + interval);
+            if (mKeepAliveSession == null) {
+                mKeepAliveSession = mSession.duplicate();
+            } else {
+                mKeepAliveSession.stopKeepAliveProcess();
+            }
+            try {
+                mKeepAliveSession.startKeepAliveProcess(interval, this);
+            } catch (SipException e) {
+                Log.e(TAG, "failed to start keepalive w interval=" + interval,
+                        e);
+            }
+        }
+
+        private void stopKeepAliveProcess() {
+            if (mKeepAliveSession != null) {
+                mKeepAliveSession.stopKeepAliveProcess();
+                mKeepAliveSession = null;
+            }
+            mKeepAliveSuccessCount = 0;
+        }
+
         // SipSessionGroup.KeepAliveProcessCallback
         @Override
         public void onResponse(boolean portChanged) {
             synchronized (SipService.this) {
                 if (portChanged) {
-                    restartPortMappingLifetimeMeasurement(
-                            mSession.getLocalProfile(), getKeepAliveInterval());
+                    int interval = getKeepAliveInterval();
+                    if (mKeepAliveSuccessCount < MIN_KEEPALIVE_SUCCESS_COUNT) {
+                        Log.i(TAG, "keepalive doesn't work with interval "
+                                + interval + ", past success count="
+                                + mKeepAliveSuccessCount);
+                        if (interval > DEFAULT_KEEPALIVE_INTERVAL) {
+                            restartPortMappingLifetimeMeasurement(
+                                    mSession.getLocalProfile(), interval);
+                            mKeepAliveSuccessCount = 0;
+                        }
+                    } else {
+                        Log.i(TAG, "keep keepalive going with interval "
+                                + interval + ", past success count="
+                                + mKeepAliveSuccessCount);
+                        mKeepAliveSuccessCount /= 2;
+                    }
                 } else {
                     // Start keep-alive interval measurement on the first
                     // successfully kept-alive SipSessionGroup
                     startPortMappingLifetimeMeasurement(
                             mSession.getLocalProfile());
+                    mKeepAliveSuccessCount++;
                 }
 
                 if (!mRunning || !portChanged) return;
@@ -960,10 +1056,7 @@
             }
 
             mTimer.cancel(this);
-            if (mKeepAliveSession != null) {
-                mKeepAliveSession.stopKeepAliveProcess();
-                mKeepAliveSession = null;
-            }
+            stopKeepAliveProcess();
 
             mRegistered = false;
             setListener(mProxy.getListener());
@@ -975,12 +1068,8 @@
                 if (DEBUGV) {
                     Log.v(TAG, "restart keepalive w interval=" + newInterval);
                 }
-                mKeepAliveSession.stopKeepAliveProcess();
-                try {
-                    mKeepAliveSession.startKeepAliveProcess(newInterval, this);
-                } catch (SipException e) {
-                    Log.e(TAG, "onKeepAliveIntervalChanged()", e);
-                }
+                mKeepAliveSuccessCount = 0;
+                startKeepAliveProcess(newInterval);
             }
         }
 
@@ -1105,14 +1194,7 @@
                         SipProfile localProfile = mSession.getLocalProfile();
                         if ((mKeepAliveSession == null) && (isBehindNAT(mLocalIp)
                                 || localProfile.getSendKeepAlive())) {
-                            mKeepAliveSession = mSession.duplicate();
-                            Log.d(TAG, "start keepalive");
-                            try {
-                                mKeepAliveSession.startKeepAliveProcess(
-                                        getKeepAliveInterval(), this);
-                            } catch (SipException e) {
-                                Log.e(TAG, "AutoRegistrationProcess", e);
-                            }
+                            startKeepAliveProcess(getKeepAliveInterval());
                         }
                     }
                     mMyWakeLock.release(session);
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 2d0dd9c..4e44402 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -21,6 +21,8 @@
 import gov.nist.javax.sip.header.SIPHeaderNames;
 import gov.nist.javax.sip.header.ProxyAuthenticate;
 import gov.nist.javax.sip.header.WWWAuthenticate;
+import gov.nist.javax.sip.header.extensions.ReferredByHeader;
+import gov.nist.javax.sip.header.extensions.ReplacesHeader;
 import gov.nist.javax.sip.message.SIPMessage;
 
 import android.net.sip.ISipSession;
@@ -91,6 +93,7 @@
     private static final int EXPIRY_TIME = 3600; // in seconds
     private static final int CANCEL_CALL_TIMER = 3; // in seconds
     private static final int KEEPALIVE_TIMEOUT = 3; // in seconds
+    private static final int INCALL_KEEPALIVE_INTERVAL = 10; // in seconds
     private static final long WAKE_LOCK_HOLDING_TIME = 500; // in milliseconds
 
     private static final EventObject DEREGISTER = new EventObject("Deregister");
@@ -116,6 +119,10 @@
     private Map<String, SipSessionImpl> mSessionMap =
             new HashMap<String, SipSessionImpl>();
 
+    // external address observed from any response
+    private String mExternalIp;
+    private int mExternalPort;
+
     /**
      * @param myself the local profile with password crossed out
      * @param password the password of the profile
@@ -172,6 +179,8 @@
 
         mCallReceiverSession = null;
         mSessionMap.clear();
+
+        resetExternalAddress();
     }
 
     synchronized void onConnectivityChanged() {
@@ -187,6 +196,12 @@
         }
     }
 
+    synchronized void resetExternalAddress() {
+        Log.d(TAG, " reset external addr on " + mSipStack);
+        mExternalIp = null;
+        mExternalPort = 0;
+    }
+
     public SipProfile getLocalProfile() {
         return mLocalProfile;
     }
@@ -360,29 +375,105 @@
         return null;
     }
 
+    private void extractExternalAddress(ResponseEvent evt) {
+        Response response = evt.getResponse();
+        ViaHeader viaHeader = (ViaHeader)(response.getHeader(
+                SIPHeaderNames.VIA));
+        if (viaHeader == null) return;
+        int rport = viaHeader.getRPort();
+        String externalIp = viaHeader.getReceived();
+        if ((rport > 0) && (externalIp != null)) {
+            mExternalIp = externalIp;
+            mExternalPort = rport;
+            Log.d(TAG, " got external addr " + externalIp + ":" + rport
+                    + " on " + mSipStack);
+        }
+    }
+
     private class SipSessionCallReceiverImpl extends SipSessionImpl {
         public SipSessionCallReceiverImpl(ISipSessionListener listener) {
             super(listener);
         }
 
+        private SipSessionImpl createNewSession(RequestEvent event,
+                ISipSessionListener listener, ServerTransaction transaction)
+                throws SipException {
+            SipSessionImpl newSession = new SipSessionImpl(listener);
+            newSession.mServerTransaction = transaction;
+            newSession.mState = SipSession.State.INCOMING_CALL;
+            newSession.mDialog = newSession.mServerTransaction.getDialog();
+            newSession.mInviteReceived = event;
+            newSession.mPeerProfile = createPeerProfile(event.getRequest());
+            newSession.mPeerSessionDescription =
+                    extractContent(event.getRequest());
+            return newSession;
+        }
+
+        private int processInviteWithReplaces(RequestEvent event,
+                ReplacesHeader replaces) {
+            String callId = replaces.getCallId();
+            SipSessionImpl session = mSessionMap.get(callId);
+            if (session == null) {
+                return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
+            }
+
+            Dialog dialog = session.mDialog;
+            if (dialog == null) return Response.DECLINE;
+
+            if (!dialog.getLocalTag().equals(replaces.getToTag()) ||
+                    !dialog.getRemoteTag().equals(replaces.getFromTag())) {
+                // No match is found, returns 481.
+                return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
+            }
+
+            ReferredByHeader referredBy = (ReferredByHeader) event.getRequest()
+                    .getHeader(ReferredByHeader.NAME);
+            if ((referredBy == null) ||
+                    !dialog.getRemoteParty().equals(referredBy.getAddress())) {
+                return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
+            }
+            return Response.OK;
+        }
+
+        private void processNewInviteRequest(RequestEvent event)
+                throws SipException {
+            ReplacesHeader replaces = (ReplacesHeader) event.getRequest()
+                    .getHeader(ReplacesHeader.NAME);
+            SipSessionImpl newSession = null;
+            if (replaces != null) {
+                int response = processInviteWithReplaces(event, replaces);
+                if (DEBUG) {
+                    Log.v(TAG, "ReplacesHeader: " + replaces
+                            + " response=" + response);
+                }
+                if (response == Response.OK) {
+                    SipSessionImpl replacedSession =
+                            mSessionMap.get(replaces.getCallId());
+                    // got INVITE w/ replaces request.
+                    newSession = createNewSession(event,
+                            replacedSession.mProxy.getListener(),
+                            mSipHelper.getServerTransaction(event));
+                    newSession.mProxy.onCallTransferring(newSession,
+                            newSession.mPeerSessionDescription);
+                } else {
+                    mSipHelper.sendResponse(event, response);
+                }
+            } else {
+                // New Incoming call.
+                newSession = createNewSession(event, mProxy,
+                        mSipHelper.sendRinging(event, generateTag()));
+                mProxy.onRinging(newSession, newSession.mPeerProfile,
+                        newSession.mPeerSessionDescription);
+            }
+            if (newSession != null) addSipSession(newSession);
+        }
+
         public boolean process(EventObject evt) throws SipException {
             if (isLoggable(this, evt)) Log.d(TAG, " ~~~~~   " + this + ": "
                     + SipSession.State.toString(mState) + ": processing "
                     + log(evt));
             if (isRequestEvent(Request.INVITE, evt)) {
-                RequestEvent event = (RequestEvent) evt;
-                SipSessionImpl newSession = new SipSessionImpl(mProxy);
-                newSession.mState = SipSession.State.INCOMING_CALL;
-                newSession.mServerTransaction = mSipHelper.sendRinging(event,
-                        generateTag());
-                newSession.mDialog = newSession.mServerTransaction.getDialog();
-                newSession.mInviteReceived = event;
-                newSession.mPeerProfile = createPeerProfile(event.getRequest());
-                newSession.mPeerSessionDescription =
-                        extractContent(event.getRequest());
-                addSipSession(newSession);
-                mProxy.onRinging(newSession, newSession.mPeerProfile,
-                        newSession.mPeerSessionDescription);
+                processNewInviteRequest((RequestEvent) evt);
                 return true;
             } else if (isRequestEvent(Request.OPTIONS, evt)) {
                 mSipHelper.sendResponse((RequestEvent) evt, Response.OK);
@@ -414,6 +505,8 @@
 
         private KeepAliveProcess mKeepAliveProcess;
 
+        private SipSessionImpl mKeepAliveSession;
+
         // lightweight timer
         class SessionTimer {
             private boolean mRunning = true;
@@ -482,6 +575,11 @@
             mClientTransaction = null;
 
             cancelSessionTimer();
+
+            if (mKeepAliveSession != null) {
+                mKeepAliveSession.stopKeepAliveProcess();
+                mKeepAliveSession = null;
+            }
         }
 
         public boolean isInCall() {
@@ -611,6 +709,7 @@
                     dialog = ((RequestEvent) evt).getDialog();
                 } else if (evt instanceof ResponseEvent) {
                     dialog = ((ResponseEvent) evt).getDialog();
+                    extractExternalAddress((ResponseEvent) evt);
                 }
                 if (dialog != null) mDialog = dialog;
 
@@ -913,7 +1012,8 @@
                 mServerTransaction = mSipHelper.sendInviteOk(mInviteReceived,
                         mLocalProfile,
                         ((MakeCallCommand) evt).getSessionDescription(),
-                        mServerTransaction);
+                        mServerTransaction,
+                        mExternalIp, mExternalPort);
                 startSessionTimer(((MakeCallCommand) evt).getTimeout());
                 return true;
             } else if (END_CALL == evt) {
@@ -936,7 +1036,13 @@
                 throws SipException {
             // expect ACK, CANCEL request
             if (isRequestEvent(Request.ACK, evt)) {
-                establishCall();
+                String sdp = extractContent(((RequestEvent) evt).getRequest());
+                if (sdp != null) mPeerSessionDescription = sdp;
+                if (mPeerSessionDescription == null) {
+                    onError(SipErrorCode.CLIENT_ERROR, "peer sdp is empty");
+                } else {
+                    establishCall(false);
+                }
                 return true;
             } else if (isRequestEvent(Request.CANCEL, evt)) {
                 // http://tools.ietf.org/html/rfc3261#section-9.2
@@ -968,7 +1074,7 @@
                 case Response.OK:
                     mSipHelper.sendInviteAck(event, mDialog);
                     mPeerSessionDescription = extractContent(response);
-                    establishCall();
+                    establishCall(true);
                     return true;
                 case Response.UNAUTHORIZED:
                 case Response.PROXY_AUTHENTICATION_REQUIRED:
@@ -1100,10 +1206,26 @@
                     response.getStatusCode());
         }
 
-        private void establishCall() {
+        private void enableKeepAlive() {
+            if (mKeepAliveSession != null) {
+                mKeepAliveSession.stopKeepAliveProcess();
+            } else {
+                mKeepAliveSession = duplicate();
+            }
+            try {
+                mKeepAliveSession.startKeepAliveProcess(
+                        INCALL_KEEPALIVE_INTERVAL, mPeerProfile, null);
+            } catch (SipException e) {
+                Log.w(TAG, "keepalive cannot be enabled; ignored", e);
+                mKeepAliveSession.stopKeepAliveProcess();
+            }
+        }
+
+        private void establishCall(boolean enableKeepAlive) {
             mState = SipSession.State.IN_CALL;
-            mInCall = true;
             cancelSessionTimer();
+            if (!mInCall && enableKeepAlive) enableKeepAlive();
+            mInCall = true;
             mProxy.onCallEstablished(this, mPeerSessionDescription);
         }
 
@@ -1283,6 +1405,7 @@
                     if (evt instanceof ResponseEvent) {
                         if (parseOptionsResult(evt)) {
                             if (mPortChanged) {
+                                resetExternalAddress();
                                 stop();
                             } else {
                                 cancelSessionTimer();
@@ -1312,8 +1435,11 @@
                     if (!mRunning) return;
 
                     if (DEBUG_PING) {
+                        String peerUri = (mPeerProfile == null)
+                                ? "null"
+                                : mPeerProfile.getUriString();
                         Log.d(TAG, "keepalive: " + mLocalProfile.getUriString()
-                                + " --> " + mPeerProfile + ", interval=" + mInterval);
+                                + " --> " + peerUri + ", interval=" + mInterval);
                     }
                     try {
                         sendKeepAlive();
diff --git a/voip/java/com/android/server/sip/SipSessionListenerProxy.java b/voip/java/com/android/server/sip/SipSessionListenerProxy.java
index f8be0a8..8655a3a 100644
--- a/voip/java/com/android/server/sip/SipSessionListenerProxy.java
+++ b/voip/java/com/android/server/sip/SipSessionListenerProxy.java
@@ -110,6 +110,20 @@
         });
     }
 
+    public void onCallTransferring(final ISipSession newSession,
+            final String sessionDescription) {
+        if (mListener == null) return;
+        proxy(new Runnable() {
+            public void run() {
+                try {
+                    mListener.onCallTransferring(newSession, sessionDescription);
+                } catch (Throwable t) {
+                    handle(t, "onCallTransferring()");
+                }
+            }
+        });
+    }
+
     public void onCallBusy(final ISipSession session) {
         if (mListener == null) return;
         proxy(new Runnable() {
diff --git a/voip/java/com/android/server/sip/SipWakeupTimer.java b/voip/java/com/android/server/sip/SipWakeupTimer.java
index 76780c0..00d47ac 100644
--- a/voip/java/com/android/server/sip/SipWakeupTimer.java
+++ b/voip/java/com/android/server/sip/SipWakeupTimer.java
@@ -83,7 +83,7 @@
         mEventQueue = null;
     }
 
-    private synchronized boolean stopped() {
+    private boolean stopped() {
         if (mEventQueue == null) {
             Log.w(TAG, "Timer stopped");
             return true;
@@ -233,7 +233,7 @@
     }
 
     @Override
-    public void onReceive(Context context, Intent intent) {
+    public synchronized void onReceive(Context context, Intent intent) {
         // This callback is already protected by AlarmManager's wake lock.
         String action = intent.getAction();
         if (getAction().equals(action)
@@ -261,7 +261,7 @@
         }
     }
 
-    private synchronized void execute(long triggerTime) {
+    private void execute(long triggerTime) {
         if (DEBUG_TIMER) Log.d(TAG, "time's up, triggerTime = "
                 + showTime(triggerTime) + ": " + mEventQueue.size());
         if (stopped() || mEventQueue.isEmpty()) return;
diff --git a/vpn/java/android/net/vpn/IVpnService.aidl b/vpn/java/android/net/vpn/IVpnService.aidl
deleted file mode 100644
index 6bf3edd..0000000
--- a/vpn/java/android/net/vpn/IVpnService.aidl
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2009, 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.vpn;
-
-import android.net.vpn.VpnProfile;
-
-/**
- * Interface to access a VPN service.
- * {@hide}
- */
-interface IVpnService {
-    /**
-     * Sets up a VPN connection.
-     * @param profile the profile object
-     * @param username the username for authentication
-     * @param password the corresponding password for authentication
-     * @return true if VPN is successfully connected
-     */
-    boolean connect(in VpnProfile profile, String username, String password);
-
-    /**
-     * Tears down the VPN connection.
-     */
-    void disconnect();
-
-    /**
-     * Gets the the current connection state.
-     */
-    String getState(in VpnProfile profile);
-
-    /**
-     * Returns the idle state.
-     * @return true if the system is not connecting/connected to a VPN
-     */
-    boolean isIdle();
-}
diff --git a/vpn/java/android/net/vpn/L2tpIpsecProfile.java b/vpn/java/android/net/vpn/L2tpIpsecProfile.java
deleted file mode 100644
index 4ae2dec..0000000
--- a/vpn/java/android/net/vpn/L2tpIpsecProfile.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2009, 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.vpn;
-
-import android.os.Parcel;
-
-/**
- * The profile for certificate-based L2TP-over-IPSec type of VPN.
- * {@hide}
- */
-public class L2tpIpsecProfile extends L2tpProfile {
-    private static final long serialVersionUID = 1L;
-
-    private String mUserCertificate;
-    private String mCaCertificate;
-
-    @Override
-    public VpnType getType() {
-        return VpnType.L2TP_IPSEC;
-    }
-
-    public void setCaCertificate(String name) {
-        mCaCertificate = name;
-    }
-
-    public String getCaCertificate() {
-        return mCaCertificate;
-    }
-
-    public void setUserCertificate(String name) {
-        mUserCertificate = name;
-    }
-
-    public String getUserCertificate() {
-        return mUserCertificate;
-    }
-
-    @Override
-    protected void readFromParcel(Parcel in) {
-        super.readFromParcel(in);
-        mCaCertificate = in.readString();
-        mUserCertificate = in.readString();
-    }
-
-    @Override
-    public void writeToParcel(Parcel parcel, int flags) {
-        super.writeToParcel(parcel, flags);
-        parcel.writeString(mCaCertificate);
-        parcel.writeString(mUserCertificate);
-    }
-}
diff --git a/vpn/java/android/net/vpn/L2tpIpsecPskProfile.java b/vpn/java/android/net/vpn/L2tpIpsecPskProfile.java
deleted file mode 100644
index 7a03018..0000000
--- a/vpn/java/android/net/vpn/L2tpIpsecPskProfile.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2009, 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.vpn;
-
-import android.os.Parcel;
-
-/**
- * The profile for pre-shared-key-based L2TP-over-IPSec type of VPN.
- * {@hide}
- */
-public class L2tpIpsecPskProfile extends L2tpProfile {
-    private static final long serialVersionUID = 1L;
-
-    private String mPresharedKey;
-
-    @Override
-    public VpnType getType() {
-        return VpnType.L2TP_IPSEC_PSK;
-    }
-
-    public void setPresharedKey(String key) {
-        mPresharedKey = key;
-    }
-
-    public String getPresharedKey() {
-        return mPresharedKey;
-    }
-
-    @Override
-    protected void readFromParcel(Parcel in) {
-        super.readFromParcel(in);
-        mPresharedKey = in.readString();
-    }
-
-    @Override
-    public void writeToParcel(Parcel parcel, int flags) {
-        super.writeToParcel(parcel, flags);
-        parcel.writeString(mPresharedKey);
-    }
-}
diff --git a/vpn/java/android/net/vpn/L2tpProfile.java b/vpn/java/android/net/vpn/L2tpProfile.java
deleted file mode 100644
index dbba0c5..0000000
--- a/vpn/java/android/net/vpn/L2tpProfile.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2009, 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.vpn;
-
-import android.os.Parcel;
-
-/**
- * The profile for L2TP type of VPN.
- * {@hide}
- */
-public class L2tpProfile extends VpnProfile {
-    private static final long serialVersionUID = 1L;
-
-    private boolean mSecret;
-    private String mSecretString;
-
-    @Override
-    public VpnType getType() {
-        return VpnType.L2TP;
-    }
-
-    /**
-     * Enables/disables the secret for authenticating tunnel connection.
-     */
-    public void setSecretEnabled(boolean enabled) {
-        mSecret = enabled;
-    }
-
-    public boolean isSecretEnabled() {
-        return mSecret;
-    }
-
-    public void setSecretString(String secret) {
-        mSecretString = secret;
-    }
-
-    public String getSecretString() {
-        return mSecretString;
-    }
-
-    @Override
-    protected void readFromParcel(Parcel in) {
-        super.readFromParcel(in);
-        mSecret = in.readInt() > 0;
-        mSecretString = in.readString();
-    }
-
-    @Override
-    public void writeToParcel(Parcel parcel, int flags) {
-        super.writeToParcel(parcel, flags);
-        parcel.writeInt(mSecret ? 1 : 0);
-        parcel.writeString(mSecretString);
-    }
-}
diff --git a/vpn/java/android/net/vpn/PptpProfile.java b/vpn/java/android/net/vpn/PptpProfile.java
deleted file mode 100644
index b4b7be5..0000000
--- a/vpn/java/android/net/vpn/PptpProfile.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2009, 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.vpn;
-
-import android.os.Parcel;
-
-/**
- * The profile for PPTP type of VPN.
- * {@hide}
- */
-public class PptpProfile extends VpnProfile {
-    private static final long serialVersionUID = 1L;
-    private boolean mEncryption = true;
-
-    @Override
-    public VpnType getType() {
-        return VpnType.PPTP;
-    }
-
-    /**
-     * Enables/disables the encryption for PPTP tunnel.
-     */
-    public void setEncryptionEnabled(boolean enabled) {
-        mEncryption = enabled;
-    }
-
-    public boolean isEncryptionEnabled() {
-        return mEncryption;
-    }
-
-    @Override
-    protected void readFromParcel(Parcel in) {
-        super.readFromParcel(in);
-        mEncryption = in.readInt() > 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel parcel, int flags) {
-        super.writeToParcel(parcel, flags);
-        parcel.writeInt(mEncryption ? 1 : 0);
-    }
-}
diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java
deleted file mode 100644
index 02486bb..0000000
--- a/vpn/java/android/net/vpn/VpnManager.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2009, 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.vpn;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Environment;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import com.android.server.vpn.VpnServiceBinder;
-
-/**
- * The class provides interface to manage all VPN-related tasks, including:
- * <ul>
- * <li>The list of supported VPN types.
- * <li>API's to start/stop the service of a particular type.
- * <li>API's to start the settings activity.
- * <li>API's to create a profile.
- * <li>API's to register/unregister a connectivity receiver and the keys to
- *      access the fields in a connectivity broadcast event.
- * </ul>
- * {@hide}
- */
-public class VpnManager {
-    /** Key to the profile name of a connectivity broadcast event. */
-    public static final String BROADCAST_PROFILE_NAME = "profile_name";
-    /** Key to the connectivity state of a connectivity broadcast event. */
-    public static final String BROADCAST_CONNECTION_STATE = "connection_state";
-    /** Key to the error code of a connectivity broadcast event. */
-    public static final String BROADCAST_ERROR_CODE = "err";
-    /** Error code to indicate an error from authentication. */
-    public static final int VPN_ERROR_AUTH = 51;
-    /** Error code to indicate the connection attempt failed. */
-    public static final int VPN_ERROR_CONNECTION_FAILED = 101;
-    /** Error code to indicate the server is not known. */
-    public static final int VPN_ERROR_UNKNOWN_SERVER = 102;
-    /** Error code to indicate an error from challenge response. */
-    public static final int VPN_ERROR_CHALLENGE = 5;
-    /** Error code to indicate an error of remote server hanging up. */
-    public static final int VPN_ERROR_REMOTE_HUNG_UP = 7;
-    /** Error code to indicate an error of remote PPP server hanging up. */
-    public static final int VPN_ERROR_REMOTE_PPP_HUNG_UP = 48;
-    /** Error code to indicate a PPP negotiation error. */
-    public static final int VPN_ERROR_PPP_NEGOTIATION_FAILED = 42;
-    /** Error code to indicate an error of losing connectivity. */
-    public static final int VPN_ERROR_CONNECTION_LOST = 103;
-    /** Largest error code used by VPN. */
-    public static final int VPN_ERROR_LARGEST = 200;
-    /** Error code to indicate a successful connection. */
-    public static final int VPN_ERROR_NO_ERROR = 0;
-
-    public static final String PROFILES_PATH = "/misc/vpn/profiles";
-
-    private static final String PACKAGE_PREFIX =
-            VpnManager.class.getPackage().getName() + ".";
-
-    // Action for broadcasting a connectivity state.
-    private static final String ACTION_VPN_CONNECTIVITY = "vpn.connectivity";
-
-    private static final String VPN_SERVICE_NAME = "vpn";
-
-    // Action to start VPN settings
-    private static final String ACTION_VPN_SETTINGS =
-            PACKAGE_PREFIX + "SETTINGS";
-
-    public static final String TAG = VpnManager.class.getSimpleName();
-
-    // TODO(oam): Test VPN when EFS is enabled (will do later)...
-    public static String getProfilePath() {
-        // This call will return the correct path if Encrypted FS is enabled or not.
-        return Environment.getSecureDataDirectory().getPath() + PROFILES_PATH;
-    }
-
-    /**
-     * Returns all supported VPN types.
-     */
-    public static VpnType[] getSupportedVpnTypes() {
-        return VpnType.values();
-    }
-
-    public static void startVpnService(Context c) {
-        ServiceManager.addService(VPN_SERVICE_NAME, new VpnServiceBinder(c));
-    }
-
-    private Context mContext;
-    private IVpnService mVpnService;
-
-    /**
-     * Creates a manager object with the specified context.
-     */
-    public VpnManager(Context c) {
-        mContext = c;
-        createVpnServiceClient();
-    }
-
-    private void createVpnServiceClient() {
-        IBinder b = ServiceManager.getService(VPN_SERVICE_NAME);
-        mVpnService = IVpnService.Stub.asInterface(b);
-    }
-
-    /**
-     * Sets up a VPN connection.
-     * @param profile the profile object
-     * @param username the username for authentication
-     * @param password the corresponding password for authentication
-     * @return true if VPN is successfully connected
-     */
-    public boolean connect(VpnProfile p, String username, String password) {
-        try {
-            return mVpnService.connect(p, username, password);
-        } catch (RemoteException e) {
-            Log.e(TAG, "connect()", e);
-            return false;
-        }
-    }
-
-    /**
-     * Tears down the VPN connection.
-     */
-    public void disconnect() {
-        try {
-            mVpnService.disconnect();
-        } catch (RemoteException e) {
-            Log.e(TAG, "disconnect()", e);
-        }
-    }
-
-    /**
-     * Gets the the current connection state.
-     */
-    public VpnState getState(VpnProfile p) {
-        try {
-            return Enum.valueOf(VpnState.class, mVpnService.getState(p));
-        } catch (RemoteException e) {
-            Log.e(TAG, "getState()", e);
-            return VpnState.IDLE;
-        }
-    }
-
-    /**
-     * Returns the idle state.
-     * @return true if the system is not connecting/connected to a VPN
-     */
-    public boolean isIdle() {
-        try {
-            return mVpnService.isIdle();
-        } catch (RemoteException e) {
-            Log.e(TAG, "isIdle()", e);
-            return true;
-        }
-    }
-
-    /**
-     * Creates a VPN profile of the specified type.
-     *
-     * @param type the VPN type
-     * @return the profile object
-     */
-    public VpnProfile createVpnProfile(VpnType type) {
-        return createVpnProfile(type, false);
-    }
-
-    /**
-     * Creates a VPN profile of the specified type.
-     *
-     * @param type the VPN type
-     * @param customized true if the profile is custom made
-     * @return the profile object
-     */
-    public VpnProfile createVpnProfile(VpnType type, boolean customized) {
-        try {
-            VpnProfile p = (VpnProfile) type.getProfileClass().newInstance();
-            p.setCustomized(customized);
-            return p;
-        } catch (InstantiationException e) {
-            return null;
-        } catch (IllegalAccessException e) {
-            return null;
-        }
-    }
-
-    /** Broadcasts the connectivity state of the specified profile. */
-    public void broadcastConnectivity(String profileName, VpnState s) {
-        broadcastConnectivity(profileName, s, VPN_ERROR_NO_ERROR);
-    }
-
-    /** Broadcasts the connectivity state with an error code. */
-    public void broadcastConnectivity(String profileName, VpnState s,
-            int error) {
-        Intent intent = new Intent(ACTION_VPN_CONNECTIVITY);
-        intent.putExtra(BROADCAST_PROFILE_NAME, profileName);
-        intent.putExtra(BROADCAST_CONNECTION_STATE, s);
-        if (error != VPN_ERROR_NO_ERROR) {
-            intent.putExtra(BROADCAST_ERROR_CODE, error);
-        }
-        mContext.sendBroadcast(intent);
-    }
-
-    public void registerConnectivityReceiver(BroadcastReceiver r) {
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(VpnManager.ACTION_VPN_CONNECTIVITY);
-        mContext.registerReceiver(r, filter);
-    }
-
-    public void unregisterConnectivityReceiver(BroadcastReceiver r) {
-        mContext.unregisterReceiver(r);
-    }
-
-    /** Starts the VPN settings activity. */
-    public void startSettingsActivity() {
-        Intent intent = new Intent(ACTION_VPN_SETTINGS);
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mContext.startActivity(intent);
-    }
-
-    /** Creates an intent to start the VPN settings activity. */
-    public Intent createSettingsActivityIntent() {
-        Intent intent = new Intent(ACTION_VPN_SETTINGS);
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        return intent;
-    }
-}
diff --git a/vpn/java/android/net/vpn/VpnProfile.aidl b/vpn/java/android/net/vpn/VpnProfile.aidl
deleted file mode 100644
index edeaef0..0000000
--- a/vpn/java/android/net/vpn/VpnProfile.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2009, 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.vpn;
-
-parcelable VpnProfile;
diff --git a/vpn/java/android/net/vpn/VpnProfile.java b/vpn/java/android/net/vpn/VpnProfile.java
deleted file mode 100644
index bd6c809..0000000
--- a/vpn/java/android/net/vpn/VpnProfile.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2009, 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.vpn;
-
-import android.content.Context;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.io.IOException;
-import java.io.Serializable;
-
-/**
- * A VPN profile.
- * {@hide}
- */
-public abstract class VpnProfile implements Parcelable, Serializable {
-    private static final long serialVersionUID = 1L;
-    private String mName; // unique display name
-    private String mId; // unique identifier
-    private String mServerName; // VPN server name
-    private String mDomainSuffices; // space separated list
-    private String mRouteList; // space separated list
-    private String mSavedUsername;
-    private boolean mIsCustomized;
-    private transient VpnState mState = VpnState.IDLE;
-
-    /** Sets a user-friendly name for this profile. */
-    public void setName(String name) {
-        mName = name;
-    }
-
-    public String getName() {
-        return mName;
-    }
-
-    /**
-     * Sets an ID for this profile.  The caller should make sure the
-     * uniqueness of the ID.
-     */
-    public void setId(String id) {
-        mId = id;
-    }
-
-    public String getId() {
-        return mId;
-    }
-
-    /**
-     * Sets the name of the VPN server. Used for DNS lookup.
-     */
-    public void setServerName(String name) {
-        mServerName = name;
-    }
-
-    public String getServerName() {
-        return mServerName;
-    }
-
-    /**
-     * Sets the domain suffices for DNS resolution.
-     *
-     * @param entries a comma-separated list of domain suffices
-     */
-    public void setDomainSuffices(String entries) {
-        mDomainSuffices = entries;
-    }
-
-    public String getDomainSuffices() {
-        return mDomainSuffices;
-    }
-
-    /**
-     * Sets the routing info for this VPN connection.
-     *
-     * @param entries a comma-separated list of routes; each entry is in the
-     *      format of "(network address)/(network mask)"
-     */
-    public void setRouteList(String entries) {
-        mRouteList = entries;
-    }
-
-    public String getRouteList() {
-        return mRouteList;
-    }
-
-    public void setSavedUsername(String name) {
-        mSavedUsername = name;
-    }
-
-    public String getSavedUsername() {
-        return mSavedUsername;
-    }
-
-    public void setState(VpnState state) {
-        mState = state;
-    }
-
-    public VpnState getState() {
-        return ((mState == null) ? VpnState.IDLE : mState);
-    }
-
-    public boolean isIdle() {
-        return (mState == VpnState.IDLE);
-    }
-
-    /**
-     * Returns whether this profile is custom made (as opposed to being
-     * created by provided user interface).
-     */
-    public boolean isCustomized() {
-        return mIsCustomized;
-    }
-
-    /**
-     * Returns the VPN type of the profile.
-     */
-    public abstract VpnType getType();
-
-    void setCustomized(boolean customized) {
-        mIsCustomized = customized;
-    }
-
-    protected void readFromParcel(Parcel in) {
-        mName = in.readString();
-        mId = in.readString();
-        mServerName = in.readString();
-        mDomainSuffices = in.readString();
-        mRouteList = in.readString();
-        mSavedUsername = in.readString();
-    }
-
-    public static final Parcelable.Creator<VpnProfile> CREATOR =
-            new Parcelable.Creator<VpnProfile>() {
-                public VpnProfile createFromParcel(Parcel in) {
-                    VpnType type = Enum.valueOf(VpnType.class, in.readString());
-                    boolean customized = in.readInt() > 0;
-                    VpnProfile p = new VpnManager(null).createVpnProfile(type,
-                            customized);
-                    if (p == null) return null;
-                    p.readFromParcel(in);
-                    return p;
-                }
-
-                public VpnProfile[] newArray(int size) {
-                    return new VpnProfile[size];
-                }
-            };
-
-    public void writeToParcel(Parcel parcel, int flags) {
-        parcel.writeString(getType().toString());
-        parcel.writeInt(mIsCustomized ? 1 : 0);
-        parcel.writeString(mName);
-        parcel.writeString(mId);
-        parcel.writeString(mServerName);
-        parcel.writeString(mDomainSuffices);
-        parcel.writeString(mRouteList);
-        parcel.writeString(mSavedUsername);
-    }
-
-    public int describeContents() {
-        return 0;
-    }
-}
diff --git a/vpn/java/android/net/vpn/VpnState.java b/vpn/java/android/net/vpn/VpnState.java
deleted file mode 100644
index 6e61f9c..0000000
--- a/vpn/java/android/net/vpn/VpnState.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2009, 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.vpn;
-
-/**
- * Enumeration of all VPN states.
- *
- * A normal VPN connection lifetime starts in {@link IDLE}. When a new
- * connection is about to be set up, it goes to {@link CONNECTING} and then
- * {@link CONNECTED} if successful; back to {@link IDLE} if failed.
- * When the connection is about to be torn down, it goes to
- * {@link DISCONNECTING} and then {@link IDLE}.
- * {@link CANCELLED} is a state when a VPN connection attempt is aborted, and
- * is in transition to {@link IDLE}.
- * The {@link UNUSABLE} state indicates that the profile is not in a state for
- * connecting due to possibly the integrity of the fields or another profile is
- * connecting etc.
- * The {@link UNKNOWN} state indicates that the profile state is to be
- * determined.
- * {@hide}
- */
-public enum VpnState {
-    CONNECTING, DISCONNECTING, CANCELLED, CONNECTED, IDLE, UNUSABLE, UNKNOWN
-}
diff --git a/vpn/java/android/net/vpn/VpnType.java b/vpn/java/android/net/vpn/VpnType.java
deleted file mode 100644
index 356f8b1..0000000
--- a/vpn/java/android/net/vpn/VpnType.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2009, 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.vpn;
-
-import com.android.internal.R;
-
-/**
- * Enumeration of all supported VPN types.
- * {@hide}
- */
-public enum VpnType {
-    PPTP("PPTP", R.string.pptp_vpn_description, PptpProfile.class),
-    L2TP("L2TP", R.string.l2tp_vpn_description, L2tpProfile.class),
-    L2TP_IPSEC_PSK("L2TP/IPSec PSK", R.string.l2tp_ipsec_psk_vpn_description,
-            L2tpIpsecPskProfile.class),
-    L2TP_IPSEC("L2TP/IPSec CRT", R.string.l2tp_ipsec_crt_vpn_description,
-            L2tpIpsecProfile.class);
-
-    private String mDisplayName;
-    private int mDescriptionId;
-    private Class<? extends VpnProfile> mClass;
-
-    VpnType(String displayName, int descriptionId,
-            Class<? extends VpnProfile> klass) {
-        mDisplayName = displayName;
-        mDescriptionId = descriptionId;
-        mClass = klass;
-    }
-
-    public String getDisplayName() {
-        return mDisplayName;
-    }
-
-    public int getDescriptionId() {
-        return mDescriptionId;
-    }
-
-    public Class<? extends VpnProfile> getProfileClass() {
-        return mClass;
-    }
-}
diff --git a/vpn/java/com/android/server/vpn/DaemonProxy.java b/vpn/java/com/android/server/vpn/DaemonProxy.java
deleted file mode 100644
index 289ee45..0000000
--- a/vpn/java/com/android/server/vpn/DaemonProxy.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.vpn;
-
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
-import android.net.vpn.VpnManager;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Serializable;
-
-/**
- * Proxy to start, stop and interact with a VPN daemon.
- * The daemon is expected to accept connection through Unix domain socket.
- * When the proxy successfully starts the daemon, it will establish a socket
- * connection with the daemon, to both send commands to the daemon and receive
- * response and connecting error code from the daemon.
- */
-class DaemonProxy implements Serializable {
-    private static final long serialVersionUID = 1L;
-    private static final boolean DBG = true;
-
-    private static final int WAITING_TIME = 15; // sec
-
-    private static final String SVC_STATE_CMD_PREFIX = "init.svc.";
-    private static final String SVC_START_CMD = "ctl.start";
-    private static final String SVC_STOP_CMD = "ctl.stop";
-    private static final String SVC_STATE_RUNNING = "running";
-    private static final String SVC_STATE_STOPPED = "stopped";
-
-    private static final int END_OF_ARGUMENTS = 255;
-
-    private String mName;
-    private String mTag;
-    private transient LocalSocket mControlSocket;
-
-    /**
-     * Creates a proxy of the specified daemon.
-     * @param daemonName name of the daemon
-     */
-    DaemonProxy(String daemonName) {
-        mName = daemonName;
-        mTag = "SProxy_" + daemonName;
-    }
-
-    String getName() {
-        return mName;
-    }
-
-    void start() throws IOException {
-        String svc = mName;
-
-        Log.i(mTag, "Start VPN daemon: " + svc);
-        SystemProperties.set(SVC_START_CMD, svc);
-
-        if (!blockUntil(SVC_STATE_RUNNING, WAITING_TIME)) {
-            throw new IOException("cannot start service: " + svc);
-        } else {
-            mControlSocket = createServiceSocket();
-        }
-    }
-
-    void sendCommand(String ...args) throws IOException {
-        OutputStream out = getControlSocketOutput();
-        for (String arg : args) outputString(out, arg);
-        out.write(END_OF_ARGUMENTS);
-        out.flush();
-
-        int result = getResultFromSocket(true);
-        if (result != args.length) {
-            throw new IOException("socket error, result from service: "
-                    + result);
-        }
-    }
-
-    // returns 0 if nothing is in the receive buffer
-    int getResultFromSocket() throws IOException {
-        return getResultFromSocket(false);
-    }
-
-    void closeControlSocket() {
-        if (mControlSocket == null) return;
-        try {
-            mControlSocket.close();
-        } catch (IOException e) {
-            Log.w(mTag, "close control socket", e);
-        } finally {
-            mControlSocket = null;
-        }
-    }
-
-    void stop() {
-        String svc = mName;
-        Log.i(mTag, "Stop VPN daemon: " + svc);
-        SystemProperties.set(SVC_STOP_CMD, svc);
-        boolean success = blockUntil(SVC_STATE_STOPPED, 5);
-        if (DBG) Log.d(mTag, "stopping " + svc + ", success? " + success);
-    }
-
-    boolean isStopped() {
-        String cmd = SVC_STATE_CMD_PREFIX + mName;
-        return SVC_STATE_STOPPED.equals(SystemProperties.get(cmd));
-    }
-
-    private int getResultFromSocket(boolean blocking) throws IOException {
-        LocalSocket s = mControlSocket;
-        if (s == null) return 0;
-        InputStream in = s.getInputStream();
-        if (!blocking && in.available() == 0) return 0;
-
-        int data = in.read();
-        Log.i(mTag, "got data from control socket: " + data);
-
-        return data;
-    }
-
-    private LocalSocket createServiceSocket() throws IOException {
-        LocalSocket s = new LocalSocket();
-        LocalSocketAddress a = new LocalSocketAddress(mName,
-                LocalSocketAddress.Namespace.RESERVED);
-
-        // try a few times in case the service has not listen()ed
-        IOException excp = null;
-        for (int i = 0; i < 10; i++) {
-            try {
-                s.connect(a);
-                return s;
-            } catch (IOException e) {
-                if (DBG) Log.d(mTag, "service not yet listen()ing; try again");
-                excp = e;
-                sleep(500);
-            }
-        }
-        throw excp;
-    }
-
-    private OutputStream getControlSocketOutput() throws IOException {
-        if (mControlSocket != null) {
-            return mControlSocket.getOutputStream();
-        } else {
-            throw new IOException("no control socket available");
-        }
-    }
-
-    /**
-     * Waits for the process to be in the expected state. The method returns
-     * false if after the specified duration (in seconds), the process is still
-     * not in the expected state.
-     */
-    private boolean blockUntil(String expectedState, int waitTime) {
-        String cmd = SVC_STATE_CMD_PREFIX + mName;
-        int sleepTime = 200; // ms
-        int n = waitTime * 1000 / sleepTime;
-        for (int i = 0; i < n; i++) {
-            if (expectedState.equals(SystemProperties.get(cmd))) {
-                if (DBG) {
-                    Log.d(mTag, mName + " is " + expectedState + " after "
-                            + (i * sleepTime) + " msec");
-                }
-                break;
-            }
-            sleep(sleepTime);
-        }
-        return expectedState.equals(SystemProperties.get(cmd));
-    }
-
-    private void outputString(OutputStream out, String s) throws IOException {
-        byte[] bytes = s.getBytes();
-        out.write(bytes.length);
-        out.write(bytes);
-        out.flush();
-    }
-
-    private void sleep(int msec) {
-        try {
-            Thread.currentThread().sleep(msec);
-        } catch (InterruptedException e) {
-            throw new RuntimeException(e);
-        }
-    }
-}
diff --git a/vpn/java/com/android/server/vpn/L2tpIpsecPskService.java b/vpn/java/com/android/server/vpn/L2tpIpsecPskService.java
deleted file mode 100644
index 50e0de1..0000000
--- a/vpn/java/com/android/server/vpn/L2tpIpsecPskService.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.vpn;
-
-import android.net.vpn.L2tpIpsecPskProfile;
-
-import java.io.IOException;
-
-/**
- * The service that manages the preshared key based L2TP-over-IPSec VPN
- * connection.
- */
-class L2tpIpsecPskService extends VpnService<L2tpIpsecPskProfile> {
-    private static final String IPSEC = "racoon";
-
-    @Override
-    protected void connect(String serverIp, String username, String password)
-            throws IOException {
-        L2tpIpsecPskProfile p = getProfile();
-        VpnDaemons daemons = getDaemons();
-
-        // IPSEC
-        daemons.startIpsecForL2tp(serverIp, p.getPresharedKey())
-                .closeControlSocket();
-
-        sleep(2000); // 2 seconds
-
-        // L2TP
-        daemons.startL2tp(serverIp,
-                (p.isSecretEnabled() ? p.getSecretString() : null),
-                username, password);
-    }
-}
diff --git a/vpn/java/com/android/server/vpn/L2tpIpsecService.java b/vpn/java/com/android/server/vpn/L2tpIpsecService.java
deleted file mode 100644
index 663b0e8..0000000
--- a/vpn/java/com/android/server/vpn/L2tpIpsecService.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.vpn;
-
-import android.net.vpn.L2tpIpsecProfile;
-import android.security.Credentials;
-
-import java.io.IOException;
-
-/**
- * The service that manages the certificate based L2TP-over-IPSec VPN connection.
- */
-class L2tpIpsecService extends VpnService<L2tpIpsecProfile> {
-    private static final String IPSEC = "racoon";
-
-    @Override
-    protected void connect(String serverIp, String username, String password)
-            throws IOException {
-        L2tpIpsecProfile p = getProfile();
-        VpnDaemons daemons = getDaemons();
-
-        // IPSEC
-        DaemonProxy ipsec = daemons.startIpsecForL2tp(serverIp,
-                Credentials.USER_PRIVATE_KEY + p.getUserCertificate(),
-                Credentials.USER_CERTIFICATE + p.getUserCertificate(),
-                Credentials.CA_CERTIFICATE + p.getCaCertificate());
-        ipsec.closeControlSocket();
-
-        sleep(2000); // 2 seconds
-
-        // L2TP
-        daemons.startL2tp(serverIp,
-                (p.isSecretEnabled() ? p.getSecretString() : null),
-                username, password);
-    }
-}
diff --git a/vpn/java/com/android/server/vpn/L2tpService.java b/vpn/java/com/android/server/vpn/L2tpService.java
deleted file mode 100644
index 784a366..0000000
--- a/vpn/java/com/android/server/vpn/L2tpService.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.vpn;
-
-import android.net.vpn.L2tpProfile;
-
-import java.io.IOException;
-
-/**
- * The service that manages the L2TP VPN connection.
- */
-class L2tpService extends VpnService<L2tpProfile> {
-    @Override
-    protected void connect(String serverIp, String username, String password)
-            throws IOException {
-        L2tpProfile p = getProfile();
-        getDaemons().startL2tp(serverIp,
-                (p.isSecretEnabled() ? p.getSecretString() : null),
-                username, password);
-    }
-}
diff --git a/vpn/java/com/android/server/vpn/PptpService.java b/vpn/java/com/android/server/vpn/PptpService.java
deleted file mode 100644
index de12710..0000000
--- a/vpn/java/com/android/server/vpn/PptpService.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.vpn;
-
-import android.net.vpn.PptpProfile;
-
-import java.io.IOException;
-
-/**
- * The service that manages the PPTP VPN connection.
- */
-class PptpService extends VpnService<PptpProfile> {
-    @Override
-    protected void connect(String serverIp, String username, String password)
-            throws IOException {
-        PptpProfile p = getProfile();
-        getDaemons().startPptp(serverIp, username, password,
-                p.isEncryptionEnabled());
-    }
-}
diff --git a/vpn/java/com/android/server/vpn/VpnConnectingError.java b/vpn/java/com/android/server/vpn/VpnConnectingError.java
deleted file mode 100644
index 3c4ec7d..0000000
--- a/vpn/java/com/android/server/vpn/VpnConnectingError.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.vpn;
-
-import java.io.IOException;
-
-/**
- * Exception thrown when a connecting attempt fails.
- */
-class VpnConnectingError extends IOException {
-    private int mErrorCode;
-
-    VpnConnectingError(int errorCode) {
-        super("Connecting error: " + errorCode);
-        mErrorCode = errorCode;
-    }
-
-    int getErrorCode() {
-        return mErrorCode;
-    }
-}
diff --git a/vpn/java/com/android/server/vpn/VpnDaemons.java b/vpn/java/com/android/server/vpn/VpnDaemons.java
deleted file mode 100644
index 499195f..0000000
--- a/vpn/java/com/android/server/vpn/VpnDaemons.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.vpn;
-
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * A helper class for managing native VPN daemons.
- */
-class VpnDaemons implements Serializable {
-    static final long serialVersionUID = 1L;
-    private final String TAG = VpnDaemons.class.getSimpleName();
-
-    private static final String MTPD = "mtpd";
-    private static final String IPSEC = "racoon";
-
-    private static final String L2TP = "l2tp";
-    private static final String L2TP_PORT = "1701";
-
-    private static final String PPTP = "pptp";
-    private static final String PPTP_PORT = "1723";
-
-    private static final String VPN_LINKNAME = "vpn";
-    private static final String PPP_ARGS_SEPARATOR = "";
-
-    private List<DaemonProxy> mDaemonList = new ArrayList<DaemonProxy>();
-
-    public DaemonProxy startL2tp(String serverIp, String secret,
-            String username, String password) throws IOException {
-        return startMtpd(L2TP, serverIp, L2TP_PORT, secret, username, password,
-                false);
-    }
-
-    public DaemonProxy startPptp(String serverIp, String username,
-            String password, boolean encryption) throws IOException {
-        return startMtpd(PPTP, serverIp, PPTP_PORT, null, username, password,
-                encryption);
-    }
-
-    public DaemonProxy startIpsecForL2tp(String serverIp, String pskKey)
-            throws IOException {
-        DaemonProxy ipsec = startDaemon(IPSEC);
-        ipsec.sendCommand(serverIp, L2TP_PORT, pskKey);
-        return ipsec;
-    }
-
-    public DaemonProxy startIpsecForL2tp(String serverIp, String userKeyKey,
-            String userCertKey, String caCertKey) throws IOException {
-        DaemonProxy ipsec = startDaemon(IPSEC);
-        ipsec.sendCommand(serverIp, L2TP_PORT, userKeyKey, userCertKey,
-                caCertKey);
-        return ipsec;
-    }
-
-    public synchronized void stopAll() {
-        new DaemonProxy(MTPD).stop();
-        new DaemonProxy(IPSEC).stop();
-    }
-
-    public synchronized void closeSockets() {
-        for (DaemonProxy s : mDaemonList) s.closeControlSocket();
-    }
-
-    public synchronized boolean anyDaemonStopped() {
-        for (DaemonProxy s : mDaemonList) {
-            if (s.isStopped()) {
-                Log.w(TAG, "    VPN daemon gone: " + s.getName());
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public synchronized int getSocketError() {
-        for (DaemonProxy s : mDaemonList) {
-            int errCode = getResultFromSocket(s);
-            if (errCode != 0) return errCode;
-        }
-        return 0;
-    }
-
-    private synchronized DaemonProxy startDaemon(String daemonName)
-            throws IOException {
-        DaemonProxy daemon = new DaemonProxy(daemonName);
-        mDaemonList.add(daemon);
-        daemon.start();
-        return daemon;
-    }
-
-    private int getResultFromSocket(DaemonProxy s) {
-        try {
-            return s.getResultFromSocket();
-        } catch (IOException e) {
-            return -1;
-        }
-    }
-
-    private DaemonProxy startMtpd(String protocol,
-            String serverIp, String port, String secret, String username,
-            String password, boolean encryption) throws IOException {
-        ArrayList<String> args = new ArrayList<String>();
-        args.addAll(Arrays.asList(protocol, serverIp, port));
-        if (secret != null) args.add(secret);
-        args.add(PPP_ARGS_SEPARATOR);
-        addPppArguments(args, serverIp, username, password, encryption);
-
-        DaemonProxy mtpd = startDaemon(MTPD);
-        mtpd.sendCommand(args.toArray(new String[args.size()]));
-        return mtpd;
-    }
-
-    private static void addPppArguments(ArrayList<String> args, String serverIp,
-            String username, String password, boolean encryption)
-            throws IOException {
-        args.addAll(Arrays.asList(
-                "linkname", VPN_LINKNAME,
-                "name", username,
-                "password", password,
-                "refuse-eap", "nodefaultroute", "usepeerdns",
-                "idle", "1800",
-                "mtu", "1400",
-                "mru", "1400"));
-        if (encryption) {
-            args.add("+mppe");
-        }
-    }
-}
diff --git a/vpn/java/com/android/server/vpn/VpnService.java b/vpn/java/com/android/server/vpn/VpnService.java
deleted file mode 100644
index 4966c06..0000000
--- a/vpn/java/com/android/server/vpn/VpnService.java
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * Copyright (C) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.vpn;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.net.vpn.VpnManager;
-import android.net.vpn.VpnProfile;
-import android.net.vpn.VpnState;
-import android.os.SystemProperties;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.R;
-
-import java.io.IOException;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.UnknownHostException;
-
-/**
- * The service base class for managing a type of VPN connection.
- */
-abstract class VpnService<E extends VpnProfile> {
-    private static final boolean DBG = true;
-    private static final int NOTIFICATION_ID = 1;
-
-    private static final String DNS1 = "net.dns1";
-    private static final String DNS2 = "net.dns2";
-    private static final String VPN_DNS1 = "vpn.dns1";
-    private static final String VPN_DNS2 = "vpn.dns2";
-    private static final String VPN_STATUS = "vpn.status";
-    private static final String VPN_IS_UP = "ok";
-    private static final String VPN_IS_DOWN = "down";
-
-    private static final String REMOTE_IP = "net.ipremote";
-    private static final String DNS_DOMAIN_SUFFICES = "net.dns.search";
-
-    private final String TAG = VpnService.class.getSimpleName();
-
-    E mProfile;
-    transient Context mContext;
-
-    private VpnState mState = VpnState.IDLE;
-    private Throwable mError;
-
-    // connection settings
-    private String mOriginalDns1;
-    private String mOriginalDns2;
-    private String mOriginalDomainSuffices;
-    private String mLocalIp;
-    private String mLocalIf;
-
-    private long mStartTime; // VPN connection start time
-
-    // for helping managing daemons
-    private VpnDaemons mDaemons = new VpnDaemons();
-
-    // for helping showing, updating notification
-    private transient NotificationHelper mNotification;
-
-    /**
-     * Establishes a VPN connection with the specified username and password.
-     */
-    protected abstract void connect(String serverIp, String username,
-            String password) throws IOException;
-
-    /**
-     * Returns the daemons management class for this service object.
-     */
-    protected VpnDaemons getDaemons() {
-        return mDaemons;
-    }
-
-    /**
-     * Returns the VPN profile associated with the connection.
-     */
-    protected E getProfile() {
-        return mProfile;
-    }
-
-    /**
-     * Returns the IP address of the specified host name.
-     */
-    protected String getIp(String hostName) throws IOException {
-        return InetAddress.getByName(hostName).getHostAddress();
-    }
-
-    void setContext(Context context, E profile) {
-        mProfile = profile;
-        mContext = context;
-        mNotification = new NotificationHelper();
-
-        if (VpnState.CONNECTED.equals(mState)) {
-            Log.i("VpnService", "     recovered: " + mProfile.getName());
-            startConnectivityMonitor();
-        }
-    }
-
-    VpnState getState() {
-        return mState;
-    }
-
-    boolean isIdle() {
-      return (mState == VpnState.IDLE);
-    }
-
-    synchronized boolean onConnect(String username, String password) {
-        try {
-            setState(VpnState.CONNECTING);
-
-            mDaemons.stopAll();
-            String serverIp = getIp(getProfile().getServerName());
-            saveLocalIpAndInterface(serverIp);
-            onBeforeConnect();
-            connect(serverIp, username, password);
-            waitUntilConnectedOrTimedout();
-            return true;
-        } catch (Throwable e) {
-            onError(e);
-            return false;
-        }
-    }
-
-    synchronized void onDisconnect() {
-        try {
-            Log.i(TAG, "disconnecting VPN...");
-            setState(VpnState.DISCONNECTING);
-            mNotification.showDisconnect();
-
-            mDaemons.stopAll();
-        } catch (Throwable e) {
-            Log.e(TAG, "onDisconnect()", e);
-        } finally {
-            onFinalCleanUp();
-        }
-    }
-
-    private void onError(Throwable error) {
-        // error may occur during or after connection setup
-        // and it may be due to one or all services gone
-        if (mError != null) {
-            Log.w(TAG, "   multiple errors occur, record the last one: "
-                    + error);
-        }
-        Log.e(TAG, "onError()", error);
-        mError = error;
-        onDisconnect();
-    }
-
-    private void onError(int errorCode) {
-        onError(new VpnConnectingError(errorCode));
-    }
-
-
-    private void onBeforeConnect() throws IOException {
-        mNotification.disableNotification();
-
-        SystemProperties.set(VPN_DNS1, "");
-        SystemProperties.set(VPN_DNS2, "");
-        SystemProperties.set(VPN_STATUS, VPN_IS_DOWN);
-        if (DBG) {
-            Log.d(TAG, "       VPN UP: " + SystemProperties.get(VPN_STATUS));
-        }
-    }
-
-    private void waitUntilConnectedOrTimedout() throws IOException {
-        sleep(2000); // 2 seconds
-        for (int i = 0; i < 80; i++) {
-            if (mState != VpnState.CONNECTING) {
-                break;
-            } else if (VPN_IS_UP.equals(
-                    SystemProperties.get(VPN_STATUS))) {
-                onConnected();
-                return;
-            } else {
-                int err = mDaemons.getSocketError();
-                if (err != 0) {
-                    onError(err);
-                    return;
-                }
-            }
-            sleep(500); // 0.5 second
-        }
-
-        if (mState == VpnState.CONNECTING) {
-            onError(new IOException("Connecting timed out"));
-        }
-    }
-
-    private synchronized void onConnected() throws IOException {
-        if (DBG) Log.d(TAG, "onConnected()");
-
-        mDaemons.closeSockets();
-        saveOriginalDns();
-        saveAndSetDomainSuffices();
-
-        mStartTime = System.currentTimeMillis();
-
-        setState(VpnState.CONNECTED);
-        setVpnDns();
-
-        startConnectivityMonitor();
-    }
-
-    private synchronized void onFinalCleanUp() {
-        if (DBG) Log.d(TAG, "onFinalCleanUp()");
-
-        if (mState == VpnState.IDLE) return;
-
-        // keep the notification when error occurs
-        if (!anyError()) mNotification.disableNotification();
-
-        restoreOriginalDns();
-        restoreOriginalDomainSuffices();
-        setState(VpnState.IDLE);
-
-        SystemProperties.set(VPN_STATUS, VPN_IS_DOWN);
-    }
-
-    private boolean anyError() {
-        return (mError != null);
-    }
-
-    private void restoreOriginalDns() {
-        // restore only if they are not overridden
-        String vpnDns1 = SystemProperties.get(VPN_DNS1);
-        if (vpnDns1.equals(SystemProperties.get(DNS1))) {
-            Log.i(TAG, String.format("restore original dns prop: %s --> %s",
-                    SystemProperties.get(DNS1), mOriginalDns1));
-            Log.i(TAG, String.format("restore original dns prop: %s --> %s",
-                    SystemProperties.get(DNS2), mOriginalDns2));
-            SystemProperties.set(DNS1, mOriginalDns1);
-            SystemProperties.set(DNS2, mOriginalDns2);
-        }
-    }
-
-    private void saveOriginalDns() {
-        mOriginalDns1 = SystemProperties.get(DNS1);
-        mOriginalDns2 = SystemProperties.get(DNS2);
-        Log.i(TAG, String.format("save original dns prop: %s, %s",
-                mOriginalDns1, mOriginalDns2));
-    }
-
-    private void setVpnDns() {
-        String vpnDns1 = SystemProperties.get(VPN_DNS1);
-        String vpnDns2 = SystemProperties.get(VPN_DNS2);
-        SystemProperties.set(DNS1, vpnDns1);
-        SystemProperties.set(DNS2, vpnDns2);
-        Log.i(TAG, String.format("set vpn dns prop: %s, %s",
-                vpnDns1, vpnDns2));
-    }
-
-    private void saveAndSetDomainSuffices() {
-        mOriginalDomainSuffices = SystemProperties.get(DNS_DOMAIN_SUFFICES);
-        Log.i(TAG, "save original suffices: " + mOriginalDomainSuffices);
-        String list = mProfile.getDomainSuffices();
-        if (!TextUtils.isEmpty(list)) {
-            SystemProperties.set(DNS_DOMAIN_SUFFICES, list);
-        }
-    }
-
-    private void restoreOriginalDomainSuffices() {
-        Log.i(TAG, "restore original suffices --> " + mOriginalDomainSuffices);
-        SystemProperties.set(DNS_DOMAIN_SUFFICES, mOriginalDomainSuffices);
-    }
-
-    private void setState(VpnState newState) {
-        mState = newState;
-        broadcastConnectivity(newState);
-    }
-
-    private void broadcastConnectivity(VpnState s) {
-        VpnManager m = new VpnManager(mContext);
-        Throwable err = mError;
-        if ((s == VpnState.IDLE) && (err != null)) {
-            if (err instanceof UnknownHostException) {
-                m.broadcastConnectivity(mProfile.getName(), s,
-                        VpnManager.VPN_ERROR_UNKNOWN_SERVER);
-            } else if (err instanceof VpnConnectingError) {
-                m.broadcastConnectivity(mProfile.getName(), s,
-                        ((VpnConnectingError) err).getErrorCode());
-            } else if (VPN_IS_UP.equals(SystemProperties.get(VPN_STATUS))) {
-                m.broadcastConnectivity(mProfile.getName(), s,
-                        VpnManager.VPN_ERROR_CONNECTION_LOST);
-            } else {
-                m.broadcastConnectivity(mProfile.getName(), s,
-                        VpnManager.VPN_ERROR_CONNECTION_FAILED);
-            }
-        } else {
-            m.broadcastConnectivity(mProfile.getName(), s);
-        }
-    }
-
-    private void startConnectivityMonitor() {
-        new Thread(new Runnable() {
-            public void run() {
-                Log.i(TAG, "VPN connectivity monitor running");
-                try {
-                    mNotification.update(mStartTime); // to pop up notification
-                    for (int i = 10; ; i--) {
-                        long now = System.currentTimeMillis();
-
-                        boolean heavyCheck = i == 0;
-                        synchronized (VpnService.this) {
-                            if (mState != VpnState.CONNECTED) break;
-                            mNotification.update(now);
-
-                            if (heavyCheck) {
-                                i = 10;
-                                if (checkConnectivity()) checkDns();
-                            }
-                            long t = 1000L - System.currentTimeMillis() + now;
-                            if (t > 100L) VpnService.this.wait(t);
-                        }
-                    }
-                } catch (InterruptedException e) {
-                    onError(e);
-                }
-                Log.i(TAG, "VPN connectivity monitor stopped");
-            }
-        }).start();
-    }
-
-    private void saveLocalIpAndInterface(String serverIp) throws IOException {
-        DatagramSocket s = new DatagramSocket();
-        int port = 80; // arbitrary
-        s.connect(InetAddress.getByName(serverIp), port);
-        InetAddress localIp = s.getLocalAddress();
-        mLocalIp = localIp.getHostAddress();
-        NetworkInterface localIf = NetworkInterface.getByInetAddress(localIp);
-        mLocalIf = (localIf == null) ? null : localIf.getName();
-        if (TextUtils.isEmpty(mLocalIf)) {
-            throw new IOException("Local interface is empty!");
-        }
-        if (DBG) {
-            Log.d(TAG, "  Local IP: " + mLocalIp + ", if: " + mLocalIf);
-        }
-    }
-
-    // returns false if vpn connectivity is broken
-    private boolean checkConnectivity() {
-        if (mDaemons.anyDaemonStopped() || isLocalIpChanged()) {
-            onError(new IOException("Connectivity lost"));
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-    private void checkDns() {
-        String dns1 = SystemProperties.get(DNS1);
-        String vpnDns1 = SystemProperties.get(VPN_DNS1);
-        if (!dns1.equals(vpnDns1) && dns1.equals(mOriginalDns1)) {
-            // dhcp expires?
-            setVpnDns();
-        }
-    }
-
-    private boolean isLocalIpChanged() {
-        try {
-            InetAddress localIp = InetAddress.getByName(mLocalIp);
-            NetworkInterface localIf =
-                    NetworkInterface.getByInetAddress(localIp);
-            if (localIf == null || !mLocalIf.equals(localIf.getName())) {
-                Log.w(TAG, "       local If changed from " + mLocalIf
-                        + " to " + localIf);
-                return true;
-            } else {
-                return false;
-            }
-        } catch (IOException e) {
-            Log.w(TAG, "isLocalIpChanged()", e);
-            return true;
-        }
-    }
-
-    protected void sleep(int ms) {
-        try {
-            Thread.currentThread().sleep(ms);
-        } catch (InterruptedException e) {
-        }
-    }
-
-    // Helper class for showing, updating notification.
-    private class NotificationHelper {
-        private NotificationManager mNotificationManager = (NotificationManager)
-                mContext.getSystemService(Context.NOTIFICATION_SERVICE);
-        private Notification mNotification =
-                new Notification(R.drawable.vpn_connected, null, 0L);
-        private PendingIntent mPendingIntent = PendingIntent.getActivity(
-                mContext, 0,
-                new VpnManager(mContext).createSettingsActivityIntent(), 0);
-        private String mConnectedTitle;
-
-        void update(long now) {
-            Notification n = mNotification;
-            if (now == mStartTime) {
-                // to pop up the notification for the first time
-                n.when = mStartTime;
-                n.tickerText = mConnectedTitle = getNotificationTitle(true);
-            } else {
-                n.tickerText = null;
-            }
-            n.setLatestEventInfo(mContext, mConnectedTitle,
-                    getConnectedNotificationMessage(now),
-                    mPendingIntent);
-            n.flags |= Notification.FLAG_NO_CLEAR;
-            n.flags |= Notification.FLAG_ONGOING_EVENT;
-            enableNotification(n);
-        }
-
-        void showDisconnect() {
-            String title = getNotificationTitle(false);
-            Notification n = new Notification(R.drawable.vpn_disconnected,
-                    title, System.currentTimeMillis());
-            n.setLatestEventInfo(mContext, title,
-                    getDisconnectedNotificationMessage(),
-                    mPendingIntent);
-            n.flags |= Notification.FLAG_AUTO_CANCEL;
-            disableNotification();
-            enableNotification(n);
-        }
-
-        void disableNotification() {
-            mNotificationManager.cancel(NOTIFICATION_ID);
-        }
-
-        private void enableNotification(Notification n) {
-            mNotificationManager.notify(NOTIFICATION_ID, n);
-        }
-
-        private String getNotificationTitle(boolean connected) {
-            String formatString = connected
-                    ? mContext.getString(
-                            R.string.vpn_notification_title_connected)
-                    : mContext.getString(
-                            R.string.vpn_notification_title_disconnected);
-            return String.format(formatString, mProfile.getName());
-        }
-
-        private String getFormattedTime(int duration) {
-            int hours = duration / 3600;
-            StringBuilder sb = new StringBuilder();
-            if (hours > 0) sb.append(hours).append(':');
-            sb.append(String.format("%02d:%02d", (duration % 3600 / 60),
-                    (duration % 60)));
-            return sb.toString();
-        }
-
-        private String getConnectedNotificationMessage(long now) {
-            return getFormattedTime((int) (now - mStartTime) / 1000);
-        }
-
-        private String getDisconnectedNotificationMessage() {
-            return mContext.getString(
-                    R.string.vpn_notification_hint_disconnected);
-        }
-    }
-}
diff --git a/vpn/java/com/android/server/vpn/VpnServiceBinder.java b/vpn/java/com/android/server/vpn/VpnServiceBinder.java
deleted file mode 100644
index c474ff9..0000000
--- a/vpn/java/com/android/server/vpn/VpnServiceBinder.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2009, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.vpn;
-
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.net.vpn.IVpnService;
-import android.net.vpn.L2tpIpsecProfile;
-import android.net.vpn.L2tpIpsecPskProfile;
-import android.net.vpn.L2tpProfile;
-import android.net.vpn.PptpProfile;
-import android.net.vpn.VpnManager;
-import android.net.vpn.VpnProfile;
-import android.net.vpn.VpnState;
-import android.util.Log;
-
-/**
- * The service class for managing a VPN connection. It implements the
- * {@link IVpnService} binder interface.
- */
-public class VpnServiceBinder extends IVpnService.Stub {
-    private static final String TAG = VpnServiceBinder.class.getSimpleName();
-    private static final boolean DBG = true;
-
-    // The actual implementation is delegated to the VpnService class.
-    private VpnService<? extends VpnProfile> mService;
-
-    private Context mContext;
-
-    public VpnServiceBinder(Context context) {
-        mContext = context;
-    }
-
-    @Override
-    public synchronized boolean connect(VpnProfile p, final String username,
-            final String password) {
-        if ((mService != null) && !mService.isIdle()) return false;
-        final VpnService s = mService = createService(p);
-
-        new Thread(new Runnable() {
-            public void run() {
-                s.onConnect(username, password);
-            }
-        }).start();
-        return true;
-    }
-
-    @Override
-    public synchronized void disconnect() {
-        if (mService == null) return;
-        final VpnService s = mService;
-        mService = null;
-
-        new Thread(new Runnable() {
-            public void run() {
-                s.onDisconnect();
-            }
-        }).start();
-    }
-
-    @Override
-    public synchronized String getState(VpnProfile p) {
-        if ((mService == null)
-                || (!p.getName().equals(mService.mProfile.getName()))) {
-            return VpnState.IDLE.toString();
-        } else {
-            return mService.getState().toString();
-        }
-    }
-
-    @Override
-    public synchronized boolean isIdle() {
-        return (mService == null || mService.isIdle());
-    }
-
-    private VpnService<? extends VpnProfile> createService(VpnProfile p) {
-        switch (p.getType()) {
-            case L2TP:
-                L2tpService l2tp = new L2tpService();
-                l2tp.setContext(mContext, (L2tpProfile) p);
-                return l2tp;
-
-            case PPTP:
-                PptpService pptp = new PptpService();
-                pptp.setContext(mContext, (PptpProfile) p);
-                return pptp;
-
-            case L2TP_IPSEC_PSK:
-                L2tpIpsecPskService psk = new L2tpIpsecPskService();
-                psk.setContext(mContext, (L2tpIpsecPskProfile) p);
-                return psk;
-
-            case L2TP_IPSEC:
-                L2tpIpsecService l2tpIpsec = new L2tpIpsecService();
-                l2tpIpsec.setContext(mContext, (L2tpIpsecProfile) p);
-                return l2tpIpsec;
-
-            default:
-                return null;
-        }
-    }
-}
diff --git a/vpn/tests/vpntests/Android.mk b/vpn/tests/vpntests/Android.mk
deleted file mode 100644
index a19fb56..0000000
--- a/vpn/tests/vpntests/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-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 := FrameworksVpnTests
-
-include $(BUILD_PACKAGE)
-
diff --git a/vpn/tests/vpntests/AndroidManifest.xml b/vpn/tests/vpntests/AndroidManifest.xml
deleted file mode 100644
index d8405f6..0000000
--- a/vpn/tests/vpntests/AndroidManifest.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.frameworks.vpntests">
-    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
-    <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.READ_CONTACTS" />
-    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
-    <uses-permission android:name="android.permission.WAKE_LOCK" />
-    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
-    <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
-    <uses-permission android:name="android.permission.BROADCAST_STICKY" />
-    
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation
-    	android:name="android.test.InstrumentationTestRunner"
-    	android:targetPackage="com.android.frameworks.vpntests"
-    	android:label="Frameworks VPN Tests" />
-</manifest>
diff --git a/vpn/tests/vpntests/src/android/net/vpn/VpnTest.java b/vpn/tests/vpntests/src/android/net/vpn/VpnTest.java
deleted file mode 100755
index 46a57d3..0000000
--- a/vpn/tests/vpntests/src/android/net/vpn/VpnTest.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2009 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.vpn;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.net.vpn.L2tpProfile;
-import android.net.vpn.L2tpIpsecProfile;
-import android.net.vpn.L2tpIpsecPskProfile;
-import android.net.vpn.PptpProfile;
-import android.net.vpn.VpnManager;
-import android.net.vpn.VpnProfile;
-import android.net.vpn.VpnState;
-import android.net.vpn.VpnType;
-import android.os.ConditionVariable;
-import android.os.Parcel;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.text.TextUtils;
-
-/**
- * Unit test class to test VPN api
- * Use the below command to run the vpn unit test only
- * runtest vpntest or
- * adb shell am instrument -e class 'com.android.unit_tests.VpnTest'
- *   -w com.android.unit_tests/android.test.InstrumentationTestRunner
- */
-public class VpnTest extends AndroidTestCase {
-    private static final String NAME = "a name";
-    private static final String SERVER_NAME = "a server name";
-    private static final String ID = "some id";
-    private static final String SUFFICES = "some suffices";
-    private static final String ROUTES = "some routes";
-    private static final String SAVED_NAME = "some name";
-
-    @Override
-    public void setUp() {
-    }
-
-    @Override
-    public void tearDown() {
-    }
-
-    @SmallTest
-    public void testVpnType() {
-        testVpnType(VpnType.L2TP);
-        testVpnType(VpnType.L2TP_IPSEC);
-        testVpnType(VpnType.L2TP_IPSEC_PSK);
-        testVpnType(VpnType.PPTP);
-    }
-
-    @SmallTest
-    public void testVpnProfile() {
-        VpnState state = VpnState.CONNECTING;
-        testVpnProfile(createTestProfile(state), state);
-    }
-
-    @SmallTest
-    public void testGetType() {
-        assertEquals(VpnType.L2TP, new L2tpProfile().getType());
-        assertEquals(VpnType.L2TP_IPSEC, new L2tpIpsecProfile().getType());
-        assertEquals(VpnType.L2TP_IPSEC_PSK, 
-                new L2tpIpsecPskProfile().getType());
-        assertEquals(VpnType.PPTP, new PptpProfile().getType());
-    }
-
-    @SmallTest
-    public void testVpnTypes() {
-        assertTrue(VpnManager.getSupportedVpnTypes().length > 0);
-    }
-
-    @SmallTest
-    public void testGetTypeFromManager() {
-        VpnManager m = new VpnManager(getContext());
-        VpnType[] types = VpnManager.getSupportedVpnTypes();
-        for (VpnType t : types) {
-            assertEquals(t, m.createVpnProfile(t).getType());
-        }
-    }
-
-    @SmallTest
-    public void testParcelable() {
-        VpnProfile p = createTestProfile(VpnState.CONNECTED);
-        Parcel parcel = Parcel.obtain();
-        p.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-
-        // VpnState is transient and not saved in the parcel
-        testVpnProfile(VpnProfile.CREATOR.createFromParcel(parcel), null);
-    }
-
-    @SmallTest
-    public void testReceiver() {
-        final String profileName = "whatever";
-        final VpnState state = VpnState.DISCONNECTING;
-        final ConditionVariable cv = new ConditionVariable();
-        cv.close();
-        BroadcastReceiver r = new BroadcastReceiver() {
-            public void onReceive(Context c, Intent i) {
-                assertEquals(profileName,
-                        i.getStringExtra(VpnManager.BROADCAST_PROFILE_NAME));
-                assertEquals(state, i.getSerializableExtra(
-                        VpnManager.BROADCAST_CONNECTION_STATE));
-                cv.open();
-            }
-        };
-
-        VpnManager m = new VpnManager(getContext());
-        m.registerConnectivityReceiver(r);
-        m.broadcastConnectivity(profileName, state);
-
-        // fail it if onReceive() doesn't get executed in 5 sec
-        assertTrue(cv.block(5000));
-    }
-
-    private void testVpnType(VpnType type) {
-        assertFalse(TextUtils.isEmpty(type.getDisplayName()));
-        assertNotNull(type.getProfileClass());
-    }
-
-    private VpnProfile createTestProfile(VpnState state) {
-        VpnProfile p = new L2tpProfile();
-        p.setName(NAME);
-        p.setServerName(SERVER_NAME);
-        p.setId(ID);
-        p.setDomainSuffices(SUFFICES);
-        p.setRouteList(ROUTES);
-        p.setSavedUsername(SAVED_NAME);
-        p.setState(state);
-        return p;
-    }
-
-    private void testVpnProfile(VpnProfile p, VpnState state) {
-        assertEquals(NAME, p.getName());
-        assertEquals(SERVER_NAME, p.getServerName());
-        assertEquals(ID, p.getId());
-        assertEquals(SUFFICES, p.getDomainSuffices());
-        assertEquals(ROUTES, p.getRouteList());
-        assertEquals(SAVED_NAME, p.getSavedUsername());
-        if (state != null) assertEquals(state, p.getState());
-    }
-}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 2a033d1..8c28319 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -2085,9 +2085,9 @@
                         transitionTo(mDriverLoadedState);
                         sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
                     } else {
-                        mSupplicantRestartCount = 0;
                         Log.e(TAG, "Failed " + mSupplicantRestartCount +
                                 " times to start supplicant, unload driver");
+                        mSupplicantRestartCount = 0;
                         transitionTo(mDriverLoadedState);
                         sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));
                     }
diff --git a/wifi/java/android/net/wifi/WifiWatchdogService.java b/wifi/java/android/net/wifi/WifiWatchdogService.java
new file mode 100644
index 0000000..bce4b3a
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiWatchdogService.java
@@ -0,0 +1,765 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.ConnectivityManager;
+import android.net.DnsPinger;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Scanner;
+
+/**
+ * {@link WifiWatchdogService} monitors the initial connection to a Wi-Fi
+ * network with multiple access points. After the framework successfully
+ * connects to an access point, the watchdog verifies connectivity by 'pinging'
+ * the configured DNS server using {@link DnsPinger}.
+ * <p>
+ * On DNS check failure, the BSSID is blacklisted if it is reasonably likely
+ * that another AP might have internet access; otherwise the SSID is disabled.
+ * <p>
+ * On DNS success, the WatchdogService initiates a walled garden check via an
+ * http get. A browser windows is activated if a walled garden is detected.
+ * 
+ * @hide
+ */
+public class WifiWatchdogService {
+
+    private static final String WWS_TAG = "WifiWatchdogService";
+
+    private static final boolean VDBG = true;
+    private static final boolean DBG = true;
+
+    // Used for verbose logging
+    private String mDNSCheckLogStr;
+
+    private Context mContext;
+    private ContentResolver mContentResolver;
+    private WifiManager mWifiManager;
+
+    private WifiWatchdogHandler mHandler;
+
+    private DnsPinger mDnsPinger;
+
+    private IntentFilter mIntentFilter;
+    private BroadcastReceiver mBroadcastReceiver;
+    private boolean mBroadcastsEnabled;
+
+    private static final int WIFI_SIGNAL_LEVELS = 4;
+
+    /**
+     * Low signal is defined as less than or equal to cut off
+     */
+    private static final int LOW_SIGNAL_CUTOFF = 0;
+
+    private static final long MIN_LOW_SIGNAL_CHECK_INTERVAL = 2 * 60 * 1000;
+    private static final long MIN_SINGLE_DNS_CHECK_INTERVAL = 10 * 60 * 1000;
+    private static final long MIN_WALLED_GARDEN_INTERVAL = 15 * 60 * 1000;
+
+    private static final int MAX_CHECKS_PER_SSID = 9;
+    private static final int NUM_DNS_PINGS = 7;
+    private static double MIN_RESPONSE_RATE = 0.50;
+
+    // TODO : Adjust multiple DNS downward to 250 on repeated failure
+    // private static final int MULTI_DNS_PING_TIMEOUT_MS = 250;
+
+    private static final int DNS_PING_TIMEOUT_MS = 800;
+    private static final long DNS_PING_INTERVAL = 250;
+
+    private static final long BLACKLIST_FOLLOWUP_INTERVAL = 15 * 1000;
+
+    private Status mStatus = new Status();
+
+    private static class Status {
+        String bssid = "";
+        String ssid = "";
+
+        HashSet<String> allBssids = new HashSet<String>();
+        int numFullDNSchecks = 0;
+
+        long lastSingleCheckTime = -24 * 60 * 60 * 1000;
+        long lastWalledGardenCheckTime = -24 * 60 * 60 * 1000;
+
+        WatchdogState state = WatchdogState.INACTIVE;
+
+        // Info for dns check
+        int dnsCheckTries = 0;
+        int dnsCheckSuccesses = 0;
+
+        public int signal = -200;
+
+    }
+
+    private enum WatchdogState {
+        /**
+         * Full DNS check in progress
+         */
+        DNS_FULL_CHECK,
+
+        /**
+         * Walled Garden detected, will pop up browser next round.
+         */
+        WALLED_GARDEN_DETECTED,
+
+        /**
+         * DNS failed, will blacklist/disable AP next round
+         */
+        DNS_CHECK_FAILURE,
+
+        /**
+         * Online or displaying walled garden auth page
+         */
+        CHECKS_COMPLETE,
+
+        /**
+         * Watchdog idle, network has been blacklisted or received disconnect
+         * msg
+         */
+        INACTIVE,
+
+        BLACKLISTED_AP
+    }
+
+    public WifiWatchdogService(Context context) {
+        mContext = context;
+        mContentResolver = context.getContentResolver();
+        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        mDnsPinger = new DnsPinger("WifiWatchdogServer.DnsPinger", context,
+                ConnectivityManager.TYPE_WIFI);
+
+        HandlerThread handlerThread = new HandlerThread("WifiWatchdogServiceThread");
+        handlerThread.start();
+        mHandler = new WifiWatchdogHandler(handlerThread.getLooper());
+
+        setupNetworkReceiver();
+
+        // The content observer to listen needs a handler, which createThread
+        // creates
+        registerForSettingsChanges();
+
+        // Start things off
+        if (isWatchdogEnabled()) {
+            mHandler.sendEmptyMessage(WifiWatchdogHandler.MESSAGE_CONTEXT_EVENT);
+        }
+    }
+
+    /**
+     *
+     */
+    private void setupNetworkReceiver() {
+        mBroadcastReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                String action = intent.getAction();
+                if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+                    mHandler.sendMessage(mHandler.obtainMessage(
+                            WifiWatchdogHandler.MESSAGE_NETWORK_EVENT,
+                            intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO)
+                            ));
+                } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
+                    mHandler.sendEmptyMessage(WifiWatchdogHandler.RSSI_CHANGE_EVENT);
+                } else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+                    mHandler.sendEmptyMessage(WifiWatchdogHandler.SCAN_RESULTS_AVAILABLE);
+                } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+                    mHandler.sendMessage(mHandler.obtainMessage(
+                            WifiWatchdogHandler.WIFI_STATE_CHANGE,
+                            intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 4)));
+                }
+            }
+        };
+
+        mIntentFilter = new IntentFilter();
+        mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        mIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
+        mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+    }
+
+    /**
+     * Observes the watchdog on/off setting, and takes action when changed.
+     */
+    private void registerForSettingsChanges() {
+        ContentObserver contentObserver = new ContentObserver(mHandler) {
+            @Override
+            public void onChange(boolean selfChange) {
+                mHandler.sendEmptyMessage((WifiWatchdogHandler.MESSAGE_CONTEXT_EVENT));
+            }
+        };
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON),
+                false, contentObserver);
+    }
+
+    private void handleNewConnection() {
+        WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+        String newSsid = wifiInfo.getSSID();
+        String newBssid = wifiInfo.getBSSID();
+
+        if (VDBG) {
+            Slog.v(WWS_TAG, String.format("handleConnected:: old (%s, %s) ==> new (%s, %s)",
+                    mStatus.ssid, mStatus.bssid, newSsid, newBssid));
+        }
+
+        if (TextUtils.isEmpty(newSsid) || TextUtils.isEmpty(newBssid)) {
+            return;
+        }
+
+        if (!TextUtils.equals(mStatus.ssid, newSsid)) {
+            mStatus = new Status();
+            mStatus.ssid = newSsid;
+        }
+
+        mStatus.bssid = newBssid;
+        mStatus.allBssids.add(newBssid);
+        mStatus.signal = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), WIFI_SIGNAL_LEVELS);
+
+        initDnsFullCheck();
+    }
+
+    public void updateRssi() {
+        WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+        if (!TextUtils.equals(mStatus.ssid, wifiInfo.getSSID()) ||
+                !TextUtils.equals(mStatus.bssid, wifiInfo.getBSSID())) {
+            return;
+        }
+
+        mStatus.signal = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), WIFI_SIGNAL_LEVELS);
+    }
+
+    /**
+     * Single step in state machine
+     */
+    private void handleStateStep() {
+        // Slog.v(WWS_TAG, "handleStateStep:: " + mStatus.state);
+
+        switch (mStatus.state) {
+            case DNS_FULL_CHECK:
+                if (VDBG) {
+                    Slog.v(WWS_TAG, "DNS_FULL_CHECK: " + mDNSCheckLogStr);
+                }
+
+                long pingResponseTime = mDnsPinger.pingDns(mDnsPinger.getDns(),
+                        DNS_PING_TIMEOUT_MS);
+
+                mStatus.dnsCheckTries++;
+                if (pingResponseTime >= 0)
+                    mStatus.dnsCheckSuccesses++;
+
+                if (DBG) {
+                    if (pingResponseTime >= 0) {
+                        mDNSCheckLogStr += " | " + pingResponseTime;
+                    } else {
+                        mDNSCheckLogStr += " | " + "x";
+                    }
+                }
+
+                switch (currentDnsCheckStatus()) {
+                    case SUCCESS:
+                        if (DBG) {
+                            Slog.d(WWS_TAG, mDNSCheckLogStr + " -- Success");
+                        }
+                        doWalledGardenCheck();
+                        break;
+                    case FAILURE:
+                        if (DBG) {
+                            Slog.d(WWS_TAG, mDNSCheckLogStr + " -- Failure");
+                        }
+                        mStatus.state = WatchdogState.DNS_CHECK_FAILURE;
+                        break;
+                    case INCOMPLETE:
+                        // Taking no action
+                        break;
+                }
+                break;
+            case DNS_CHECK_FAILURE:
+                WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+                if (!mStatus.ssid.equals(wifiInfo.getSSID()) ||
+                        !mStatus.bssid.equals(wifiInfo.getBSSID())) {
+                    Slog.i(WWS_TAG, "handleState DNS_CHECK_FAILURE:: network has changed!");
+                    mStatus.state = WatchdogState.INACTIVE;
+                    break;
+                }
+
+                if (mStatus.numFullDNSchecks >= mStatus.allBssids.size() ||
+                        mStatus.numFullDNSchecks >= MAX_CHECKS_PER_SSID) {
+                    disableAP(wifiInfo);
+                } else {
+                    blacklistAP();
+                }
+                break;
+            case WALLED_GARDEN_DETECTED:
+                popUpBrowser();
+                mStatus.state = WatchdogState.CHECKS_COMPLETE;
+                break;
+            case BLACKLISTED_AP:
+                WifiInfo wifiInfo2 = mWifiManager.getConnectionInfo();
+                if (wifiInfo2.getSupplicantState() != SupplicantState.COMPLETED) {
+                    Slog.d(WWS_TAG,
+                            "handleState::BlacklistedAP - offline, but didn't get disconnect!");
+                    mStatus.state = WatchdogState.INACTIVE;
+                    break;
+                }
+                if (mStatus.bssid.equals(wifiInfo2.getBSSID())) {
+                    Slog.d(WWS_TAG, "handleState::BlacklistedAP - connected to same bssid");
+                    if (!handleSingleDnsCheck()) {
+                        disableAP(wifiInfo2);
+                        break;
+                    }
+                }
+
+                Slog.d(WWS_TAG, "handleState::BlacklistedAP - Simiulating a new connection");
+                handleNewConnection();
+                break;
+        }
+    }
+
+    private void doWalledGardenCheck() {
+        if (!isWalledGardenTestEnabled()) {
+            if (VDBG)
+                Slog.v(WWS_TAG, "Skipping walled garden check - disabled");
+            mStatus.state = WatchdogState.CHECKS_COMPLETE;
+            return;
+        }
+        long waitTime = waitTime(MIN_WALLED_GARDEN_INTERVAL,
+                mStatus.lastWalledGardenCheckTime);
+        if (waitTime > 0) {
+            if (VDBG) {
+                Slog.v(WWS_TAG, "Skipping walled garden check - wait " +
+                        waitTime + " ms.");
+            }
+            mStatus.state = WatchdogState.CHECKS_COMPLETE;
+            return;
+        }
+
+        mStatus.lastWalledGardenCheckTime = SystemClock.elapsedRealtime();
+        if (isWalledGardenConnection()) {
+            if (DBG)
+                Slog.d(WWS_TAG,
+                        "Walled garden test complete - walled garden detected");
+            mStatus.state = WatchdogState.WALLED_GARDEN_DETECTED;
+        } else {
+            if (DBG)
+                Slog.d(WWS_TAG, "Walled garden test complete - online");
+            mStatus.state = WatchdogState.CHECKS_COMPLETE;
+        }
+    }
+
+    private boolean handleSingleDnsCheck() {
+        mStatus.lastSingleCheckTime = SystemClock.elapsedRealtime();
+        long responseTime = mDnsPinger.pingDns(mDnsPinger.getDns(),
+                DNS_PING_TIMEOUT_MS);
+        if (DBG) {
+            Slog.d(WWS_TAG, "Ran a single DNS ping. Response time: " + responseTime);
+        }
+        if (responseTime < 0) {
+            return false;
+        }
+        return true;
+
+    }
+
+    /**
+     * @return Delay in MS before next single DNS check can proceed.
+     */
+    private long timeToNextScheduledDNSCheck() {
+        if (mStatus.signal > LOW_SIGNAL_CUTOFF) {
+            return waitTime(MIN_SINGLE_DNS_CHECK_INTERVAL, mStatus.lastSingleCheckTime);
+        } else {
+            return waitTime(MIN_LOW_SIGNAL_CHECK_INTERVAL, mStatus.lastSingleCheckTime);
+        }
+    }
+
+    /**
+     * Helper to return wait time left given a min interval and last run
+     * 
+     * @param interval minimum wait interval
+     * @param lastTime last time action was performed in
+     *            SystemClock.elapsedRealtime()
+     * @return non negative time to wait
+     */
+    private static long waitTime(long interval, long lastTime) {
+        long wait = interval + lastTime - SystemClock.elapsedRealtime();
+        return wait > 0 ? wait : 0;
+    }
+
+    private void popUpBrowser() {
+        Uri uri = Uri.parse("http://www.google.com");
+        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+        intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
+                Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(intent);
+    }
+
+    private void disableAP(WifiInfo info) {
+        // TODO : Unban networks if they had low signal ?
+        Slog.i(WWS_TAG, String.format("Disabling current SSID, %s [bssid %s].  " +
+                "numChecks %d, numAPs %d", mStatus.ssid, mStatus.bssid,
+                mStatus.numFullDNSchecks, mStatus.allBssids.size()));
+        mWifiManager.disableNetwork(info.getNetworkId());
+        mStatus.state = WatchdogState.INACTIVE;
+    }
+
+    private void blacklistAP() {
+        Slog.i(WWS_TAG, String.format("Blacklisting current BSSID %s [ssid %s].  " +
+                "numChecks %d, numAPs %d", mStatus.bssid, mStatus.ssid,
+                mStatus.numFullDNSchecks, mStatus.allBssids.size()));
+
+        mWifiManager.addToBlacklist(mStatus.bssid);
+        mWifiManager.reassociate();
+        mStatus.state = WatchdogState.BLACKLISTED_AP;
+    }
+
+    /**
+     * Checks the scan for new BBIDs using current mSsid
+     */
+    private void updateBssids() {
+        String curSsid = mStatus.ssid;
+        HashSet<String> bssids = mStatus.allBssids;
+        List<ScanResult> results = mWifiManager.getScanResults();
+        int oldNumBssids = bssids.size();
+
+        if (results == null) {
+            if (VDBG) {
+                Slog.v(WWS_TAG, "updateBssids: Got null scan results!");
+            }
+            return;
+        }
+
+        for (ScanResult result : results) {
+            if (result != null && curSsid.equals(result.SSID))
+                bssids.add(result.BSSID);
+        }
+
+        // if (VDBG && bssids.size() - oldNumBssids > 0) {
+        // Slog.v(WWS_TAG,
+        // String.format("updateBssids:: Found %d new APs (total %d) on SSID %s",
+        // bssids.size() - oldNumBssids, bssids.size(), curSsid));
+        // }
+    }
+
+    enum DnsCheckStatus {
+        SUCCESS,
+        FAILURE,
+        INCOMPLETE
+    }
+
+    /**
+     * Computes the current results of the dns check, ends early if outcome is
+     * assured.
+     */
+    private DnsCheckStatus currentDnsCheckStatus() {
+        /**
+         * After a full ping count, if we have more responses than this cutoff,
+         * the outcome is success; else it is 'failure'.
+         */
+        double pingResponseCutoff = MIN_RESPONSE_RATE * NUM_DNS_PINGS;
+        int remainingChecks = NUM_DNS_PINGS - mStatus.dnsCheckTries;
+
+        /**
+         * Our final success count will be at least this big, so we're
+         * guaranteed to succeed.
+         */
+        if (mStatus.dnsCheckSuccesses >= pingResponseCutoff) {
+            return DnsCheckStatus.SUCCESS;
+        }
+
+        /**
+         * Our final count will be at most the current count plus the remaining
+         * pings - we're guaranteed to fail.
+         */
+        if (remainingChecks + mStatus.dnsCheckSuccesses < pingResponseCutoff) {
+            return DnsCheckStatus.FAILURE;
+        }
+
+        return DnsCheckStatus.INCOMPLETE;
+    }
+
+    private void initDnsFullCheck() {
+        if (DBG) {
+            Slog.d(WWS_TAG, "Starting DNS pings at " + SystemClock.elapsedRealtime());
+        }
+        mStatus.numFullDNSchecks++;
+        mStatus.dnsCheckSuccesses = 0;
+        mStatus.dnsCheckTries = 0;
+        mStatus.state = WatchdogState.DNS_FULL_CHECK;
+
+        if (DBG) {
+            mDNSCheckLogStr = String.format("Dns Check %d.  Pinging %s on ssid [%s]: ",
+                    mStatus.numFullDNSchecks, mDnsPinger.getDns(),
+                    mStatus.ssid);
+        }
+    }
+
+    /**
+     * DNS based detection techniques do not work at all hotspots. The one sure
+     * way to check a walled garden is to see if a URL fetch on a known address
+     * fetches the data we expect
+     */
+    private boolean isWalledGardenConnection() {
+        InputStream in = null;
+        HttpURLConnection urlConnection = null;
+        try {
+            URL url = new URL(getWalledGardenUrl());
+            urlConnection = (HttpURLConnection) url.openConnection();
+            in = new BufferedInputStream(urlConnection.getInputStream());
+            Scanner scanner = new Scanner(in);
+            if (scanner.findInLine(getWalledGardenPattern()) != null) {
+                return false;
+            } else {
+                return true;
+            }
+        } catch (IOException e) {
+            return false;
+        } finally {
+            if (in != null) {
+                try {
+                    in.close();
+                } catch (IOException e) {
+                }
+            }
+            if (urlConnection != null)
+                urlConnection.disconnect();
+        }
+    }
+
+    /**
+     * There is little logic inside this class, instead methods of the form
+     * "handle___" are called in the main {@link WifiWatchdogService}.
+     */
+    private class WifiWatchdogHandler extends Handler {
+        /**
+         * Major network event, object is NetworkInfo
+         */
+        static final int MESSAGE_NETWORK_EVENT = 1;
+        /**
+         * Change in settings, no object
+         */
+        static final int MESSAGE_CONTEXT_EVENT = 2;
+
+        /**
+         * Change in signal strength
+         */
+        static final int RSSI_CHANGE_EVENT = 3;
+        static final int SCAN_RESULTS_AVAILABLE = 4;
+
+        static final int WIFI_STATE_CHANGE = 5;
+
+        /**
+         * Single step of state machine. One DNS check, or one WalledGarden
+         * check, or one external action. We separate out external actions to
+         * increase chance of detecting that a check failure is caused by change
+         * in network status. Messages should have an arg1 which to sync status
+         * messages.
+         */
+        static final int CHECK_SEQUENCE_STEP = 10;
+        static final int SINGLE_DNS_CHECK = 11;
+
+        /**
+         * @param looper
+         */
+        public WifiWatchdogHandler(Looper looper) {
+            super(looper);
+        }
+
+        boolean singleCheckQueued = false;
+        long queuedSingleDnsCheckArrival;
+
+        /**
+         * Sends a singleDnsCheck message with shortest time - guards against
+         * multiple.
+         */
+        private boolean queueSingleDnsCheck() {
+            long delay = timeToNextScheduledDNSCheck();
+            long newArrival = delay + SystemClock.elapsedRealtime();
+            if (singleCheckQueued && queuedSingleDnsCheckArrival <= newArrival)
+                return true;
+            queuedSingleDnsCheckArrival = newArrival;
+            singleCheckQueued = true;
+            removeMessages(SINGLE_DNS_CHECK);
+            return sendMessageDelayed(obtainMessage(SINGLE_DNS_CHECK), delay);
+        }
+
+        boolean checkSequenceQueued = false;
+        long queuedCheckSequenceArrival;
+
+        /**
+         * Sends a state_machine_step message if the delay requested is lower
+         * than the current delay.
+         */
+        private boolean sendCheckSequenceStep(long delay) {
+            long newArrival = delay + SystemClock.elapsedRealtime();
+            if (checkSequenceQueued && queuedCheckSequenceArrival <= newArrival)
+                return true;
+            queuedCheckSequenceArrival = newArrival;
+            checkSequenceQueued = true;
+            removeMessages(CHECK_SEQUENCE_STEP);
+            return sendMessageDelayed(obtainMessage(CHECK_SEQUENCE_STEP), delay);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case CHECK_SEQUENCE_STEP:
+                    checkSequenceQueued = false;
+                    handleStateStep();
+                    if (mStatus.state == WatchdogState.CHECKS_COMPLETE) {
+                        queueSingleDnsCheck();
+                    } else if (mStatus.state == WatchdogState.DNS_FULL_CHECK) {
+                        sendCheckSequenceStep(DNS_PING_INTERVAL);
+                    } else if (mStatus.state == WatchdogState.BLACKLISTED_AP) {
+                        sendCheckSequenceStep(BLACKLIST_FOLLOWUP_INTERVAL);
+                    } else if (mStatus.state != WatchdogState.INACTIVE) {
+                        sendCheckSequenceStep(0);
+                    }
+                    return;
+                case MESSAGE_NETWORK_EVENT:
+                    if (!mBroadcastsEnabled) {
+                        Slog.e(WWS_TAG,
+                                "MessageNetworkEvent - WatchdogService not enabled... returning");
+                        return;
+                    }
+                    NetworkInfo info = (NetworkInfo) msg.obj;
+                    switch (info.getState()) {
+                        case DISCONNECTED:
+                            mStatus.state = WatchdogState.INACTIVE;
+                            return;
+                        case CONNECTED:
+                            handleNewConnection();
+                            sendCheckSequenceStep(0);
+                    }
+                    return;
+                case SINGLE_DNS_CHECK:
+                    singleCheckQueued = false;
+                    if (mStatus.state != WatchdogState.CHECKS_COMPLETE) {
+                        Slog.d(WWS_TAG, "Single check returning, curState: " + mStatus.state);
+                        break;
+                    }
+
+                    if (!handleSingleDnsCheck()) {
+                        initDnsFullCheck();
+                        sendCheckSequenceStep(0);
+                    } else {
+                        queueSingleDnsCheck();
+                    }
+
+                    break;
+                case RSSI_CHANGE_EVENT:
+                    updateRssi();
+                    if (mStatus.state == WatchdogState.CHECKS_COMPLETE)
+                        queueSingleDnsCheck();
+                    break;
+                case SCAN_RESULTS_AVAILABLE:
+                    updateBssids();
+                    break;
+                case WIFI_STATE_CHANGE:
+                    if ((Integer) msg.obj == WifiManager.WIFI_STATE_DISABLING) {
+                        Slog.i(WWS_TAG, "WifiStateDisabling -- Resetting WatchdogState");
+                        mStatus = new Status();
+                    }
+                    break;
+                case MESSAGE_CONTEXT_EVENT:
+                    if (isWatchdogEnabled() && !mBroadcastsEnabled) {
+                        mContext.registerReceiver(mBroadcastReceiver, mIntentFilter);
+                        mBroadcastsEnabled = true;
+                        Slog.i(WWS_TAG, "WifiWatchdogService enabled");
+                    } else if (!isWatchdogEnabled() && mBroadcastsEnabled) {
+                        mContext.unregisterReceiver(mBroadcastReceiver);
+                        removeMessages(SINGLE_DNS_CHECK);
+                        removeMessages(CHECK_SEQUENCE_STEP);
+                        mBroadcastsEnabled = false;
+                        Slog.i(WWS_TAG, "WifiWatchdogService disabled");
+                    }
+                    break;
+            }
+        }
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.print("WatchdogStatus: ");
+        pw.print("State " + mStatus.state);
+        pw.println(", network [" + mStatus.ssid + ", " + mStatus.bssid + "]");
+        pw.print("checkCount " + mStatus.numFullDNSchecks);
+        pw.println(", bssids: " + mStatus.allBssids);
+        pw.print(", hasCheckMessages? " +
+                mHandler.hasMessages(WifiWatchdogHandler.CHECK_SEQUENCE_STEP));
+        pw.println(" hasSingleCheckMessages? " +
+                mHandler.hasMessages(WifiWatchdogHandler.SINGLE_DNS_CHECK));
+        pw.println("DNS check log str: " + mDNSCheckLogStr);
+        pw.println("lastSingleCheck: " + mStatus.lastSingleCheckTime);
+    }
+
+    /**
+     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED
+     */
+    private Boolean isWalledGardenTestEnabled() {
+        return Settings.Secure.getInt(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, 1) == 1;
+    }
+
+    /**
+     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_URL
+     */
+    private String getWalledGardenUrl() {
+        String url = Settings.Secure.getString(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL);
+        if (TextUtils.isEmpty(url))
+            return "http://www.google.com/";
+        return url;
+    }
+
+    /**
+     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_PATTERN
+     */
+    private String getWalledGardenPattern() {
+        String pattern = Settings.Secure.getString(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN);
+        if (TextUtils.isEmpty(pattern))
+            return "<title>.*Google.*</title>";
+        return pattern;
+    }
+
+    /**
+     * @see android.provider.Settings.Secure#WIFI_WATCHDOG_ON
+     */
+    private boolean isWatchdogEnabled() {
+        return Settings.Secure.getInt(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_ON, 1) == 1;
+    }
+}